[
  {
    "path": ".cspell.jsonc",
    "content": "// The .jsonc extension allows free use of comments and trailing commas.\n// The file is named with a dot in front to discourage frequent editing —\n// target dictionaries are located in the resources/dictionaries/ directory.\n{\n  \"$schema\": \"https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json\",\n  \"version\": \"0.2\",\n  \"language\": \"en-US\",\n  \"dictionaryDefinitions\": [\n    {\n      // Allowed words\n      \"name\": \"main-list\",\n      \"path\": \"resources/dictionaries/custom.txt\",\n      \"addWords\": true,\n    },\n    {\n      // Banned words with no clear or correct replacements\n      // For a few words with those, see the flagWords property later in this file\n      \"name\": \"deny-list\",\n      \"path\": \"resources/dictionaries/ban.txt\"\n    },\n    {\n      \"name\": \"2lw-deny-list\",\n      \"path\": \"resources/dictionaries/two-letter-words-ban.txt\"\n    },\n    {\n      \"name\": \"tvm-instructions\",\n      \"path\": \"resources/dictionaries/tvm-instructions.txt\"\n    }\n  ],\n  \"dictionaries\": [\n    \"main-list\",\n    \"deny-list\",\n    \"2lw-deny-list\",\n    \"tvm-instructions\",\n  ],\n  \"useGitignore\": true,\n  \"files\": [\n    \"**/*.{md,mdx}\",\n    \"**/*.{js,jsx,mjs}\",\n  ],\n  \"minWordLength\": 3,\n  \"overrides\": [\n    // Enable case sensitivity for Markdown and MDX files only\n    {\n      \"filename\": \"**/*.{md,mdx}\",\n      \"caseSensitive\": true,\n      // Known incorrect spellings and correct suggestions\n      \"flagWords\": [\n        \"AccountChain->accountchain\",\n        \"BaseChain->basechain\",\n        \"boc->BoC\",\n        \"BOC->BoC\",\n        \"Github->GitHub\",\n        \"id->ID\",\n        \"Id->ID\",\n        \"MasterChain->masterchain\",\n        \"ShardChain->shardchain\",\n        \"StateInit->`StateInit`\",\n        \"TLB->TL-B\",\n        \"Toncenter->TON Center\",\n        \"toncoins->Toncoin\",\n        \"Toncoins->Toncoin\",\n        \"WorkChain->workchain\",\n        \"zkProofs->ZK-proofs\",\n        \"zkProof->ZK-proof\",\n      ],\n    },\n    // Do not check for banned words (denylists or flagWords) in certain files\n    {\n      \"filename\": \"contribute/style-guide*.mdx\",\n      \"ignoreWords\": [\n        \"tos\",\n        \"DOI\",\n        \"boc\",\n        \"BOC\",\n      ],\n      \"ignoreRegExpList\": [\n        \"\\\\b[tT]on[a-zA-Z]+\\\\b\", // ton or Ton-prefixed words\n        \"\\\\b[a-zA-Z]+Chain\\\\b\", // Chain-suffixed words\n      ],\n      \"dictionaries\": [\n        \"!deny-list\", // turns off the dictionary\n        \"!2lw-deny-list\", // turns off the dictionary\n      ]\n    },\n    {\n      \"filename\": \"languages/tolk/features/compiler-optimizations.mdx\",\n      \"ignoreWords\": [\n        \"fifting\",\n      ]\n    },\n    {\n      \"filename\": \"languages/tolk/from-func/tolk-vs-func.mdx\",\n      \"ignoreWords\": [\n        \"transpiles\",\n      ]\n    },\n    {\n      \"filename\": \"**/api/**/*.{json,yml,yaml}\",\n      \"ignoreWords\": [\n        \"smc\",\n      ],\n      \"dictionaries\": [\n        \"!deny-list\", // turns off the dictionary\n        \"!2lw-deny-list\", // turns off the dictionary\n      ]\n    },\n    {\n      \"filename\": \"**/*.{js,jsx,mjs}\",\n      \"ignoreWords\": [\n        \"Dests\",\n      ],\n      \"dictionaries\": [\n        \"!deny-list\", // turns off the dictionary\n        \"!2lw-deny-list\", // turns off the dictionary\n      ]\n    }\n  ],\n  \"ignorePaths\": [\n    // Some whitepapers\n    \"foundations/whitepapers/tblkch.mdx\",\n    \"foundations/whitepapers/ton.mdx\",\n    \"foundations/whitepapers/tvm.mdx\",\n    \"languages/fift/whitepaper.mdx\",\n    \"languages/tolk/features/standard-library.mdx\",\n    // Generated files\n    \"tvm/instructions.mdx\",\n    // Binaries\n    \"**/*.boc\",\n    // Code\n    \"**/*.fc\",\n    \"**/*.fif\",\n    \"**/*.fift\",\n    \"**/*.func\",\n    \"**/*.tact\",\n    \"**/*.tasm\",\n    \"**/*.tlb\",\n    \"**/*.tolk\",\n    \"**/*.py*\",\n    \"**/*.{ts,tsx}\",\n    \"**/*.css\",\n    // Miscellaneous\n    \"**/*.git*\",\n    \"**/*.svg\",\n    \"**/*.txt\",\n    \"CODEOWNERS\",\n    \"LICENSE-*\",\n    \"snippets/tvm-instruction-table.jsx\",\n    \"snippets/catchain-visualizer.jsx\"\n  ],\n  \"ignoreRegExpList\": [\n    //\n    // Predefined patterns from:\n    // https://github.com/streetsidesoftware/cspell/blob/main/packages/cspell-lib/src/lib/Settings/DefaultSettings.ts\n    //\n    \"SpellCheckerDisable\",\n    \"SpellCheckerIgnoreInDocSetting\",\n    \"Urls\",\n    \"Email\",\n    \"RsaCert\",\n    \"SshRsa\",\n    \"Base64MultiLine\",\n    \"Base64SingleLine\",\n    \"CommitHash\",\n    \"CommitHashLink\",\n    \"CStyleHexValue\",\n    \"CSSHexValue\",\n    \"SHA\",\n    \"HashStrings\",\n    \"UnicodeRef\",\n    \"UUID\",\n    \"href\",\n    //\n    // Custom patterns\n    //\n    \"\\\\s*[^\\\\s]*?=[\\\"'\\\\{]\", // arbitrary JSX attribute names\n    \"=\\\\s*\\\".*?\\\"\", // string values of JSX attributes\n    \"=\\\\s*'.*?'\", // string values of JSX attributes\n    \"(?<!\\\\\\\\)\\\\$(?:\\\\\\\\.|[^$\\\\\\\\])*?\\\\$\", // inline math\n    \"/(?<!\\\\\\\\)\\\\$\\\\$[\\\\s\\\\S]*?\\\\$\\\\$/g\", // block math\n    \"(?<!\\\\\\\\)``.*?``\", // inline code with double backticks\n    \"(?<!\\\\\\\\)`.*?`\", // inline code\n    \"/^([ \\\\t]*```).*([\\\\s\\\\S]*?)^\\\\1$/gmx\", // block code\n    \"^import[ \\\\t].+$\", // import ...\n    \"/^export[ \\\\t].+?(?=\\\\r?\\\\n\\\\r?\\\\n)/gms\", // export ...\n    \"(?<!\\\\\\\\)\\\\{(?:[^{}]|\\\\{(?:[^{}]|\\\\{[^{}]*\\\\})*\\\\})*\\\\}\", // jsx expressions in {}\n  ],\n}\n"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\nindent_style = space\nindent_size = 2\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto eol=lf\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference\n\nversion: 2\nupdates:\n  - package-ecosystem: \"npm\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n      day: \"monday\"\n      time: \"04:00\"\n      timezone: \"Etc/UTC\"\n    versioning-strategy: increase\n    allow:\n      - dependency-name: \"cspell\"\n      - dependency-name: \"husky\"\n      - dependency-name: \"mint\"\n    ignore:\n      - dependency-name: \"remark*\"\n      - dependency-name: \"unified*\"\n      - dependency-name: \"unist*\"\n      - dependency-name: \"mdast*\"\n      - dependency-name: \"*string*\"\n"
  },
  {
    "path": ".github/scripts/build_review_instructions.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Generate reviewer instructions with embedded style guide.\"\"\"\n\nfrom __future__ import annotations\n\nimport os\nimport textwrap\n\ndef main() -> None:\n    workspace = os.environ.get(\"GITHUB_WORKSPACE\")\n    if not workspace:\n        raise SystemExit(\"GITHUB_WORKSPACE env var is required\")\n\n    style_path = os.path.join(workspace, \"contribute\", \"style-guide-extended.mdx\")\n    try:\n        with open(style_path, encoding=\"utf-8\") as fh:\n            style_content = fh.read().rstrip()\n    except FileNotFoundError as exc:\n        raise SystemExit(f\"Style guide file not found: {style_path}\") from exc\n\n    style_block = f\"<styleguide>\\n{style_content}\\n</styleguide>\\n\\n\"\n\n    body = textwrap.dedent(\n        \"\"\"Repository: TON Blockchain documentation\n\nScope and priorities:\n1. Style-guide compliance is the first and absolute priority. Before reviewing, read the entire <styleguide> block. For every changed line in the diff, confirm it matches the guide. Any violation must be reported with the exact style-rule link.\n2. Only after style compliance, check for obvious, provable, blocking errors not covered by the guide (e.g., an incorrect calculation or an unsafe, non‑runnable step) and report them with proof. If not certain from repo content alone, omit.\n\nReview protocol:\n- Inspect only content files touched by this PR: `.md`, `.mdx`, and `docs.json`.\n- It is acceptable to report findings that originate in `docs.json` (e.g., broken or duplicate paths/slugs, invalid sidebar grouping, typos in titles). When the problem is in `docs.json`, cite its exact lines.\n- Examine only the lines changed in this diff (use surrounding context as needed). Do not flag issues that exist solely in unchanged content.\n- Report every issue you see in this diff; do not postpone or soften problems.\n- Location links must be repo-relative paths such as pending/discover/web3-basics/glossary.mdx?plain=1#L10-L12 (no https:// prefix).\n- When a style rule applies, cite it using contribute/style-guide-extended.mdx?plain=1#L<start>-L<end>. Only add the citation after running a verification command such as `rg \"<term>\" contribute/style-guide-extended.mdx` or `sed -n '<start>,<end>p'` and inspecting the output to confirm the line range.\n- If no style rule applies (e.g., factual error, typo), explain the issue clearly without a style link.\n- Keep findings direct, professional, and concise. Suggestions must describe the required fix.\n- Code identifiers: if the issue is lack of code font, preserve the token’s original case and wrap it in backticks. Only change case when the style guide explicitly mandates a canonical case for that exact identifier and you cite the relevant line range.\n\nHARD SCOPE WALL — CONTENT ONLY (MANDATORY):\n- You MUST NEVER read, open, cite, or rely on any non‑content files. This includes but is not limited to CI configs (`.github/**`), workflows (`*.yml`), code (`*.ts`, `*.tsx`, `*.js`, `*.py`, `*.go`, etc.), configuration/manifests (`package.json`, `pnpm-lock.yaml`, `*.toml`, `*.yaml`), tests, scripts, or build tool files.\n- Allowed inputs are limited to the changed `.md`/`.mdx` files, `docs.json`, and `contribute/style-guide-extended.mdx` (for rule citations).\n- Do not search outside these allowed files. Do not run commands that read or display non‑content files. Treat them as inaccessible.\n\nContext for `docs.json`:\n- Purpose: defines the site navigation tree, groupings, and slug mapping used by the docs site (metadata that directly affects the rendered docs experience).\n- Legit uses during review:\n  • Findings may target `docs.json` when the issue is there (e.g., broken/duplicate slug, incorrect path, wrong ordering/grouping).\n  • You may also use `docs.json` to verify that changed frontmatter `slug`/title or links in `.md`/`.mdx` remain valid.\n  • Cite `docs.json` lines when it is the source of the problem; otherwise cite the offending `.md`/`.mdx` lines.\n  • If an issue relates to both `docs.json` and `.md`/`.mdx`, report it only on `docs.json`.\n- Do not speculate about Mintlify runtime behavior or external systems; rely solely on repository content.\n\nSeverity policy:\n- Report only HIGH‑severity violations.\n- Do not report MEDIUM or LOW items.\n- HIGH includes, in this order of precedence:\n  (a) style‑guide rules tagged [HIGH] or listed under “Global overrides (always [HIGH])” in contribute/style-guide-extended.mdx; then\n  (b) obvious, non‑style blocking errors (e.g., incorrect calculations, non‑runnable commands, unsafe steps) that you can prove using repository content (diff lines, examples, reference tables).\n- For (b), include minimal proof with each finding (a short calculation or exact snippet) and cite the repo path/lines.\n- Do not assume or infer behavior. Only report (b) when you are 100% certain from the repo itself; if uncertain, omit.\n\nPersistence and completeness:\n- Persist until the review is fully handled end-to-end within this single run.\n- Do not stop after a partial pass; continue until you have either reported all HIGH-severity issues you can find in scope or are confident there are none.\n- Do not stop to ask any kind of follow-up questions.\n\nVerbosity and structure:\n- Follow the existing review output contract, do not invent alternative formats.\n- It is acceptable for the overall review to be long when there are many findings, but keep each Description and Suggestion concise (ideally no more than two short paragraphs each) while still giving enough detail to implement the fix.\n- Avoid meta-commentary about your own reasoning process or tool usage; focus solely on concrete findings, locations, and fixes.\n\nGoal: deliver exhaustive, high-confidence feedback that brings these TON Docs changes into full style-guide compliance and factual correctness.\n\"\"\"\n    )\n\n    link_rules = textwrap.dedent(\n        \"\"\"\n        \n        LINK FORMATTING — REQUIRED (overrides earlier bullets):\n        - Style‑guide citations: use a compact Markdown link with a short label, e.g. [Style rule — <short title>](contribute/style-guide-extended.mdx?plain=1#L<start>-L<end>). Verify the exact line range first (e.g., `rg \"<term>\" contribute/style-guide-extended.mdx` or `sed -n '<start>,<end>p'`).\n        - General code/location references: output a plain repo‑relative link on its own line, with no Markdown/backticks/prefix text so GitHub renders a rich preview. Example line:\n          pending/discover/web3-basics/glossary.mdx?plain=1#L10-L12\n        - Do not use https:// prefixes for repo‑relative links.\n        \"\"\"\n    )\n\n    print(style_block + body + link_rules)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": ".github/scripts/build_review_payload.py",
    "content": "#!/usr/bin/env python3\n\"\"\"\nBuild a GitHub Pull Request review payload from Pitaya results.\n\nInputs:\n  - --run-dir: path to pitaya results/run_* directory (contains instances/)\n  - --repo:    owner/repo for link rewriting (GITHUB_REPOSITORY)\n  - --sha:     PR head SHA for absolute blob links (PR_HEAD_SHA)\n  - --severities: comma-separated list of severities to include as inline comments (e.g., \"HIGH\" or \"HIGH,MEDIUM,LOW\")\n  - --max-comments: hard cap for number of inline comments (default 40)\n\nOutput:\n  JSON to stdout:\n    {\n      \"body\": \"<composer summary with absolutized Location links>\",\n      \"event\": \"COMMENT\",\n      \"comments\": [\n        {\"path\":\"...\", \"side\":\"RIGHT\", \"line\":123, \"start_line\":120, \"start_side\":\"RIGHT\", \"body\":\"...\"}\n      ]\n    }\n\"\"\"\nfrom __future__ import annotations\n\nimport argparse\nimport json\nimport os\nimport re\nfrom dataclasses import dataclass\nfrom pathlib import Path\nfrom typing import Dict, Iterable, List, Optional, Tuple\n\n# ---------- Utilities ----------\n\ndef _read_json(path: Path) -> Optional[dict]:\n    try:\n        txt = path.read_text(encoding=\"utf-8\", errors=\"replace\")\n        return json.loads(txt)\n    except Exception:\n        return None\n\n\ndef _iter_instance_jsons(run_dir: Path) -> Iterable[Tuple[Path, dict]]:\n    inst = run_dir / \"instances\"\n    if not inst.is_dir():\n        return []\n    files = list(inst.rglob(\"*.json\"))\n    for p in files:\n        data = _read_json(p)\n        if isinstance(data, dict):\n            yield p, data\n\n\ndef _role_of(obj: dict) -> Optional[str]:\n    # Strategy stores role either at top-level or under metadata.pr_review.role\n    role = obj.get(\"role\")\n    if isinstance(role, str) and role:\n        return role\n    md = obj.get(\"metadata\")\n    if isinstance(md, dict):\n        prr = md.get(\"pr_review\")\n        if isinstance(prr, dict):\n            r = prr.get(\"role\")\n            if isinstance(r, str):\n                return r\n    return None\n\n\ndef _final_message_of(obj: dict) -> Optional[str]:\n    msg = obj.get(\"final_message\")\n    return msg if isinstance(msg, str) else None\n\n\ndef _metrics_of(obj: dict) -> Dict[str, object]:\n    m = obj.get(\"metrics\")\n    return m if isinstance(m, dict) else {}\n\n\n# ---------- Link rewriting (replicates rewrite_review_links.py) ----------\n\ndef _absolutize_location_links(body: str, repo: Optional[str], sha: Optional[str]) -> str:\n    if not body or not repo:\n        return body\n    blob_prefix = f\"https://github.com/{repo}/blob/\"\n    doc_blob_prefix = f\"{blob_prefix}{sha or 'main'}/\"\n    style_blob_prefix = f\"{blob_prefix}main/\"\n    style_rel = \"contribute/style-guide-extended.mdx\"\n\n    def absolutize_path(path: str) -> str:\n        if path.startswith(\"http://\") or path.startswith(\"https://\"):\n            return path\n        normalized = path.lstrip(\"./\")\n        base = style_blob_prefix if normalized.startswith(style_rel) else doc_blob_prefix\n        return f\"{base}{normalized}\"\n\n    # 1) Fix explicit Location: lines when present\n    lines: List[str] = []\n    for line in body.splitlines():\n        stripped = line.lstrip()\n        indent_len = len(line) - len(stripped)\n        for marker in (\"- Location:\", \"Location:\", \"* Location:\"):\n            if stripped.startswith(marker):\n                prefix, _, rest = stripped.partition(\":\")\n                link = rest.strip()\n                if link:\n                    link = absolutize_path(link)\n                    stripped = f\"{prefix}: {link}\"\n                    line = \" \" * indent_len + stripped\n                break\n        lines.append(line)\n\n    rewritten = \"\\n\".join(lines)\n\n    # 2) Convert any doc links like path/to/file.mdx?plain=1#L10-L20 anywhere in text\n    #    Avoid variable-width lookbehinds; match optional scheme as a capture and skip when present.\n    if repo:\n        generic_pattern = re.compile(\n            r\"(?P<prefix>https?://)?(?P<path>[A-Za-z0-9_./\\-]+\\.(?:md|mdx|json))\\?plain=1#L\\d+(?:-L\\d+)?\"\n        )\n\n        def repl(match: re.Match[str]) -> str:\n            if match.group(\"prefix\"):\n                # Already absolute; leave as-is\n                return match.group(0)\n            p = match.group(\"path\").lstrip(\"./\")\n            base = style_blob_prefix if p.startswith(style_rel) else doc_blob_prefix\n            # Append the anchor part after the path\n            suffix = match.group(0)[len(match.group(\"path\")) :]\n            return f\"{base}{p}{suffix}\"\n\n        rewritten = generic_pattern.sub(repl, rewritten)\n\n    style_pattern = re.compile(rf\"{re.escape(style_rel)}\\?plain=1#L\\d+(?:-L\\d+)?\")\n\n    def replace_style_links(text: str) -> str:\n        result: list[str] = []\n        last = 0\n        for match in style_pattern.finditer(text):\n            start, end = match.span()\n            result.append(text[last:start])\n            link = match.group(0)\n            prefix_start = max(0, start - len(style_blob_prefix))\n            if text[prefix_start:start] == style_blob_prefix:\n                result.append(link)\n            else:\n                result.append(f\"{style_blob_prefix}{link.lstrip('./')}\")\n            last = end\n        result.append(text[last:])\n        return \"\".join(result)\n\n    rewritten = replace_style_links(rewritten)\n\n    # Ensure doc blob URLs use PR head SHA (style guide stays on main)\n    if sha:\n        doc_prefix_regex = re.compile(rf\"{re.escape(blob_prefix)}([^/]+)/([^\\s)]+)\")\n\n        def fix_doc(match: re.Match[str]) -> str:\n            base = match.group(1)\n            remainder = match.group(2)\n            target = \"main\" if remainder.startswith(style_rel) else sha\n            if base == target:\n                return match.group(0)\n            return f\"{blob_prefix}{target}/{remainder}\"\n\n        rewritten = doc_prefix_regex.sub(fix_doc, rewritten)\n\n    return rewritten\n\n\ndef _build_from_sidecar(sidecar: dict, *, repo: str, sha: str, repo_root: Path) -> Tuple[str, str, List[Dict[str, object]]]:\n    \"\"\"Return (body, event, comments[]) from sidecar index.json. Event is always COMMENT.\"\"\"\n    body = str(sidecar.get(\"intro\") or \"\").strip()\n    # Force COMMENT-only behavior regardless of sidecar content\n    event = \"COMMENT\"\n    commit_id = str(sidecar.get(\"commit_id\") or \"\").strip()\n    if commit_id:\n        sha = commit_id\n    items = sidecar.get(\"selected_details\") or []\n    comments: List[Dict[str, object]] = []\n    def sanitize_code_for_gh_suggestion(code: str) -> str:\n        \"\"\"Normalize a suggestion snippet for GitHub suggestions.\n        - If a fenced block is present, extract its inner content.\n        - Remove diff headers and treat leading '+' additions as plain text; drop '-' lines.\n        \"\"\"\n        # Extract inner of first fenced block when present\n        lang, inner = _extract_first_code_block(code)\n        text = inner if inner is not None else code\n        out: List[str] = []\n        for ln in text.splitlines():\n            if ln.startswith('--- ') or ln.startswith('+++ ') or ln.startswith('@@'):\n                continue\n            if ln.startswith('+') and not ln.startswith('++'):\n                out.append(ln[1:])\n                continue\n            if ln.startswith('-') and not ln.startswith('--'):\n                # Skip removed lines in GH suggestion body\n                continue\n            out.append(ln)\n        return \"\\n\".join(out).rstrip(\"\\n\")\n\n    for it in items:\n        try:\n            path = str(it.get(\"path\") or \"\").strip()\n            start = int(it.get(\"start\") or 0)\n            end = int(it.get(\"end\") or 0)\n            # severity is not required for comment body; skip storing it\n            title = str(it.get(\"title\") or \"\").strip()\n            desc = str(it.get(\"desc\") or \"\").strip()\n            sugg = it.get(\"suggestion\") or {}\n            code = str(sugg.get(\"code\") or \"\")\n        except Exception:\n            continue\n        if not (path and start > 0 and end >= start and title):\n            continue\n        # Clamp to file length when available\n        file_path = (repo_root / path).resolve()\n        if file_path.is_file():\n            try:\n                line_count = sum(1 for _ in file_path.open(\"r\", encoding=\"utf-8\", errors=\"ignore\"))\n                if end > line_count:\n                    end = line_count\n                if start > line_count:\n                    continue\n            except Exception:\n                pass\n        # Build comment body with title + description and optional suggestion fence\n        code = code.rstrip(\"\\n\")\n        parts: List[str] = []\n        # Prefer including severity in heading when present in sidecar\n        sev = (it.get(\"severity\") or \"\").strip().upper()\n        if title:\n            heading = f\"### [{sev}] {title}\".strip()\n            parts.append(heading)\n        if desc:\n            parts.append(\"\")\n            parts.append(desc)\n        # When replacement text is present, include a GitHub suggestion block.\n        # Allow empty replacement (deletion) suggestions: GitHub treats an empty block as delete selected lines.\n        if code is not None:\n            repl = sanitize_code_for_gh_suggestion(code)\n            repl_lines = repl.splitlines()\n            n_range = end - start + 1\n            if (\n                (n_range == 1 and len(repl_lines) == 1) or\n                (n_range > 1 and len(repl_lines) == n_range) or\n                (repl == \"\" and n_range >= 1)\n            ):\n                parts.append(\"\")\n                parts.append(\"```suggestion\")\n                if repl:\n                    parts.append(repl)\n                parts.append(\"```\")\n        else:\n            # No auto-fix block; rely on title/description and CTA only.\n            pass\n        # Always include the feedback CTA\n        parts.append(\"\")\n        parts.append(\"Please leave a reaction 👍/👎 to this suggestion to improve future reviews for everyone!\")\n        body_text = \"\\n\".join(parts).strip()\n        body_text = _absolutize_location_links(body_text, repo or None, sha or None)\n\n        c: Dict[str, object] = {\"path\": path, \"side\": \"RIGHT\", \"body\": body_text}\n        if start == end:\n            c[\"line\"] = end\n        else:\n            c[\"start_line\"] = start\n            c[\"line\"] = end\n            c[\"start_side\"] = \"RIGHT\"\n        comments.append(c)\n    # Rewrite links in top-level body\n    body = _absolutize_location_links(body, repo or None, sha or None)\n    return body, event, comments\n\n\n# ---------- Finding parsing ----------\n\n_H_RE = re.compile(r\"^###\\s*\\[(HIGH|MEDIUM|LOW)\\]\\s*(.+?)\\s*$\", re.IGNORECASE)\n_LOC_RE = re.compile(\n    r\"^Location:\\s*([^\\s?#]+)(?:\\?plain=1)?#L(?P<start>\\d+)(?:-L(?P<end>\\d+))?\\s*$\",\n    re.IGNORECASE,\n)\n\n\n@dataclass\nclass Finding:\n    severity: str\n    title: str\n    path: str\n    start: int\n    end: int\n    desc: str\n    suggestion_raw: str\n    suggestion_replacement: Optional[str] = None\n    uid: Optional[str] = None\n\n    def key(self) -> Tuple[str, int, int, str]:\n        t = re.sub(r\"\\W+\", \" \", self.title or \"\").strip().lower()\n        return (self.path, self.start, self.end, t)\n\n\ndef _extract_first_code_block(text: str) -> Tuple[Optional[str], Optional[str]]:\n    \"\"\"\n    Return (lang, content) for the first fenced code block in text.\n    \"\"\"\n    m = re.search(r\"```([a-zA-Z0-9_-]*)\\s*\\n([\\s\\S]*?)\\n```\", text)\n    if not m:\n        return None, None\n    lang = (m.group(1) or \"\").strip().lower()\n    content = m.group(2)\n    return lang, content\n\n\n_TRAILER_JSON_RE = re.compile(r\"```json\\s*(\\{[\\s\\S]*?\\})\\s*```\\s*$\", re.IGNORECASE | re.MULTILINE)\n# Remove any fenced code blocks (```lang ... ```), used when we can't submit a proper GH suggestion\n_FENCED_BLOCK_RE = re.compile(r\"```[a-zA-Z0-9_-]*\\s*\\n[\\s\\S]*?\\n```\", re.MULTILINE)\n\ndef _strip_trailing_json_trailer(text: str) -> str:\n    \"\"\"Remove a trailing fenced JSON block (validator trailer) from text.\"\"\"\n    return _TRAILER_JSON_RE.sub(\"\", text).rstrip()\n\n\ndef _parse_findings(md: str) -> List[Finding]:\n    lines = md.splitlines()\n    i = 0\n    items: List[Finding] = []\n\n    while i < len(lines):\n        m = _H_RE.match(lines[i])\n        if not m:\n            i += 1\n            continue\n        severity = m.group(1).upper()\n        title = m.group(2).strip()\n        i += 1\n\n        # Expect blocks with Location:, Description:, Suggestion:\n        loc_path = \"\"\n        loc_start = 0\n        loc_end = 0\n        desc_lines: List[str] = []\n        sugg_lines: List[str] = []\n\n        # Scan until next heading or end\n        section = \"none\"\n        while i < len(lines) and not _H_RE.match(lines[i]):\n            line = lines[i]\n            if line.strip().lower().startswith(\"location:\"):\n                lm = _LOC_RE.match(line.strip())\n                if lm:\n                    loc_path = lm.group(1).strip()\n                    loc_start = int(lm.group(\"start\"))\n                    loc_end = int(lm.group(\"end\") or lm.group(\"start\"))\n                section = \"location\"\n            elif line.strip().lower().startswith(\"description:\"):\n                section = \"desc\"\n            elif line.strip().lower().startswith(\"suggestion:\"):\n                section = \"sugg\"\n            else:\n                if section == \"desc\":\n                    desc_lines.append(line)\n                elif section == \"sugg\":\n                    sugg_lines.append(line)\n            i += 1\n\n        if not (loc_path and loc_start > 0 and loc_end >= loc_start):\n            # Skip malformed entries\n            continue\n        desc = \"\\n\".join(desc_lines).strip()\n        sugg_raw = \"\\n\".join(sugg_lines).strip()\n        # Remove any trailing validator JSON trailer that might have been captured\n        sugg_raw = _strip_trailing_json_trailer(sugg_raw)\n\n        # Try to derive a GH suggestion replacement from the first non-diff code block\n        replacement: Optional[str] = None\n        lang, content = _extract_first_code_block(sugg_raw)\n        if content:\n            if lang and lang != \"diff\" and lang != \"patch\":\n                replacement = content\n            elif not lang:\n                # Unspecified language — assume it's a replacement snippet\n                replacement = content\n            # else: diff/patch -> skip automated suggestion; keep raw in comment\n\n        items.append(\n            Finding(\n                severity=severity,\n                title=title,\n                path=loc_path,\n                start=loc_start,\n                end=loc_end,\n                desc=desc,\n                suggestion_raw=sugg_raw,\n                suggestion_replacement=replacement,\n            )\n        )\n    return items\n\n\ndef _parse_trailer_findings(md: str) -> List[dict]:\n    \"\"\"Parse the fenced JSON trailer at the end and return .findings list when present.\"\"\"\n    m = re.search(r\"```json\\s*(\\{[\\s\\S]*?\\})\\s*```\\s*$\", md, flags=re.IGNORECASE | re.MULTILINE)\n    if not m:\n        return []\n    try:\n        obj = json.loads(m.group(1))\n        if isinstance(obj, dict):\n            f = obj.get(\"findings\")\n            if isinstance(f, list):\n                out = []\n                for it in f:\n                    if isinstance(it, dict):\n                        out.append(it)\n                return out\n    except Exception:\n        return []\n    return []\n\n\n# Removed verdict aggregation logic: event selection is fixed to COMMENT.\n\n\n# ---------- Main ----------\n\ndef main() -> None:\n    ap = argparse.ArgumentParser()\n    ap.add_argument(\"--run-dir\", required=True, help=\"Pitaya results/run_* directory\")\n    ap.add_argument(\"--repo\", default=os.environ.get(\"GITHUB_REPOSITORY\") or \"\", help=\"owner/repo\")\n    ap.add_argument(\"--sha\", default=os.environ.get(\"PR_HEAD_SHA\") or \"\", help=\"PR head SHA\")\n    ap.add_argument(\"--severities\", default=os.environ.get(\"INLINE_SEVERITIES\") or \"HIGH\")\n    ap.add_argument(\"--max-comments\", type=int, default=int(os.environ.get(\"MAX_COMMENTS\") or 40))\n    args = ap.parse_args()\n\n    run_dir = Path(args.run_dir)\n    repo = args.repo.strip()\n    sha = args.sha.strip()\n    include_sevs = {s.strip().upper() for s in (args.severities or \"HIGH\").split(\",\") if s.strip()}\n\n    # Prefer sidecar when present (new strategy contract)\n    sidecar_path = run_dir / \"review\" / \"index.json\"\n    if sidecar_path.exists():\n        try:\n            sidecar = json.loads(sidecar_path.read_text(encoding=\"utf-8\", errors=\"replace\"))\n        except Exception as e:\n            raise SystemExit(f\"Failed to read sidecar {sidecar_path}: {e}\")\n        body, _event, comments = _build_from_sidecar(sidecar, repo=repo, sha=sha, repo_root=Path(os.environ.get(\"GITHUB_WORKSPACE\") or \".\"))\n        # Always submit a COMMENT review regardless of findings\n        out = {\n            \"body\": body or \"No documentation issues detected.\",\n            \"event\": \"COMMENT\",\n            \"comments\": comments,\n            \"commit_id\": (sidecar.get(\"commit_id\") or sha) or None,\n        }\n        json.dump(out, fp=os.fdopen(1, \"w\"), ensure_ascii=False)\n        return\n\n    # Fallback: derive from instances when sidecar is absent\n    files = list(_iter_instance_jsons(run_dir))\n    if not files:\n        raise SystemExit(\"No instance JSON files found in run dir and no sidecar present\")\n\n    composer_body: Optional[str] = None\n    composer_metrics: Dict[str, object] = {}\n    validator_messages: List[str] = []\n    validator_trailer_findings: List[dict] = []\n    metrics_list: List[Dict[str, object]] = []\n\n    for path, obj in files:\n        role = _role_of(obj) or \"\"\n        fm = _final_message_of(obj)\n        metrics = _metrics_of(obj)\n        if role == \"composer\":\n            if fm and not composer_body:\n                composer_body = fm\n            if metrics:\n                composer_metrics.update(metrics)\n        elif role == \"validator\":\n            if fm:\n                validator_messages.append(fm)\n                # collect trailer findings if present\n                validator_trailer_findings.extend(_parse_trailer_findings(fm))\n            if metrics:\n                metrics_list.append(metrics)\n        else:\n            # Heuristic: treat messages that end with a fenced JSON trailer as validator outputs\n            if isinstance(fm, str) and re.search(r\"```json\\s*\\{[\\s\\S]*\\}\\s*```\\s*$\", fm, re.IGNORECASE):\n                validator_messages.append(fm)\n                validator_trailer_findings.extend(_parse_trailer_findings(fm))\n                if metrics:\n                    metrics_list.append(metrics)\n\n    # Removed verdict computation; not used for event selection.\n\n    # Event will be set by simplified rule after building comments.\n\n    # Derive selected finding IDs and a human body from composer output (new composer may return JSON)\n    selected_ids: List[str] = []\n    body = composer_body or \"\"\n    composer_json = None\n    try:\n        composer_json = json.loads(body) if body.strip().startswith(\"{\") else None\n    except Exception:\n        composer_json = None\n    if isinstance(composer_json, dict) and (\"intro\" in composer_json or \"selected_ids\" in composer_json):\n        intro = composer_json.get(\"intro\")\n        if isinstance(intro, str) and intro.strip():\n            body = intro.strip()\n        else:\n            body = \"Automated review summary\"\n        ids = composer_json.get(\"selected_ids\")\n        if isinstance(ids, list):\n            seen_ids = set()\n            for v in ids:\n                if isinstance(v, str) and v not in seen_ids:\n                    selected_ids.append(v)\n                    seen_ids.add(v)\n    # Fallback to original markdown body\n    body = _absolutize_location_links(body, repo if repo else None, sha if sha else None)\n    if not body.strip():\n        body = \"No documentation issues detected.\"\n\n    # Parse validator findings and deduplicate\n    findings: List[Finding] = []\n    for msg in validator_messages:\n        parsed = _parse_findings(msg or \"\")\n        # Attempt to attach UIDs from trailer by matching on (path,start,end,severity,title)\n        if validator_trailer_findings:\n            trailer_index: Dict[Tuple[str, int, int, str, str], str] = {}\n            for it in validator_trailer_findings:\n                path = str(it.get(\"path\") or \"\").strip()\n                start = int(it.get(\"start\") or 0)\n                end = int(it.get(\"end\") or 0)\n                sev = str(it.get(\"severity\") or \"\").strip().upper()\n                title = str(it.get(\"title\") or \"\").strip()\n                uid = str(it.get(\"uid\") or \"\").strip()\n                if path and start > 0 and end >= start and sev and title and uid:\n                    trailer_index[(path, start, end, sev, title)] = uid\n            for f in parsed:\n                key = (f.path, f.start, f.end, f.severity.upper(), f.title)\n                if key in trailer_index:\n                    f.uid = trailer_index[key]\n        findings.extend(parsed)\n\n    # Build selected findings list (preserve order) when composer provided UIDs\n    selected_findings: List[Finding] = []\n    if selected_ids:\n        # Index validator trailer findings by uid and tuple for robust matching\n        trailer_by_uid: Dict[str, dict] = {}\n        for it in validator_trailer_findings:\n            uid = str(it.get(\"uid\") or \"\").strip()\n            if uid:\n                trailer_by_uid[uid] = it\n        # Index parsed findings for lookup by (path,start,end,sev,title)\n        parsed_index: Dict[Tuple[str, int, int, str, str], Finding] = {}\n        parsed_alt_index: Dict[Tuple[str, int, int, str], Finding] = {}\n        for f in findings:\n            parsed_index[(f.path, f.start, f.end, f.severity.upper(), f.title)] = f\n            parsed_alt_index[(f.path, f.start, f.end, f.severity.upper())] = f\n        for uid in selected_ids:\n            fobj: Optional[Finding] = None\n            t = trailer_by_uid.get(uid)\n            if t:\n                key = (\n                    str(t.get(\"path\") or \"\").strip(),\n                    int(t.get(\"start\") or 0),\n                    int(t.get(\"end\") or 0),\n                    str(t.get(\"severity\") or \"\").strip().upper(),\n                    str(t.get(\"title\") or \"\").strip(),\n                )\n                fobj = parsed_index.get(key)\n                if not fobj:\n                    key2 = (key[0], key[1], key[2], key[3])\n                    fobj = parsed_alt_index.get(key2)\n                if not fobj and key[0] and key[1] > 0 and key[2] >= key[1]:\n                    # Create a minimal finding from trailer\n                    fobj = Finding(\n                        severity=key[3] or \"HIGH\",\n                        title=key[4] or \"Selected finding\",\n                        path=key[0],\n                        start=key[1],\n                        end=key[2],\n                        desc=\"\",\n                        suggestion_raw=\"\",\n                    )\n                    fobj.uid = uid\n            else:\n                # Fallback: search parsed findings by uid\n                fobj = next((pf for pf in findings if pf.uid == uid), None)\n            if fobj and fobj.severity in include_sevs:\n                selected_findings.append(fobj)\n        base_list = selected_findings\n    else:\n        # Filter by severities, then dedupe\n        findings = [f for f in findings if f.severity in include_sevs]\n        seen: set[Tuple[str, int, int, str]] = set()\n        deduped: List[Finding] = []\n        for f in findings:\n            k = f.key()\n            if k in seen:\n                continue\n            seen.add(k)\n            deduped.append(f)\n        base_list = deduped\n\n    # Cap number of comments\n    base_list = base_list[: max(0, int(args.max_comments))]\n\n    # Build inline comments\n    comments: List[Dict[str, object]] = []\n    # Optional bounds check against workspace files to reduce 422 errors\n    repo_root = Path(os.environ.get(\"GITHUB_WORKSPACE\") or \".\")\n    for f in base_list:\n        # Clamp line numbers to file length when possible\n        file_path = (repo_root / f.path).resolve()\n        if file_path.is_file():\n            try:\n                line_count = sum(1 for _ in file_path.open(\"r\", encoding=\"utf-8\", errors=\"ignore\"))\n                if f.end > line_count:\n                    f.end = line_count\n                if f.start > line_count:\n                    # Skip invalid locations entirely\n                    continue\n            except Exception:\n                pass\n        # Compose comment body with optional suggestion\n        parts: List[str] = []\n        parts.append(f\"### [{f.severity}] {f.title}\")\n        if f.desc.strip():\n            parts.append(\"\")\n            parts.append(f.desc.strip())\n        # Only submit commit suggestions when the replacement likely covers the full selected range\n        submitted_suggestion = False\n        if f.suggestion_replacement is not None:\n            repl = f.suggestion_replacement.rstrip(\"\\n\")\n            repl_lines = repl.splitlines()\n            n_range = f.end - f.start + 1\n            if (\n                (n_range == 1 and len(repl_lines) == 1) or\n                (n_range > 1 and len(repl_lines) == n_range) or\n                (repl == \"\" and n_range >= 1)\n            ):\n                parts.append(\"\")\n                parts.append(\"```suggestion\")\n                if repl:\n                    parts.append(repl)\n                parts.append(\"```\")\n                submitted_suggestion = True\n        if not submitted_suggestion and f.suggestion_raw.strip():\n            # Detect deletion-only diffs and convert to empty GH suggestion\n            raw = f.suggestion_raw\n            lang, inner = _extract_first_code_block(raw)\n            text = inner if inner is not None else raw\n            lines = [ln.strip() for ln in text.splitlines()]\n            has_add = any(ln.startswith('+') and not ln.startswith('++') for ln in lines)\n            has_del = any(ln.startswith('-') and not ln.startswith('--') for ln in lines)\n            if has_del and not has_add:\n                parts.append(\"\")\n                parts.append(\"```suggestion\")\n                parts.append(\"```\")\n                submitted_suggestion = True\n        if not submitted_suggestion and f.suggestion_raw.strip():\n            parts.append(\"\")\n            # Do not include fenced blocks if we can't guarantee a commit suggestion\n            cleaned = _TRAILER_JSON_RE.sub(\"\", f.suggestion_raw.strip())\n            cleaned = _FENCED_BLOCK_RE.sub(\"\", cleaned).strip()\n            if cleaned:\n                parts.append(cleaned)\n        # Always include the feedback CTA\n        parts.append(\"\")\n        parts.append(\"Please leave a reaction 👍/👎 to this suggestion to improve future reviews for everyone!\")\n        body_text = \"\\n\".join(parts).strip()\n        # Rewrite style-guide references to clickable blob URLs\n        body_text = _absolutize_location_links(body_text, repo if repo else None, sha if sha else None)\n\n        c: Dict[str, object] = {\n            \"path\": f.path,\n            \"side\": \"RIGHT\",\n            \"body\": body_text,\n        }\n        if f.start == f.end:\n            c[\"line\"] = f.end\n        else:\n            c[\"start_line\"] = f.start\n            c[\"line\"] = f.end\n            c[\"start_side\"] = \"RIGHT\"\n        comments.append(c)\n\n    # Always submit a COMMENT review, never approve or request changes.\n    event = \"COMMENT\"\n\n    out = {\n        \"body\": body,\n        \"event\": event,\n        \"comments\": comments,\n        \"commit_id\": sha or None,\n    }\n    json.dump(out, fp=os.fdopen(1, \"w\"), ensure_ascii=False)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": ".github/scripts/common.mjs",
    "content": "export async function hidePriorCommentsWithPrefix({\n  github, // injected by GitHub\n  context, // injected by GitHub\n  exec, // injected by GitHub\n  prefix = '',\n  resolved = true,\n  user = 'github-actions[bot]',\n}) {\n  const comments = await withRetry(() =>\n    github.rest.issues.listComments({\n      owner: context.repo.owner,\n      repo: context.repo.repo,\n      issue_number: context.issue.number,\n    })\n  );\n  await exec.exec('sleep 0.5s');\n  for (const comment of comments.data) {\n    const commentData = await withRetry(() =>\n      github.graphql(`\n        query($nodeId: ID!) {\n          node(id: $nodeId) {\n            ... on IssueComment {\n              isMinimized\n            }\n          }\n        }\n      `, { nodeId: comment.node_id })\n    );\n    await exec.exec('sleep 0.5s');\n    const isHidden = commentData?.node?.isMinimized;\n    if (isHidden) { continue; }\n    if (\n      comment.user.login === user &&\n      comment.body.startsWith(prefix)\n    ) {\n      console.log('Comment node_id:', comment.node_id);\n      const commentStatus = await withRetry(() =>\n        github.graphql(`\n          mutation($subjectId: ID!, $classifier: ReportedContentClassifiers!) {\n            minimizeComment(input: {\n              subjectId: $subjectId,\n              classifier: $classifier\n            }) {\n              minimizedComment {\n                isMinimized\n                minimizedReason\n              }\n            }\n          }\n        `, {\n          subjectId: comment.node_id,\n          classifier: resolved ? 'RESOLVED' : 'OUTDATED',\n        })\n      );\n      await exec.exec('sleep 0.5s');\n      console.log(commentStatus);\n    }\n  }\n}\n\nexport async function createComment({\n  github, // injected by GitHub\n  context, // injected by GitHub\n  exec, // injected by GitHub\n  body = '',\n}) {\n  await withRetry(() =>\n    github.rest.issues.createComment({\n      owner: context.repo.owner,\n      repo: context.repo.repo,\n      issue_number: context.issue.number,\n      body: body,\n    })\n  );\n  await exec.exec('sleep 0.2s');\n}\n\n/** @param fn {() => Promise<any>} */\nasync function withRetry(fn, maxRetries = 3, baseDelayMs = 1500) {\n  let lastError;\n  for (let attempt = 1; attempt <= maxRetries; attempt += 1) {\n    try {\n      return await fn();\n    } catch (error) {\n      // Don't retry on 4xx errors (client errors), only on 5xx or network issues\n      if (error.status && error.status >= 400 && error.status < 500) {\n        throw error;\n      }\n      lastError = error;\n\n      // Exponential backoff\n      const delay = baseDelayMs * Math.pow(2, attempt - 1);\n      console.log(`Attempt ${attempt} failed, retrying in ${delay / 1000}s...`);\n      await new Promise((resolve) => setTimeout(resolve, delay));\n    }\n  }\n  // Did not produce results after multiple retries\n  throw lastError;\n}\n"
  },
  {
    "path": ".github/scripts/generate-v2-api-table.py",
    "content": "import json\nimport re\nfrom pathlib import Path\nfrom collections import defaultdict\n\n# Define which specs to process and where to inject tables\nSPECS = [\n    {\n        'spec_path': 'ecosystem/api/toncenter/v2.json',\n        'mdx_path': 'ecosystem/api/toncenter/v2/overview.mdx',\n        'marker': 'API_V2_ENDPOINTS',\n        'link_base': '/ecosystem/api/toncenter/v2',\n        'exclude_tags': ['rpc'],\n        'include_jsonrpc': True,\n    },\n]\n\ndef load_openapi_spec(filepath: Path) -> dict:\n    \"\"\"Load the OpenAPI JSON file.\"\"\"\n    with open(filepath, 'r') as f:\n        return json.load(f)\n\n\ndef extract_endpoints(spec: dict, exclude_tags: list = None) -> list:\n    \"\"\"Extract endpoints from the OpenAPI spec.\"\"\"\n    exclude_tags = [t.lower() for t in (exclude_tags or [])]\n\n    endpoints = []\n    seen_paths = set()\n    paths = spec.get('paths', {})\n\n    for path, path_item in paths.items():\n        for method in ['get', 'post', 'put', 'patch', 'delete']:\n            if method not in path_item:\n                continue\n\n            operation = path_item[method]\n            tags = operation.get('tags', ['Other'])\n            tags_lower = [t.lower() for t in tags]\n\n            # Skip if ALL tags are in exclude list\n            if all(t in exclude_tags for t in tags_lower):\n                continue\n\n            # Use first non-excluded tag as category\n            tag = next((t for t in tags if t.lower() not in exclude_tags), tags[0])\n\n            # Avoid duplicates\n            if path in seen_paths:\n                continue\n            seen_paths.add(path)\n\n            endpoints.append({\n                'path': path,\n                'method': method.upper(),\n                'tag': tag,\n                'summary': operation.get('summary', ''),\n                'operationId': operation.get('operationId', ''),\n            })\n\n    return endpoints\n\n\ndef generate_mintlify_link(endpoint: dict, base_path: str) -> str:\n    \"\"\"Generate Mintlify documentation link based on summary (slugified).\"\"\"\n    tag = endpoint['tag'].lower().replace(' ', '-').replace('_', '-')\n    summary = endpoint.get('summary', '')\n\n    if summary:\n        # Mintlify slugifies the summary for the URL\n        # \"Get account state and balance\" -> \"get-account-state-and-balance\"\n        slug = summary.lower()\n        slug = re.sub(r'[^a-z0-9\\s-]', '', slug)\n        slug = re.sub(r'\\s+', '-', slug)\n        slug = re.sub(r'-+', '-', slug)\n        slug = slug.strip('-')\n        return f\"{base_path}/{tag}/{slug}\"\n\n    operation_id = endpoint.get('operationId', '')\n    if operation_id:\n        clean_op_id = operation_id.replace('_get', '').replace('_post', '')\n        slug = re.sub(r'([a-z])([A-Z])', r'\\1-\\2', clean_op_id).lower()\n        return f\"{base_path}/{tag}/{slug}\"\n\n    path_slug = endpoint['path'].split('/')[-1].lower()\n    return f\"{base_path}/{tag}/{path_slug}\"\n\n\ndef generate_table(endpoints: list, link_base: str) -> str:\n    \"\"\"Generate markdown table from endpoints.\"\"\"\n    # Group by tag\n    grouped = defaultdict(list)\n    for ep in endpoints:\n        grouped[ep['tag']].append(ep)\n\n    # Custom sort order\n    tag_order = ['accounts', 'blocks', 'transactions', 'send', 'run method', 'utils', 'configuration', 'json-rpc']\n\n    def sort_key(tag):\n        try:\n            return tag_order.index(tag.lower())\n        except ValueError:\n            return len(tag_order)\n\n    sorted_tags = sorted(grouped.keys(), key=sort_key)\n\n    lines = [\n        \"| Category | Method | Description |\",\n        \"| -------- | ------ | ----------- |\",\n    ]\n\n    for tag in sorted_tags:\n        for ep in grouped[tag]:\n            method = ep['method']\n            path = ep['path'].replace('/api/v2', '').replace('/api/v3', '')\n            summary = ep['summary']\n            link = generate_mintlify_link(ep, link_base)\n\n            display_tag = tag.capitalize() if tag.islower() else tag\n            method_display = f\"[`{method} {path}`]({link})\"\n\n            lines.append(f\"| **{display_tag}** | {method_display} | {summary} |\")\n\n    return '\\n'.join(lines)\n\n\ndef process_spec(config: dict, repo_root: Path) -> str:\n    \"\"\"Process a single OpenAPI spec and generate table.\"\"\"\n    spec_path = repo_root / config['spec_path']\n\n    if not spec_path.exists():\n        print(f\"Spec not found: {spec_path}\")\n        return None\n\n    spec = load_openapi_spec(spec_path)\n    if spec is None:\n        return None\n\n    endpoints = extract_endpoints(spec, config.get('exclude_tags', []))\n\n    # Optionally add JSON-RPC endpoint\n    if config.get('include_jsonrpc'):\n        paths = spec.get('paths', {})\n        for rpc_path in ['/api/v2/jsonRPC', '/api/v3/jsonRPC']:\n            if rpc_path in paths:\n                jsonrpc = paths[rpc_path].get('post', {})\n                endpoints.append({\n                    'path': rpc_path,\n                    'method': 'POST',\n                    'tag': 'JSON-RPC',\n                    'summary': jsonrpc.get('summary', 'JSON-RPC endpoint'),\n                    'operationId': jsonrpc.get('operationId', 'jsonRPC_post'),\n                })\n\n    return generate_table(endpoints, config['link_base'])\n\n\ndef inject_table_into_mdx(mdx_path: Path, marker: str, table: str) -> bool:\n    \"\"\"\n    Inject generated table into MDX file between marker comments.\n\n    Markers in MDX should look like:\n    {/* BEGIN_AUTO_GENERATED: API_V2_ENDPOINTS */}\n    {/* END_AUTO_GENERATED: API_V2_ENDPOINTS */}\n    \"\"\"\n    if not mdx_path.exists():\n        print(f\"MDX not found: {mdx_path}\")\n        return False\n\n    content = mdx_path.read_text()\n\n    # Pattern to match the marker block (handles both empty and filled markers)\n    pattern = rf'(\\{{/\\* BEGIN_AUTO_GENERATED: {marker} \\*/\\}})[ \\t]*\\n.*?(\\{{/\\* END_AUTO_GENERATED: {marker} \\*/\\}})'\n\n    if not re.search(pattern, content, re.DOTALL):\n        print(f\"      Markers not found in {mdx_path}\")\n        print(f\"      Add these markers where you want the table:\")\n        print(f\"      {{/* BEGIN_AUTO_GENERATED: {marker} */}}\")\n        print(f\"      {{/* END_AUTO_GENERATED: {marker} */}}\")\n        return False\n\n    # Replace content between markers\n    new_content = re.sub(\n        pattern,\n        rf'\\1\\n{table}\\n\\2',\n        content,\n        flags=re.DOTALL\n    )\n\n    if new_content != content:\n        mdx_path.write_text(new_content)\n        return True\n\n    return False\n\n\ndef find_repo_root() -> Path:\n    \"\"\"Find the repository root (where mint.json is located).\"\"\"\n    current = Path(__file__).resolve().parent\n\n    for parent in [current] + list(current.parents):\n        if (parent / 'mint.json').exists():\n            return parent\n\n    return current.parent\n\n\ndef main():\n    repo_root = find_repo_root()\n\n    for config in SPECS:\n        print(f\"\\nProcessing: {config['spec_path']}\")\n\n        table = process_spec(config, repo_root)\n        if not table:\n            continue\n\n        mdx_path = repo_root / config['mdx_path']\n        marker = config['marker']\n\n        if inject_table_into_mdx(mdx_path, marker, table):\n            print(f\"  Updated {config['mdx_path']}\")\n        else:\n            print(f\"  No changes needed or markers missing\")\n\n    print(\"\\n Done\")\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": ".github/scripts/generate-v3-api-table.py",
    "content": "import re\nfrom pathlib import Path\nfrom collections import defaultdict\n\ntry:\n    import yaml\n    HAS_YAML = True\nexcept ImportError:\n    HAS_YAML = False\n    print(\"PyYAML not installed. Run: pip install pyyaml\")\n    exit(1)\n\nSPEC_PATH = 'ecosystem/api/toncenter/v3.yaml'\nMDX_PATH = 'ecosystem/api/toncenter/v3/overview.mdx'\nMARKER = 'API_V3_ENDPOINTS'\nLINK_BASE = '/ecosystem/api/toncenter/v3'\n\n# Tag display order\nTAG_ORDER = [\n    'accounts',\n    'actions and traces',\n    'blockchain data',\n    'jettons',\n    'nfts',\n    'dns',\n    'multisig',\n    'vesting',\n    'stats',\n    'utils',\n    'api/v2',\n]\n\n# Map tag slugs to Mintlify's actual URL slugs\nTAG_SLUG_MAP = {\n    'api-v2': 'apiv2',\n}\n\n\ndef load_openapi_spec(filepath: Path) -> dict:\n    \"\"\"Load the OpenAPI YAML file.\"\"\"\n    with open(filepath, 'r') as f:\n        return yaml.safe_load(f)\n\n\ndef extract_endpoints(spec: dict) -> list:\n    \"\"\"Extract endpoints from the OpenAPI spec.\"\"\"\n    endpoints = []\n    seen_paths = set()\n    paths = spec.get('paths', {})\n\n    for path, path_item in paths.items():\n        for method in ['get', 'post', 'put', 'patch', 'delete']:\n            if method not in path_item:\n                continue\n\n            operation = path_item[method]\n            tags = operation.get('tags', ['Other'])\n            tag = tags[0] if tags else 'Other'\n\n            # Avoid duplicates\n            if path in seen_paths:\n                continue\n            seen_paths.add(path)\n\n            endpoints.append({\n                'path': path,\n                'method': method.upper(),\n                'tag': tag,\n                'summary': operation.get('summary', ''),\n                'operationId': operation.get('operationId', ''),\n            })\n\n    return endpoints\n\n\ndef generate_mintlify_link(endpoint: dict) -> str:\n    \"\"\"Generate Mintlify documentation link based on summary\"\"\"\n    tag = endpoint['tag'].lower().replace(' ', '-').replace('_', '-').replace('/', '-')\n\n    # Apply tag slug mapping for Mintlify\n    tag = TAG_SLUG_MAP.get(tag, tag)\n\n    summary = endpoint.get('summary', '')\n\n    if summary:\n        slug = summary.lower()\n        slug = re.sub(r'[^a-z0-9\\s-]', '', slug)\n        slug = re.sub(r'\\s+', '-', slug)\n        slug = re.sub(r'-+', '-', slug)\n        slug = slug.strip('-')\n        return f\"{LINK_BASE}/{tag}/{slug}\"\n\n    operation_id = endpoint.get('operationId', '')\n    if operation_id:\n        clean_op_id = operation_id.replace('_get', '').replace('_post', '')\n        slug = re.sub(r'([a-z])([A-Z])', r'\\1-\\2', clean_op_id).lower()\n        return f\"{LINK_BASE}/{tag}/{slug}\"\n\n    path_slug = endpoint['path'].split('/')[-1].lower()\n    return f\"{LINK_BASE}/{tag}/{path_slug}\"\n\n\ndef generate_table(endpoints: list) -> str:\n    \"\"\"Generate markdown table from endpoints.\"\"\"\n    # Group by tag\n    grouped = defaultdict(list)\n    for ep in endpoints:\n        grouped[ep['tag']].append(ep)\n\n    def sort_key(tag):\n        try:\n            return TAG_ORDER.index(tag.lower())\n        except ValueError:\n            return len(TAG_ORDER)\n\n    sorted_tags = sorted(grouped.keys(), key=sort_key)\n\n    lines = [\n        \"| Category | Method | Description |\",\n        \"| -------- | ------ | ----------- |\",\n    ]\n\n    for tag in sorted_tags:\n        for ep in grouped[tag]:\n            method = ep['method']\n            path = ep['path'].replace('/api/v3', '')\n            summary = ep['summary']\n            link = generate_mintlify_link(ep)\n\n            # Handle tag display\n            display_tag = tag\n            if tag.lower() == 'api/v2':\n                display_tag = 'Legacy (v2)'\n            elif tag.islower():\n                display_tag = tag.capitalize()\n\n            method_display = f\"[`{method} {path}`]({link})\"\n\n            lines.append(f\"| **{display_tag}** | {method_display} | {summary} |\")\n\n    return '\\n'.join(lines)\n\n\ndef inject_table_into_mdx(mdx_path: Path, table: str) -> bool:\n    \"\"\"Inject generated table into MDX file between marker comments.\"\"\"\n    if not mdx_path.exists():\n        print(f\"   MDX not found: {mdx_path}\")\n        return False\n\n    content = mdx_path.read_text()\n\n    # Pattern to match the marker block\n    pattern = rf'(\\{{/\\* BEGIN_AUTO_GENERATED: {MARKER} \\*/\\}})[ \\t]*\\n.*?(\\{{/\\* END_AUTO_GENERATED: {MARKER} \\*/\\}})'\n\n    if not re.search(pattern, content, re.DOTALL):\n        print(f\"      Markers not found in {mdx_path}\")\n        print(f\"      Add these markers where you want the table:\")\n        print(f\"      {{/* BEGIN_AUTO_GENERATED: {MARKER} */}}\")\n        print(f\"      {{/* END_AUTO_GENERATED: {MARKER} */}}\")\n        return False\n\n    new_content = re.sub(\n        pattern,\n        rf'\\1\\n{table}\\n\\2',\n        content,\n        flags=re.DOTALL\n    )\n\n    if new_content != content:\n        mdx_path.write_text(new_content)\n        return True\n\n    return False\n\n\ndef find_repo_root() -> Path:\n    \"\"\"Find the repository root\"\"\"\n    current = Path(__file__).resolve().parent\n\n    for parent in [current] + list(current.parents):\n        if (parent / 'docs.json').exists():\n            return parent\n\n    return current.parent\n\n\ndef main():\n    repo_root = find_repo_root()\n\n    spec_path = repo_root / SPEC_PATH\n    mdx_path = repo_root / MDX_PATH\n\n    print(f\"\\n Processing: {SPEC_PATH}\")\n\n    if not spec_path.exists():\n        print(f\"Spec not found: {spec_path}\")\n        return\n\n    spec = load_openapi_spec(spec_path)\n    endpoints = extract_endpoints(spec)\n\n    print(f\"    Found {len(endpoints)} endpoints\")\n\n    table = generate_table(endpoints)\n\n    if inject_table_into_mdx(mdx_path, table):\n        print(f\"   Updated {MDX_PATH}\")\n    else:\n        print(f\"   No changes needed or markers missing\")\n\n    print(\"\\n Done\")\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": ".github/scripts/rewrite_review_links.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Convert repo-relative doc links in the review body to absolute blob URLs.\"\"\"\n\nfrom __future__ import annotations\n\nimport os\nimport re\nimport sys\n\n\ndef main() -> None:\n    text = sys.stdin.read()\n    if not text:\n        sys.stdout.write(text)\n        return\n\n    repo = os.environ.get(\"GITHUB_REPOSITORY\")\n    sha = os.environ.get(\"PR_HEAD_SHA\")\n    if not repo:\n        sys.stdout.write(text)\n        return\n\n    blob_prefix = f\"https://github.com/{repo}/blob/\"\n    doc_blob_prefix = f\"{blob_prefix}{sha or 'main'}/\"\n    style_blob_prefix = f\"{blob_prefix}main/\"\n    style_rel = \"contribute/style-guide-extended.mdx\"\n\n    def absolutize_location(path: str) -> str:\n        if path.startswith(\"http://\") or path.startswith(\"https://\"):\n            return path\n        normalized = path.lstrip(\"./\")\n        base = style_blob_prefix if normalized.startswith(style_rel) else doc_blob_prefix\n        return f\"{base}{normalized}\"\n\n    lines: list[str] = []\n    for line in text.splitlines():\n        stripped = line.lstrip()\n        indent_len = len(line) - len(stripped)\n        for marker in (\"- Location:\", \"Location:\", \"* Location:\"):\n            if stripped.startswith(marker):\n                prefix, _, rest = stripped.partition(\":\")\n                link = rest.strip()\n                if link:\n                    link = absolutize_location(link)\n                    stripped = f\"{prefix}: {link}\"\n                    line = \" \" * indent_len + stripped\n                break\n        lines.append(line)\n\n    rewritten = \"\\n\".join(lines)\n\n    style_pattern = re.compile(rf\"{re.escape(style_rel)}\\?plain=1#L\\d+(?:-L\\d+)?\")\n\n    def replace_style_links(text: str) -> str:\n        result: list[str] = []\n        last = 0\n        for match in style_pattern.finditer(text):\n            start, end = match.span()\n            result.append(text[last:start])\n            link = match.group(0)\n            prefix_start = max(0, start - len(style_blob_prefix))\n            if text[prefix_start:start] == style_blob_prefix:\n                result.append(link)\n            else:\n                result.append(f\"{style_blob_prefix}{link.lstrip('./')}\")\n            last = end\n        result.append(text[last:])\n        return \"\".join(result)\n\n    rewritten = replace_style_links(rewritten)\n\n    # Ensure any doc blob URLs use the PR head SHA (style guide stays on main)\n    if sha:\n        doc_prefix_regex = re.compile(rf\"{re.escape(blob_prefix)}([^/]+)/([^\\s)]+)\")\n\n        def fix_doc(match: re.Match[str]) -> str:\n            base = match.group(1)\n            remainder = match.group(2)\n            target = \"main\" if remainder.startswith(style_rel) else sha\n            if base == target:\n                return match.group(0)\n            return f\"{blob_prefix}{target}/{remainder}\"\n\n        rewritten = doc_prefix_regex.sub(fix_doc, rewritten)\n\n    sys.stdout.write(rewritten)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": ".github/scripts/tvm-instruction-gen.py",
    "content": "import json\nimport os\nimport sys\nimport textwrap\nimport mistletoe\n\nWORKSPACE_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))\nMDX_PATH = os.path.join(WORKSPACE_ROOT, \"tvm\", \"instructions.mdx\")\n\nSTART_MARK = \"{/* STATIC_START tvm_instructions */}\"\nEND_MARK = \"{/* STATIC_END tvm_instructions */}\"\n\n\ndef humanize_category(key):\n    if not key:\n        return \"Uncategorized\"\n    words = [p.capitalize() for p in key.replace(\"_\", \" \").split() if p]\n    return \" \".join(words) or \"Uncategorized\"\n\n\ndef render_alias(alias):\n    return f\"\"\"\n- `{alias['mnemonic']}`<br />\n{textwrap.indent(alias['description'].replace('\\n', '<br />'), \"  \")}\n\"\"\".strip()\n\n\ndef render_instruction(insn, aliases):\n    return f\"\"\"\n#### `{insn['doc']['opcode']}` {insn['mnemonic']}\n\n{insn['doc']['description'].replace('\\n', '<br />')}<br />\n**Category:** {humanize_category(insn['doc']['category'])} ({insn['doc']['category']})<br />\n\n```fift Fift\n{insn['doc']['fift']}\n```\n\n{'**Aliases**:' if aliases else ''}\n{'\\n'.join(render_alias(alias) for alias in aliases)}\n\"\"\".strip()\n\n\ndef render_static_mdx(spec):\n    return '\\n\\n'.join(render_instruction(insn, [alias for alias in spec['aliases'] if alias['alias_of'] == insn['mnemonic']]) for insn in spec['instructions'])\n\n\ndef inject_into_mdx(mdx_path, new_block):\n    with open(mdx_path, \"r\", encoding=\"utf-8\") as fh:\n        src = fh.read()\n    start_idx = src.find(START_MARK)\n    end_idx = src.find(END_MARK) + len(END_MARK)\n    if start_idx == -1 or end_idx == -1 or end_idx <= start_idx:\n        raise RuntimeError(\"Static markers not found or malformed in instructions.mdx\")\n\n    # Preserve everything outside markers; replace inside with marker + newline + content + newline + end marker\n    before = src[: start_idx + len(START_MARK)]\n    after = src[end_idx:]\n\n    # Hide the static block in the rendered page to avoid duplicating the\n    # interactive table. Keeping it in the DOM still enables full-text search.\n    wrapped_block = f\"<div hidden>\\n{new_block}\\n</div>\"\n    replacement = f\"{START_MARK}\\n{wrapped_block}\\n{END_MARK}\"\n\n    updated = before + replacement[len(START_MARK):] + after\n\n    with open(mdx_path, \"w\", encoding=\"utf-8\") as fh:\n        fh.write(updated)\n\n\ndef generate(spec_input_path, spec_output_path, instructions_mdx_path):\n    with open(spec_input_path) as f:\n        spec = json.load(f)\n    static_block = render_static_mdx(spec)\n    inject_into_mdx(instructions_mdx_path, static_block)\n    update_doc_cp0(spec, spec_output_path)\n\n\ndef update_doc_cp0(spec, spec_output_path):\n    for insn in spec['instructions']:\n        doc = insn['doc']\n        doc['description'] = mistletoe.markdown(doc['description'])\n    for alias in spec['aliases']:\n        alias['description'] = mistletoe.markdown(alias['description'])\n    with open(spec_output_path, 'w', encoding='utf-8') as f:\n        json.dump(spec, f, ensure_ascii=False, separators=(',', ':'))\n\n\nif __name__ == \"__main__\":\n    if len(sys.argv) != 4:\n        print(f\"Usage: {sys.argv[0]} <cp0-input-path> <cp0-output-path> <instructions-mdx-path>\")\n        sys.exit(1)\n    generate(sys.argv[1], sys.argv[2], sys.argv[3])\n"
  },
  {
    "path": ".github/workflows/bouncer.yml",
    "content": "name: 🏀 Bouncer\n# aka 🚪 Supervisor\n\nenv:\n  # additions only\n  MAX_ADDITIONS: 600\n  # many target issues usually mean bigger pull requests\n  MAX_ISSUES_PER_PR: 3\n\non:\n  pull_request_target: # do NOT use actions/checkout!\n    # any branches\n    branches: [\"**\"]\n    # on creation, on new commits, and description edits\n    types: [opened, synchronize, edited]\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}-bouncer\n  cancel-in-progress: true\n\npermissions:\n  contents: read\n  pull-requests: write\n\njobs:\n  enforce-smaller-requests:\n    name: \"PR is manageable\"\n    runs-on: ubuntu-latest\n    steps:\n      - name: Check if a number of additions modulo filtered files is within the threshold\n        id: stats\n        uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0\n        with:\n          script: |\n            const maxAdditions = Number(process.env.MAX_ADDITIONS ?? '600');\n            await exec.exec('sleep 0.5s');\n            const { data: files } = await github.rest.pulls.listFiles({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              pull_number: context.payload.pull_request.number,\n              per_page: 100,\n            });\n            const filtered = files.filter((f) =>\n              f.filename.match(/\\.mdx?$/) !== null &&\n              !f.filename.startsWith('tvm/instructions.mdx') &&\n              !f.filename.startsWith('snippets'),\n            );\n            const additions = filtered.reduce((acc, it) => acc + it.additions, 0);\n            if (additions > maxAdditions) {\n              core.setOutput('trigger', 'true');\n            } else {\n              core.setOutput('trigger', 'false');\n            }\n\n      - name: ${{ steps.stats.outputs.trigger == 'true' && 'An opened PR is too big to be reviewed at once!' || '...' }}\n        if: github.event.action == 'opened' && steps.stats.outputs.trigger == 'true'\n        uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0\n        with:\n          script: |\n            await exec.exec('sleep 0.5s');\n            await github.rest.issues.createComment({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              issue_number: context.payload.pull_request.number,\n              body: [\n                'Thank you for the contribution!',\n                [\n                  'Unfortunately, it is too large, with over ${{ env.MAX_ADDITIONS }} added lines,',\n                  'excluding some generated or otherwise special files.',\n                  'Thus, this pull request is challenging to review and iterate on.',\n                ].join(' '),\n                [\n                  'Please split the PR into several smaller ones and consider',\n                  'reverting any unrelated changes, writing less, or approaching',\n                  'the problem in the issue from a different angle.',\n                ].join(' '),\n                [\n                  'I look forward to your next submissions.',\n                  'If you still intend to proceed as is, then you are at the mercy of the reviewers.',\n                ].join(' '),\n              ].join('\\n\\n'),\n            });\n            process.exit(1);\n\n      - name: ${{ steps.stats.outputs.trigger == 'true' && 'Some change in the PR made it too big!' || '...' }}\n        if: github.event.action != 'opened' && steps.stats.outputs.trigger == 'true'\n        uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0\n        with:\n          script: |\n            core.setFailed([\n              [\n                'This pull request has gotten over ${{ env.MAX_ADDITIONS }} added lines,',\n                'which can be challenging to review and iterate on',\n                'Please, decrease the size of this PR or consider splitting it into several smaller requests.'\n              ].join(' '),\n              [\n                'Until then, the CI will be soft-marked as failed.',\n                'If you still intend to proceed as is, then you are at the mercy of the reviewers.',\n              ].join(' '),\n            ].join('\\n\\n'));\n            process.exit(1);\n\n  enforce-better-descriptions:\n    name: \"Title and description\"\n    runs-on: ubuntu-latest\n    steps:\n      # pr title check\n      - name: \"Check that the title conforms to the simplified version of Conventional Commits\"\n        if: ${{ !cancelled() }}\n        uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0\n        with:\n          script: |\n            const title = context.payload.pull_request.title;\n            const types = 'feat|fix|chore|refactor|test';\n            const pattern = new RegExp(`^(revert: )?(${types})(?:\\\\/(${types}))?!?(\\\\([^\\\\)]+\\\\))?!?: [a-zA-Z].{1,200}`);\n            const matches = title.match(pattern) !== null;\n            if (!matches) {\n              core.setFailed([\n                'Title of this pull request does not conform to the simplified version of Conventional Commits used in the documentation',\n                `Received: ${title}`,\n                'Expected to find a type of: feat, fix, chore, refactor, or test, followed by the parts outlined here: https://www.conventionalcommits.org/en/v1.0.0/',\n              ].join('\\n'));\n              process.exit(1);\n            }\n\n      # pr close issue limits\n      - name: \"Check that there is no more than ${{ env.MAX_ISSUES_PER_PR }} linked issues\"\n        if: ${{ !cancelled() && github.event.pull_request.user.login != 'dependabot[bot]' }}\n        uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0\n        with:\n          script: |\n            const maxIssuesAllowed = Number(process.env.MAX_ISSUES_PER_PR ?? '3');\n            const body = context.payload.pull_request.body || '';\n            const closePatterns = /\\b(?:close[sd]?|fixes|fixed|fix|resolve[sd]?|towards):?\\s+(?:https?:\\/\\/github\\.com\\/|[a-z0-9\\-\\_\\/]*#\\d+)/gi;\n            const issueCount = [...body.matchAll(closePatterns)].length;\n            if (issueCount > maxIssuesAllowed) {\n              core.setFailed(`This pull request attempts to close ${issueCount} issues, while the maximum number allowed is ${maxIssuesAllowed}.`);\n              process.exit(1);\n            }\n            const changelogPattern = /\\bchange\\s*log:?\\s+https?:\\/\\/.*?\\.mdx?/gi;\n            const hasChangelog = body.match(changelogPattern) !== null;\n            if (issueCount === 0 && !hasChangelog) {\n              core.setFailed([\n                'This pull request does not resolve any issues — no close patterns found in the description.',\n                'Please, specify an issue by writing `Closes #that-issue-number` in the description of this PR.',\n                'If there is no such issue, create a new one: https://github.com/ton-org/docs/issues/1366#issuecomment-3560650817',\n                '\\nIf this PR updates descriptions in accordance with a new release of a tool,',\n                'provide a changelog by writing `Changelog https://....md` in the description of this PR.',\n              ].join(' '));\n              process.exit(1);\n            }\n"
  },
  {
    "path": ".github/workflows/commander.yml",
    "content": "# Listens to new comments with /commands and acts accordingly\nname: 📡 Commander\n\nenv:\n  HUSKY: 0\n  NODE_VERSION: 20\n\non:\n  issue_comment:\n    types: [created]\n  pull_request_review_comment:\n    types: [created]\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}-commander\n  cancel-in-progress: true\n\npermissions:\n  contents: read\n  pull-requests: write\n\njobs:\n  fmt:\n    name: \"Fix formatting\"\n    runs-on: ubuntu-latest\n    if: |\n      (\n        github.event_name == 'pull_request_review_comment' ||\n        (\n          github.event_name == 'issue_comment' &&\n          github.event.issue.pull_request != null\n        )\n      ) &&\n      contains(fromJSON('[\"OWNER\", \"MEMBER\", \"COLLABORATOR\"]'), github.event.comment.author_association) &&\n      (startsWith(github.event.comment.body, '/fmt ') || github.event.comment.body == '/fmt')\n    steps:\n      # This is done cautiously to confirm whether the comment comes from a PR that is a fork.\n      # If so, all other steps are skipped and nothing important is run afterwards.\n      - name: Gather PR context in env variables\n        env:\n          FROM_PR: ${{ github.event.pull_request.number }}\n          FROM_ISSUE: ${{ github.event.issue.number }}\n        uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0\n        with:\n          script: |\n            const fs = require('node:fs');\n            const prNumRaw = process.env.FROM_PR ?? process.env.FROM_ISSUE ?? '';\n            const prNum = Number(prNumRaw);\n            if (isNaN(prNum) || prNum <= 0 || prNum >= 1e20) {\n              console.error(`PR number was not provided or is invalid: ${prNumRaw}`);\n              process.exit(1);\n            }\n            core.exportVariable('PR_NUMBER', prNumRaw);\n            const { data: pr } = await github.rest.pulls.get({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              pull_number: prNum,\n            });\n            core.exportVariable('BASE_REF', pr.base.ref);\n            core.exportVariable('HEAD_REF', pr.head.ref);\n            const headRepo = pr.head.repo?.full_name ?? '';\n            const thisRepo = `${context.repo.owner}/${context.repo.repo}`;\n            if (headRepo === '' && headRepo !== thisRepo) {\n              core.exportVariable('IS_FORK', 'true');\n              core.notice('This job does not run in forks for a vast number of reasons. Please, apply the necessary fixes yourself.');\n            } else {\n              core.exportVariable('IS_FORK', 'false');\n            }\n\n      - name: Checkout the PR branch\n        if: env.IS_FORK != 'true'\n        uses: actions/checkout@v4\n        with:\n          ref: ${{ env.HEAD_REF }}\n          fetch-depth: 0\n\n      - name: Setup Node.js\n        if: env.IS_FORK != 'true'\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ env.NODE_VERSION }}\n          cache: \"npm\"\n\n      - name: Install dependencies\n        if: env.IS_FORK != 'true'\n        run: |\n          corepack enable\n          npm ci\n\n      - name: Get changed MDX and Markdown files\n        if: env.IS_FORK != 'true'\n        id: changed-files\n        uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47\n        with:\n          files: |\n            **.md\n            **.mdx\n          separator: \" \"\n          base_sha: ${{ env.BASE_REF }}\n\n      - name: Apply formatting\n        if: env.IS_FORK != 'true'\n        id: fix-fmt\n        env:\n          ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}\n        uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0\n        with:\n          script: |\n            const files = (process.env.ALL_CHANGED_FILES ?? '')\n              .trim().split(' ').filter(Boolean).filter((it) => it.match(/\\.mdx?$/) !== null);\n            if (files.length === 0) {\n              console.log('\\nNo such files affected!');\n              process.exit(0);\n            }\n            try {\n              await exec.exec('npm', ['run', 'check:fmt:some', '--', ...files], {\n                silent: true, // >/dev/null 2>&1\n              });\n              console.log('\\nNo issues');\n              core.setOutput('changes', 'false');\n            } catch (_) {\n              console.log('\\nFound issues, fixing...');\n              await exec.exec('npm', ['run', 'fmt:some', '--', ...files], {\n                silent: true, // >/dev/null 2>&1\n              });\n              core.setOutput('changes', 'true');\n            }\n\n      - name: Commit changes, if any\n        if: env.IS_FORK != 'true' && steps.fix-fmt.outputs.changes == 'true'\n        uses: stefanzweifel/git-auto-commit-action@28e16e81777b558cc906c8750092100bbb34c5e3 # v7.0.0\n        with:\n          commit_message: \"fix: formatting\"\n          branch: ${{ env.HEAD_REF }}\n"
  },
  {
    "path": ".github/workflows/generate-api-tables.yml",
    "content": "name: Generate API Tables\n\nenv:\n  PYTHON_VERSION: \"3.11\"\n  NODE_VERSION: \"20\"\n\non:\n  push:\n    paths:\n      - 'ecosystem/api/toncenter/v2.json'\n      - 'ecosystem/api/toncenter/v3.yaml'\n    branches:\n      - main\n\npermissions:\n  contents: write\n\njobs:\n  generate:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: actions/setup-python@v5\n        with:\n          python-version: ${{ env.PYTHON_VERSION }}\n\n      - uses: actions/setup-node@v4\n        with:\n          node-version: ${{ env.NODE_VERSION }}\n          cache: \"npm\"\n\n      - name: Install dependencies\n        run: |\n          pip install pyyaml==6.0.3\n          corepack enable\n          npm ci\n\n      - name: Generate tables\n        run: |\n          python3 .github/scripts/generate-v2-api-table.py\n          python3 .github/scripts/generate-v3-api-table.py\n          npm run fmt:some -- ecosystem/api/toncenter/v2/overview.mdx ecosystem/api/toncenter/v3/overview.mdx\n\n      - name: Commit changes\n        run: |\n          git config user.name \"github-actions[bot]\"\n          git config user.email \"github-actions[bot]@users.noreply.github.com\"\n          git add ecosystem/api/toncenter/v2/overview.mdx ecosystem/api/toncenter/v3/overview.mdx\n          git diff --staged --quiet || git commit -m \"chore(bot): auto-generate API tables\"\n          git push\n"
  },
  {
    "path": ".github/workflows/instructions.yml",
    "content": "name: 🕘 Instructions update\n\non:\n  schedule:\n    - cron: '17 3 * * *'\n  workflow_dispatch:\n    inputs:\n      source_branch:\n        description: 'Branch in ton-org/tvm-spec to fetch cp0.json from'\n        required: false\n        default: 'master'\n        type: string\n\npermissions:\n  contents: write\n  pull-requests: write\n\njobs:\n  fetch-and-release:\n    if: ${{ github.event_name == 'workflow_dispatch' || github.repository == 'ton-org/docs' }}\n    runs-on: ubuntu-latest\n    env:\n      SOURCE_BRANCH: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.source_branch || 'master' }}\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v4\n        with:\n          fetch-depth: 0  # needed for pushing later\n\n      - name: Set up Git\n        run: |\n          git config user.name \"github-actions[bot]\"\n          git config user.email \"github-actions[bot]@users.noreply.github.com\"\n\n      - name: Set up Python\n        uses: actions/setup-python@v5\n        with:\n          python-version: '3.x'\n\n      - name: Install Python dependencies\n        run: pip install mistletoe==1.5.0\n\n      - name: Clone ton-org/tvm-spec\n        run: git clone https://github.com/ton-org/tvm-spec && cd tvm-spec && git checkout $SOURCE_BRANCH\n\n      - name: Update instructions.mdx and cp0.json\n        # cp0.txt is a workaround: mintlify gives 404 for url /resources/tvm/cp0.json -_-\n        run: python3 .github/scripts/tvm-instruction-gen.py tvm-spec/cp0.json resources/tvm/cp0.txt tvm/instructions.mdx\n\n      - name: Check for changes\n        id: git-diff\n        run: |\n          git add resources/tvm/cp0.txt tvm/instructions.mdx\n          CHANGED_FILES=$(git diff --cached --name-only | tr '\\n' ' ')\n          echo \"changed=$CHANGED_FILES\" >> $GITHUB_OUTPUT\n\n      - name: Create Pull Request if needed\n        if: ${{ steps.git-diff.outputs.changed != '' }}\n        id: cpr\n        uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c # v6\n        with:\n          commit-message: \"feat: update TVM instructions list\"\n          title: \"feat: update TVM instructions list\"\n          branch: \"update-spec\"\n          add-paths: |\n            resources/tvm/cp0.txt\n            tvm/instructions.mdx\n          token: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/linter.yml",
    "content": "name: 💅 Linting suite\n\nenv:\n  HUSKY: 0\n  NODE_VERSION: 20\n\non:\n  pull_request:\n    branches: [\"**\"]\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}-linter\n  cancel-in-progress: true\n\npermissions:\n  contents: read\n  pull-requests: write\n\njobs:\n  format-check:\n    name: \"Formatting\"\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ env.NODE_VERSION }}\n          cache: \"npm\"\n\n      - name: Install dependencies\n        run: |\n          corepack enable\n          npm ci\n\n      - name: Get changed MDX and Markdown files\n        id: changed-files\n        uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47\n        with:\n          files: |\n            **.md\n            **.mdx\n          separator: \" \"\n\n      - name: Check formatting of MDX and Markdown files\n        id: check-fmt\n        env:\n          ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}\n        uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0\n        with:\n          script: |\n            const files = (process.env.ALL_CHANGED_FILES ?? '')\n              .trim().split(' ').filter(Boolean).filter((it) => it.match(/\\.mdx?$/) !== null);\n            if (files.length === 0) {\n              console.log('\\nNo such files affected!');\n              process.exit(0);\n            }\n            console.log('\\nChecking formatting of the following MDX and Markdown files affected by this PR:\\n');\n            for (const file of files) {\n              console.log(`- ${file}`);\n            }\n            try {\n              await exec.exec('npm', ['run', 'check:fmt:some', '--', ...files], {\n                silent: true, // >/dev/null 2>&1\n              });\n            } catch (_) {\n              // Comment right in the actions output\n              console.log('\\n\\x1b[31mError:\\x1b[0m Some files are not properly formatted!');\n              console.log('1. Install necessary dependencies: \\x1b[31mnpm ci\\x1b[0m');\n              console.log(`2. Run this command to fix the issues: \\x1b[31mnpm run fmt:some -- ${files.join(' ')}\\x1b[0m`);\n\n              // Rethrow the exit code of the failed formatting check\n              core.setFailed('Some files are not properly formatted!');\n              process.exit(1);\n            }\n\n      - name: Hide prior PR comments and issue a new one in case of failure\n        if: |\n          (\n            !cancelled() &&\n            steps.changed-files.conclusion == 'success' &&\n            github.event_name == 'pull_request' &&\n            (\n              github.event.pull_request.head.repo.fork == false ||\n              github.event.pull_request.head.repo.full_name == github.repository\n            )\n          )\n        env:\n          ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}\n          SUCCESS: ${{ steps.check-fmt.conclusion == 'failure' && 'false' || 'true' }}\n        uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0\n        with:\n          script: |\n            const { hidePriorCommentsWithPrefix, createComment } = await import('${{ github.workspace }}/.github/scripts/common.mjs');\n            const success = JSON.parse(process.env.SUCCESS ?? 'false');\n            const files = (process.env.ALL_CHANGED_FILES ?? '')\n              .trim().split(' ').filter(Boolean).filter((it) => it.match(/\\.mdx?$/) !== null);\n            const comment = [\n              'To fix the **formatting** issues:\\n',\n              '1. Install necessary dependencises: `npm ci`',\n              '2. Then, run this command:',\n              '   ```shell',\n              `   npm run fmt:some -- ${files.join(' ')}`,\n              '   ```',\n              '\\nAlternatively, a maintainer can comment /fmt in this PR to auto-apply fixes in a new commit from the bot.',\n            ].join('\\n');\n            const prefix = comment.slice(0, 30);\n            await hidePriorCommentsWithPrefix({ github, context, exec, prefix, resolved: success });\n            // Create a new PR comment in case of a new failure\n            if (!success) {\n              await createComment({ github, context, exec, body: comment });\n            }\n\n  spell-check:\n    name: \"Spelling\"\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v4\n        # The fetch-depth is not set to 0 to prevent the cspell-action\n        # from misfiring on files that are in main but not on this PR branch\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ env.NODE_VERSION }}\n          cache: \"npm\"\n\n      - name: Install dependencies\n        run: |\n          corepack enable\n          npm ci\n\n      - name: Run CSpell on changed files\n        # This action also annotates the PR\n        uses: streetsidesoftware/cspell-action@v7\n        with:\n          check_dot_files: explicit\n          suggestions: true\n          config: \".cspell.jsonc\"\n\n  link-check:\n    name: \"Links: broken, navigation, redirects\"\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ env.NODE_VERSION }}\n          cache: \"npm\"\n\n      - name: Install dependencies\n        run: |\n          corepack enable\n          npm ci\n\n      # Broken\n\n      - name: Check broken links\n        if: ${{ !cancelled() }}\n        run: npm run check:links\n\n      # Navigation\n\n      - name: Check uniqueness of navigation paths in docs.json\n        if: ${{ !cancelled() }}\n        run: npm run check:navigation -- unique\n\n      - name: Check existence of navigation .mdx pages in docs.json\n        if: ${{ !cancelled() }}\n        run: npm run check:navigation -- exist\n\n      - name: Check coverage of .mdx pages by docs.json\n        if: ${{ !cancelled() }}\n        run: npm run check:navigation -- cover\n\n      # Redirects\n\n      - name: Check uniqueness of redirect sources in docs.json\n        if: ${{ !cancelled() }}\n        run: npm run check:redirects -- unique\n\n      - name: Check existence of redirect destinations in docs.json\n        if: ${{ !cancelled() }}\n        run: npm run check:redirects -- exist\n\n      - name: Check redirects against the previous TON Documentation\n        if: ${{ !cancelled() }}\n        run: npm run check:redirects -- previous\n\n      - name: Check redirects against the upstream docs.json structure\n        if: ${{ !cancelled() }}\n        run: npm run check:redirects -- upstream\n"
  },
  {
    "path": ".github/workflows/pitaya.yml",
    "content": "name: 🤖 AI review\n\non:\n  pull_request:\n    types: [opened, ready_for_review]\n  issue_comment:\n    types: [created]\n  pull_request_review_comment:\n    types: [created]\n  pull_request_target:\n    types: [opened]\n\npermissions:\n  contents: read\n  pull-requests: write\n  issues: write\n\njobs:\n  fork-pr-note:\n    if: github.event_name == 'pull_request_target' && github.event.action == 'opened' && github.event.pull_request.head.repo.full_name != github.repository\n    runs-on: ubuntu-latest\n    steps:\n      - name: Comment external PR use /review\n        env:\n          GITHUB_TOKEN: ${{ github.token }}\n        run: |\n          set -euo pipefail\n          PR_NUMBER=\"${{ github.event.pull_request.number }}\"\n          API=\"https://api.github.com/repos/${{ github.repository }}/issues/${PR_NUMBER}/comments\"\n          BODY=$(cat <<'TXT'\n          Skipping AI review because this PR is from a fork. A maintainer can start the review by commenting /review in this PR.\n          TXT\n          )\n          jq -n --arg body \"$BODY\" '{body:$body}' > payload.json\n          curl -sS -X POST \"$API\" \\\n            -H \"Authorization: Bearer ${GITHUB_TOKEN}\" \\\n            -H \"Accept: application/vnd.github+json\" \\\n            -H \"X-GitHub-Api-Version: 2022-11-28\" \\\n            -H \"Content-Type: application/json\" \\\n            -d @payload.json >/dev/null\n\n  pr-review:\n    concurrency:\n      group: pitaya-ai-review-${{ github.event.pull_request.number || github.event.issue.number || github.run_id }}\n      cancel-in-progress: true\n    # Run on:\n    # - PR events when ready_for_review or opened as non‑draft\n    # - Issue comments only when it's a PR thread, command is /review, and commenter is trusted\n    if: |\n      (\n        github.event_name == 'pull_request' &&\n        ((github.event.action == 'ready_for_review') || (github.event.action == 'opened' && github.event.pull_request.draft == false)) &&\n        github.event.pull_request.head.repo.full_name == github.repository\n      ) ||\n      (\n        github.event_name == 'issue_comment' &&\n        github.event.issue.pull_request != null &&\n        (github.event.comment.body == '/review' || startsWith(github.event.comment.body, '/review ')) &&\n        (\n          github.event.comment.author_association == 'OWNER' ||\n          github.event.comment.author_association == 'MEMBER' ||\n          github.event.comment.author_association == 'COLLABORATOR'\n        )\n      ) ||\n      (\n        github.event_name == 'pull_request_review_comment' &&\n        (github.event.comment.body == '/review' || startsWith(github.event.comment.body, '/review ')) &&\n        (\n          github.event.comment.author_association == 'OWNER' ||\n          github.event.comment.author_association == 'MEMBER' ||\n          github.event.comment.author_association == 'COLLABORATOR'\n        )\n      )\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n\n      - name: PR context\n        env:\n          GH_TOKEN: ${{ github.token }}\n          PR_FROM_PR: ${{ github.event.pull_request.number }}\n          PR_FROM_ISSUE: ${{ github.event.issue.number }}\n        run: |\n          set -euo pipefail\n          PR_NUMBER=\"${PR_FROM_PR:-}\"\n          if [ -z \"${PR_NUMBER:-}\" ] || [ \"$PR_NUMBER\" = \"null\" ]; then\n            PR_NUMBER=\"${PR_FROM_ISSUE:-}\"\n          fi\n          if [ -z \"${PR_NUMBER:-}\" ] || [ \"$PR_NUMBER\" = \"null\" ]; then\n            echo \"PR number not provided.\" >&2\n            exit 1\n          fi\n          echo \"PR_NUMBER=$PR_NUMBER\" >> $GITHUB_ENV\n          gh api repos/${{ github.repository }}/pulls/${PR_NUMBER} > pr.json\n          echo \"BASE_REF=$(jq -r '.base.ref' pr.json)\" >> $GITHUB_ENV\n          echo \"HEAD_REF=$(jq -r '.head.ref' pr.json)\" >> $GITHUB_ENV\n          BASE_REPO=\"${{ github.repository }}\"\n          HEAD_REPO=\"$(jq -r '.head.repo.full_name // \"\"' pr.json)\"\n          if [ -n \"$HEAD_REPO\" ] && [ \"$HEAD_REPO\" != \"$BASE_REPO\" ]; then\n            echo \"IS_FORK=true\" >> $GITHUB_ENV\n          else\n            echo \"IS_FORK=false\" >> $GITHUB_ENV\n          fi\n\n      - name: React 👀 on PR\n        env:\n          GH_TOKEN: ${{ github.token }}\n          REPO: ${{ github.repository }}\n        run: |\n          set -euo pipefail\n          rid=\"\"\n          if ! rid=$(gh api \\\n            -X POST \\\n            -H \"X-GitHub-Api-Version: 2022-11-28\" \\\n            \"/repos/${REPO}/issues/${PR_NUMBER}/reactions\" \\\n            -f content=eyes \\\n            --jq '.id // empty' 2>/dev/null); then\n            echo \"::warning::Failed to add 👀 reaction to PR ${PR_NUMBER}.\" >&2\n          fi\n          if [ -n \"${rid:-}\" ]; then\n            echo \"PR_REACTION_EYES_ID=$rid\" >> \"$GITHUB_ENV\"\n          fi\n\n      - name: React 👀 on comment\n        if: github.event_name == 'issue_comment'\n        env:\n          GH_TOKEN: ${{ github.token }}\n          REPO: ${{ github.repository }}\n          COMMENT_ID: ${{ github.event.comment.id }}\n        run: |\n          set -euo pipefail\n          rid=\"\"\n          if ! rid=$(gh api \\\n            -X POST \\\n            -H \"X-GitHub-Api-Version: 2022-11-28\" \\\n            \"/repos/${REPO}/issues/comments/${COMMENT_ID}/reactions\" \\\n            -f content=eyes \\\n            --jq '.id // empty' 2>/dev/null); then\n            echo \"::warning::Failed to add 👀 reaction to comment ${COMMENT_ID}.\" >&2\n          fi\n          if [ -n \"${rid:-}\" ]; then\n            echo \"ISSUE_COMMENT_REACTION_EYES_ID=$rid\" >> \"$GITHUB_ENV\"\n          fi\n\n      - name: React 👀 on inline comment\n        if: github.event_name == 'pull_request_review_comment'\n        env:\n          GH_TOKEN: ${{ github.token }}\n          REPO: ${{ github.repository }}\n          COMMENT_ID: ${{ github.event.comment.id }}\n        run: |\n          set -euo pipefail\n          rid=\"\"\n          if ! rid=$(gh api \\\n            -X POST \\\n            -H \"X-GitHub-Api-Version: 2022-11-28\" \\\n            \"/repos/${REPO}/pulls/comments/${COMMENT_ID}/reactions\" \\\n            -f content=eyes \\\n            --jq '.id // empty' 2>/dev/null); then\n            echo \"::warning::Failed to add 👀 reaction to review comment ${COMMENT_ID}.\" >&2\n          fi\n          if [ -n \"${rid:-}\" ]; then\n            echo \"REVIEW_COMMENT_REACTION_EYES_ID=$rid\" >> \"$GITHUB_ENV\"\n          fi\n\n      - name: Checkout PR head\n        run: |\n          set -euo pipefail\n          git fetch origin \"pull/${PR_NUMBER}/head:pr_head\"\n          git checkout -B pr_head pr_head\n\n      - name: Fetch branches\n        run: git fetch origin \"+refs/heads/*:refs/remotes/origin/*\"\n\n      - name: Ensure base branch\n        run: |\n          BASE_REF=\"${BASE_REF:-main}\"\n          if ! git show-ref --verify --quiet \"refs/heads/${BASE_REF}\"; then\n            git branch --track \"${BASE_REF}\" \"origin/${BASE_REF}\" || true\n          fi\n\n      - name: Use repo scripts\n        if: env.IS_FORK != 'true'\n        run: |\n          set -euo pipefail\n          echo \"USING_TRUSTED_CI_SCRIPTS=$GITHUB_WORKSPACE/.github/scripts\" >> $GITHUB_ENV\n\n      - name: Use base scripts for forks\n        if: env.IS_FORK == 'true'\n        run: |\n          set -euo pipefail\n          mkdir -p \"$RUNNER_TEMP/ai-ci\"\n          git show \"$BASE_REF\":.github/scripts/build_review_instructions.py > \"$RUNNER_TEMP/ai-ci/build_review_instructions.py\"\n          git show \"$BASE_REF\":.github/scripts/build_review_payload.py > \"$RUNNER_TEMP/ai-ci/build_review_payload.py\"\n          echo \"USING_TRUSTED_CI_SCRIPTS=$RUNNER_TEMP/ai-ci\" >> $GITHUB_ENV\n\n      - name: Detect docs changes\n        run: |\n          set -euo pipefail\n          # Compare PR head against BASE_REF and look for docs changes\n          CHANGED=$(git diff --name-only \"$BASE_REF\"...pr_head | grep -E '(\\.(md|mdx)$|^docs\\.json$)' || true)\n          if [ -z \"$CHANGED\" ]; then\n            echo \"DOCS_CHANGED=false\" >> $GITHUB_ENV\n            echo \"No docs (.md, .mdx, docs.json) changes detected; skipping AI review.\" >&2\n          else\n            echo \"DOCS_CHANGED=true\" >> $GITHUB_ENV\n            echo \"$CHANGED\" | sed 's/^/- /' >&2\n          fi\n\n      - name: Comment no docs changes\n        if: env.DOCS_CHANGED != 'true'\n        env:\n          GITHUB_TOKEN: ${{ github.token }}\n        run: |\n          set -euo pipefail\n          API=\"https://api.github.com/repos/${{ github.repository }}/issues/${PR_NUMBER}/comments\"\n          BODY=$(cat <<'TXT'\n          Skipping AI review because no docs changes in md, mdx, or docs.json\n          TXT\n          )\n          jq -n --arg body \"$BODY\" '{body:$body}' > payload.json\n          curl -sS -X POST \"$API\" \\\n            -H \"Authorization: Bearer ${GITHUB_TOKEN}\" \\\n            -H \"Accept: application/vnd.github+json\" \\\n            -H \"X-GitHub-Api-Version: 2022-11-28\" \\\n            -H \"Content-Type: application/json\" \\\n            -d @payload.json >/dev/null\n\n      - name: Check secrets\n        if: env.DOCS_CHANGED == 'true' && (env.IS_FORK != 'true' || github.event_name != 'pull_request')\n        env:\n          OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}\n        run: |\n          if [ -z \"${OPENROUTER_API_KEY:-}\" ]; then\n            echo \"OPENROUTER_API_KEY is not set. Add it to repository secrets.\" >&2\n            exit 2\n          fi\n\n      - name: Setup Python\n        if: env.DOCS_CHANGED == 'true' && (env.IS_FORK != 'true' || github.event_name != 'pull_request')\n        uses: actions/setup-python@v5\n        with:\n          python-version: \"3.13\"\n\n      - name: Setup uv\n        if: env.DOCS_CHANGED == 'true' && (env.IS_FORK != 'true' || github.event_name != 'pull_request')\n        uses: astral-sh/setup-uv@v3\n\n      - name: Checkout Pitaya\n        if: env.DOCS_CHANGED == 'true' && (env.IS_FORK != 'true' || github.event_name != 'pull_request')\n        uses: actions/checkout@v4\n        with:\n          repository: tact-lang/pitaya\n          path: pitaya-src\n\n      - name: Install Pitaya deps\n        if: env.DOCS_CHANGED == 'true' && (env.IS_FORK != 'true' || github.event_name != 'pull_request')\n        working-directory: pitaya-src\n        run: uv sync\n\n      - name: Build agent image\n        if: env.DOCS_CHANGED == 'true' && (env.IS_FORK != 'true' || github.event_name != 'pull_request')\n        run: docker build -t pitaya-agents:latest pitaya-src\n\n      - name: Run Pitaya review\n        if: env.DOCS_CHANGED == 'true' && (env.IS_FORK != 'true' || github.event_name != 'pull_request')\n        working-directory: pitaya-src\n        env:\n          OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}\n          OPENROUTER_BASE_URL: https://openrouter.ai/api/v1\n        run: |\n          REVIEW_INSTRUCTIONS=$(python3 \"$USING_TRUSTED_CI_SCRIPTS/build_review_instructions.py\")\n\n          uv run pitaya \"Review this pull request\" \\\n            --repo \"$GITHUB_WORKSPACE\" \\\n            --base-branch pr_head \\\n            --strategy pr-review \\\n            -S reviewers=2 \\\n            -S ci_fail_policy=never \\\n            -S base_branch=\"$BASE_REF\" \\\n            -S include_branches=\"pr_head,$BASE_REF\" \\\n            -S review_instructions=\"$REVIEW_INSTRUCTIONS\" \\\n            --plugin codex \\\n            --model \"openai/gpt-5.1\" \\\n            --no-tui \\\n            --verbose\n\n      - name: Post review\n        if: env.DOCS_CHANGED == 'true' && (env.IS_FORK != 'true' || github.event_name != 'pull_request')\n        working-directory: pitaya-src\n        env:\n          GITHUB_TOKEN: ${{ github.token }}\n        run: |\n          set -euo pipefail\n\n          RUN_DIR=\"$(ls -td .pitaya/results/run_* 2>/dev/null | head -n1)\"\n          if [ -z \"${RUN_DIR:-}\" ] || [ ! -d \"$RUN_DIR\" ]; then\n            echo \"No results directory found\" >&2\n            exit 1\n          fi\n\n          # Sidecar must exist (selection may be empty when approving clean PRs)\n          SIDECAR=\"$RUN_DIR/review/index.json\"\n          if [ ! -f \"$SIDECAR\" ]; then\n            echo \"Sidecar not found: $SIDECAR\" >&2\n            exit 1\n          fi\n          COMMIT_ID=\"$(jq -r '.commit_id // empty' \"$SIDECAR\")\"\n          if [ -z \"$COMMIT_ID\" ]; then\n            echo \"commit_id missing in sidecar; aborting.\" >&2\n            exit 1\n          fi\n\n          # Build review payload (summary + inline comments)\n          INLINE_SEVERITIES=\"${INLINE_SEVERITIES:-HIGH}\"  # comma-separated; default HIGH only\n          MAX_COMMENTS=\"${MAX_COMMENTS:-40}\"\n          python3 \"$USING_TRUSTED_CI_SCRIPTS/build_review_payload.py\" \\\n            --run-dir \"$RUN_DIR\" \\\n            --repo \"${{ github.repository }}\" \\\n            --sha \"$COMMIT_ID\" \\\n            --severities \"${INLINE_SEVERITIES}\" \\\n            --max-comments \"${MAX_COMMENTS}\" > review_payload.json\n\n          API=\"https://api.github.com/repos/${{ github.repository }}/pulls/${PR_NUMBER}/reviews\"\n\n          COMMENTS=$(jq -r '.comments | length' review_payload.json)\n          BODY_TEXT=$(jq -r '.body // empty' review_payload.json)\n          if [ \"${BODY_TEXT// }\" = \"\" ]; then\n            BODY_TEXT=\"No documentation issues detected.\"\n            jq --arg body \"$BODY_TEXT\" '.body = $body' review_payload.json > review_payload.tmp && mv review_payload.tmp review_payload.json\n          fi\n\n          echo \"Submitting PR review (comments: $COMMENTS)...\"\n          HTTP_CODE=$(curl -sS -o response.json -w \"%{http_code}\" -X POST \"$API\" \\\n               -H \"Authorization: Bearer ${GITHUB_TOKEN}\" \\\n               -H \"Accept: application/vnd.github+json\" \\\n               -H \"X-GitHub-Api-Version: 2022-11-28\" \\\n               -H \"Content-Type: application/json\" \\\n               -d @review_payload.json || true)\n\n          echo \"GitHub API HTTP: ${HTTP_CODE:-<none>}\"\n          if ! [[ \"$HTTP_CODE\" =~ ^[0-9]{3}$ ]] || [ \"$HTTP_CODE\" -lt 200 ] || [ \"$HTTP_CODE\" -ge 300 ]; then\n            echo \"Response body:\"; cat response.json || true; echo\n\n            # Attempt to submit inline comments individually so good ones still land.\n            COMMENT_API_INLINE=\"https://api.github.com/repos/${{ github.repository }}/pulls/${PR_NUMBER}/comments\"\n            BODY_TEXT=$(jq -r '.body // \"\"' review_payload.json)\n            COMMIT_FOR_COMMENTS=$(jq -r '.commit_id // \"\"' review_payload.json)\n            GOOD=0; BAD=0\n            BAD_SUMMARY_FILE=$(mktemp)\n            : > \"$BAD_SUMMARY_FILE\"\n\n            while IFS= read -r c; do\n              TMP=$(mktemp)\n              echo \"$c\" | jq --arg commit \"$COMMIT_FOR_COMMENTS\" '{\n                body: .body,\n                commit_id: ($commit // .commit_id // \"\"),\n                path: .path\n              } + (if has(\"line\") then {line:.line, side:(.side//\"RIGHT\")} else {} end)\n                + (if has(\"start_line\") then {start_line:.start_line, start_side:(.start_side//\"RIGHT\")} else {} end)' > \"$TMP\"\n\n              HTTP_COMMENT=$(curl -sS -o response_comment.json -w \"%{http_code}\" -X POST \"$COMMENT_API_INLINE\" \\\n                -H \"Authorization: Bearer ${GITHUB_TOKEN}\" \\\n                -H \"Accept: application/vnd.github+json\" \\\n                -H \"X-GitHub-Api-Version: 2022-11-28\" \\\n                -H \"Content-Type: application/json\" \\\n                -d @\"$TMP\" || true)\n\n              if [[ \"$HTTP_COMMENT\" =~ ^2[0-9][0-9]$ ]]; then\n                GOOD=$((GOOD+1))\n              else\n                BAD=$((BAD+1))\n                PATH_LINE=$(echo \"$c\" | jq -r '\"\\(.path):L\\(.start_line // .line // \"?\")-L\\(.line // .start_line // \"?\")\"')\n                BODY_SNIP=$(echo \"$c\" | jq -r '.body')\n                BODY_SNIP_FIRST6=$(printf \"%s\" \"$BODY_SNIP\" | head -n 6)\n                BODY_SNIP_LINECOUNT=$(printf \"%s\\n\" \"$BODY_SNIP\" | wc -l)\n                {\n                  echo \"- ${PATH_LINE}\"\n                  printf \"%s\" \"$BODY_SNIP_FIRST6\" | sed 's/^/  /'\n                  if [ \"$BODY_SNIP_LINECOUNT\" -gt 6 ]; then\n                    echo \"  …(truncated)\"\n                  fi\n                  echo\n                } >> \"$BAD_SUMMARY_FILE\"\n              fi\n              rm -f \"$TMP\" response_comment.json\n            done < <(jq -c '.comments[]' review_payload.json)\n\n            # Build fallback timeline comment containing intro + failed inline text (if any)\n            COMMENT_API=\"https://api.github.com/repos/${{ github.repository }}/issues/${PR_NUMBER}/comments\"\n            FALLBACK_FILE=$(mktemp)\n            {\n              echo \"$BODY_TEXT\"\n              echo\n              echo \"---\"\n              echo \"Per-comment submission: ${GOOD} posted, ${BAD} failed.\"\n              if [ \"$BAD\" -gt 0 ]; then\n                echo\n                echo \"Unposted inline comments (raw text):\"\n                cat \"$BAD_SUMMARY_FILE\"\n              fi\n            } > \"$FALLBACK_FILE\"\n\n            jq -n --arg body \"$(cat \"$FALLBACK_FILE\")\" '{body:$body}' > payload.json\n            HTTP_CODE2=$(curl -sS -o response2.json -w \"%{http_code}\" -X POST \"$COMMENT_API\" \\\n              -H \"Authorization: Bearer ${GITHUB_TOKEN}\" \\\n              -H \"Accept: application/vnd.github+json\" \\\n              -H \"X-GitHub-Api-Version: 2022-11-28\" \\\n              -H \"Content-Type: application/json\" \\\n              -d @payload.json || true)\n            echo \"Fallback GitHub API HTTP: $HTTP_CODE2\"; cat response2.json || true; echo\n            if ! [[ \"$HTTP_CODE2\" =~ ^[0-9]{3}$ ]] || [ \"$HTTP_CODE2\" -lt 200 ] || [ \"$HTTP_CODE2\" -ge 300 ]; then\n              echo \"::error::Failed to submit PR review, per-comment comments, and fallback comment.\" >&2\n              exit 1\n            fi\n            rm -f \"$BAD_SUMMARY_FILE\" \"$FALLBACK_FILE\"\n          fi\n\n      - name: Summary\n        if: env.DOCS_CHANGED == 'true' && (env.IS_FORK != 'true' || github.event_name != 'pull_request')\n        working-directory: pitaya-src\n        run: |\n          set -euo pipefail\n          RUN_DIR=\"$(ls -td .pitaya/results/run_* 2>/dev/null | head -n1)\"\n          if [ -z \"${RUN_DIR:-}\" ]; then\n            exit 0\n          fi\n          SUMMARY_FILE=\"$RUN_DIR/summary.md\"\n          INTRO_FILE=\"$RUN_DIR/review/index.json\"\n          {\n            echo \"### Pitaya Review\"\n            if [ -f \"$INTRO_FILE\" ]; then\n              INTRO=$(jq -r '.intro // empty' \"$INTRO_FILE\")\n              SEL=$(jq -r '.selected_details | length' \"$INTRO_FILE\")\n              EVENT=$(jq -r '.event // empty' \"$INTRO_FILE\"); if [ -z \"$EVENT\" ]; then EVENT=COMMENT; fi\n              COMMIT=$(jq -r '.commit_id // empty' \"$INTRO_FILE\")\n              echo \"\"\n              if [ -n \"$INTRO\" ]; then\n                echo \"$INTRO\"\n                echo \"\"\n              fi\n              echo \"- Outcome $EVENT\"\n              echo \"- Inline suggestions $SEL\"\n              if [ -n \"$COMMIT\" ]; then\n                echo \"- Reviewed commit \\`$COMMIT\\`\"\n              fi\n            fi\n            if [ -f \"$SUMMARY_FILE\" ]; then\n              echo \"\"\n              echo \"<details><summary>Run stats</summary>\"\n              echo \"\"\n              tail -n +2 \"$SUMMARY_FILE\"\n              echo \"</details>\"\n            fi\n          } >> \"$GITHUB_STEP_SUMMARY\"\n\n      - name: Archive logs\n        if: env.DOCS_CHANGED == 'true' && (env.IS_FORK != 'true' || github.event_name != 'pull_request')\n        id: pitaya_artifacts\n        working-directory: pitaya-src\n        run: |\n          set -euo pipefail\n          if compgen -G \".pitaya/logs/run_*\" >/dev/null || compgen -G \".pitaya/results/run_*\" >/dev/null; then\n            tar -czf pitaya-artifacts.tar.gz .pitaya/logs/run_* .pitaya/results/run_* 2>/dev/null || true\n            echo \"has_artifacts=true\" >> \"$GITHUB_OUTPUT\"\n          else\n            echo \"No Pitaya logs or results to archive.\" >&2\n            echo \"has_artifacts=false\" >> \"$GITHUB_OUTPUT\"\n          fi\n\n      - name: Upload artifacts\n        if: env.DOCS_CHANGED == 'true' && (env.IS_FORK != 'true' || github.event_name != 'pull_request') && steps.pitaya_artifacts.outputs.has_artifacts == 'true'\n        uses: actions/upload-artifact@v4\n        with:\n          name: pitaya-logs-${{ github.run_id }}\n          path: pitaya-src/pitaya-artifacts.tar.gz\n          if-no-files-found: ignore\n          retention-days: 7\n\n      - name: Cleanup 👀\n        if: always()\n        env:\n          GH_TOKEN: ${{ github.token }}\n          REPO: ${{ github.repository }}\n          PR_REACTION_EYES_ID: ${{ env.PR_REACTION_EYES_ID }}\n          ISSUE_COMMENT_REACTION_EYES_ID: ${{ env.ISSUE_COMMENT_REACTION_EYES_ID }}\n          REVIEW_COMMENT_REACTION_EYES_ID: ${{ env.REVIEW_COMMENT_REACTION_EYES_ID }}\n          COMMENT_ID: ${{ github.event.comment.id }}\n        run: |\n          set -euo pipefail\n          # Remove from PR\n          if [ -n \"${PR_REACTION_EYES_ID:-}\" ]; then\n            gh api -X DELETE \\\n              -H \"X-GitHub-Api-Version: 2022-11-28\" \\\n              \"/repos/${REPO}/issues/${PR_NUMBER}/reactions/${PR_REACTION_EYES_ID}\" \\\n              >/dev/null 2>&1 || echo \"::warning::Failed to remove 👀 from PR ${PR_NUMBER}.\" >&2\n          fi\n          # Remove from issue comment\n          if [ -n \"${ISSUE_COMMENT_REACTION_EYES_ID:-}\" ] && [ -n \"${COMMENT_ID:-}\" ]; then\n            gh api -X DELETE \\\n              -H \"X-GitHub-Api-Version: 2022-11-28\" \\\n              \"/repos/${REPO}/issues/comments/${COMMENT_ID}/reactions/${ISSUE_COMMENT_REACTION_EYES_ID}\" \\\n              >/dev/null 2>&1 || echo \"::warning::Failed to remove 👀 from issue comment ${COMMENT_ID}.\" >&2\n          fi\n          # Remove from review comment\n          if [ -n \"${REVIEW_COMMENT_REACTION_EYES_ID:-}\" ] && [ -n \"${COMMENT_ID:-}\" ]; then\n            gh api -X DELETE \\\n              -H \"X-GitHub-Api-Version: 2022-11-28\" \\\n              \"/repos/${REPO}/pulls/comments/${COMMENT_ID}/reactions/${REVIEW_COMMENT_REACTION_EYES_ID}\" \\\n              >/dev/null 2>&1 || echo \"::warning::Failed to remove 👀 from review comment ${COMMENT_ID}.\" >&2\n          fi\n"
  },
  {
    "path": ".gitignore",
    "content": "# Vale (spell and style checker)\n.vale/*\n!.vale/config/\n!.vale/NONE/\n\n# Miscellaneous\n.DS_Store\n\n# Editors\n.idea/\n.vscode/\n.helix/\n.vim/\n.nvim/\n.emacs/\n.emacs.d/\n\n# Node.js\nnode_modules/\n\n# Python\n__pycache__\n\n# Generated folders\n/stats/\n"
  },
  {
    "path": ".husky/pre-push",
    "content": ""
  },
  {
    "path": ".prettierignore",
    "content": "*.mdx\n/ecosystem/api/toncenter/v2/\n/ecosystem/api/toncenter/v3/\n/ecosystem/api/toncenter/smc-index/\n/LICENSE*\n"
  },
  {
    "path": ".remarkignore",
    "content": "# Ignore folders\nnode_modules/\n/pending/\n\n# Ignore some whitepapers\n/languages/fift/whitepaper.mdx\n/foundations/whitepapers/tblkch.mdx\n/foundations/whitepapers/ton.mdx\n/foundations/whitepapers/tvm.mdx\n\n# Ignore some root files\n/index.mdx\n/LICENSE*\n\n# Ignore generated files and directories\n/tvm/instructions.mdx\n/ecosystem/api/toncenter/v2/\n/ecosystem/api/toncenter/v3/\n/ecosystem/api/toncenter/smc-index/\n"
  },
  {
    "path": ".remarkrc.mjs",
    "content": "import remarkFrontmatter from 'remark-frontmatter';\nimport remarkGfm from 'remark-gfm';\nimport remarkMath from 'remark-math';\nimport remarkMdx from 'remark-mdx';\nimport unifiedConsistency from 'unified-consistency';\nimport stringWidth from 'string-width';\nimport { visitParents, SKIP } from 'unist-util-visit-parents';\nimport { generate } from 'astring';\n\n/**\n * @import {} from 'remark-stringify'\n * @type import('unified').Preset\n */\nconst remarkConfig = {\n  settings: {\n    bullet: '-',\n    emphasis: '_',\n    rule: '-',\n    incrementListMarker: false,\n    tightDefinitions: true,\n  },\n  plugins: [\n    remarkFrontmatter,\n    remarkMath,\n    [\n      remarkGfm,\n      {\n        singleTilde: false,\n        stringLength: stringWidth,\n      },\n    ],\n    [\n      remarkMdx,\n      {\n        printWidth: 20,\n      },\n    ],\n    function formatJsxElements() {\n      return (tree, file) => {\n        // a JSX element embedded in flow (block)\n        visitParents(tree, 'mdxJsxFlowElement', (node, ancestors) => {\n          try {\n            if (!node.attributes) { return; }\n            for (const attr of node.attributes) {\n              if (\n                attr.type === 'mdxJsxAttribute' &&\n                attr.value?.type === 'mdxJsxAttributeValueExpression' &&\n                attr.value.data?.estree\n              ) {\n                const expr = attr.value;\n\n                // Slighly trim single-line expressions\n                if (typeof expr.value === 'string' && !expr.value.trim().includes('\\n')) {\n                  expr.value = expr.value.trim();\n                  delete expr.data.estree;\n                  continue;\n                }\n\n                // Multi-line expressions\n                if (!expr.data) { continue; }\n                const indent = ancestors.length === 0 ? 0 : ancestors.length;\n                const formatted = generate(expr.data.estree.body[0].expression, {\n                  startingIndentLevel: indent,\n                });\n                expr.value = formatted;\n                delete expr.data.estree;\n              }\n            }\n          } catch (_) {\n            // NOTE: Let's silently do nothing — this is the default behavior anyways\n          }\n        });\n        // a JSX element embedded in text (span, inline)\n        visitParents(tree, 'mdxJsxTextElement', (node) => {\n          try {\n            if (!node.attributes) { return SKIP; }\n            for (const attr of node.attributes) {\n              if (\n                attr.type === 'mdxJsxAttribute' &&\n                attr.value?.type === 'mdxJsxAttributeValueExpression' &&\n                attr.value.data?.estree\n              ) {\n                const expr = attr.value;\n                if (!expr.data) { continue; }\n                const formatted = generate(expr.data.estree.body[0].expression);\n                expr.value = formatted;\n                delete expr.data.estree;\n              }\n            }\n            return SKIP;\n          } catch (_) {\n            // NOTE: Let's silently do nothing — this is the default behavior anyways\n          }\n        });\n        // a JavaScript expression embedded in flow (block)\n        visitParents(tree, 'mdxFlowExpression', (node) => {\n          try {\n            if (!node.data) { return SKIP; }\n            const formatted = generate(node.data.estree.body[0].expression);\n            node.value = formatted;\n            delete node.data.estree;\n            return SKIP;\n          } catch (_) {\n            // NOTE: Let's silently do nothing — this is the default behavior anyways\n          }\n        });\n        // a JavaScript expression embedded in text (span, inline)\n        visitParents(tree, 'mdxTextExpression', (node) => {\n          try {\n            if (!node.data) { return SKIP; }\n            const formatted = generate(node.data.estree.body[0].expression);\n            node.value = formatted;\n            delete node.data.estree;\n            return SKIP;\n          } catch (_) {\n            // NOTE: Let's silently do nothing — this is the default behavior anyways\n            // console.error(\n            //   `Could not format a node in the file ${file.path}: ${JSON.stringify(node)}`\n            // );\n          }\n        });\n      };\n    },\n    unifiedConsistency,\n  ],\n};\n\nexport default remarkConfig;\n"
  },
  {
    "path": "CODEOWNERS",
    "content": ""
  },
  {
    "path": "LICENSE-code",
    "content": "MIT License\n\nCopyright (c) 2025 TON Studio and others\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "LICENSE-docs",
    "content": "Attribution-ShareAlike 4.0 International\n\n=======================================================================\n\nCreative Commons Corporation (\"Creative Commons\") is not a law firm and\ndoes not provide legal services or legal advice. Distribution of\nCreative Commons public licenses does not create a lawyer-client or\nother relationship. Creative Commons makes its licenses and related\ninformation available on an \"as-is\" basis. Creative Commons gives no\nwarranties regarding its licenses, any material licensed under their\nterms and conditions, or any related information. Creative Commons\ndisclaims all liability for damages resulting from their use to the\nfullest extent possible.\n\nUsing Creative Commons Public Licenses\n\nCreative Commons public licenses provide a standard set of terms and\nconditions that creators and other rights holders may use to share\noriginal works of authorship and other material subject to copyright\nand certain other rights specified in the public license below. The\nfollowing considerations are for informational purposes only, are not\nexhaustive, and do not form part of our licenses.\n\n     Considerations for licensors: Our public licenses are\n     intended for use by those authorized to give the public\n     permission to use material in ways otherwise restricted by\n     copyright and certain other rights. Our licenses are\n     irrevocable. Licensors should read and understand the terms\n     and conditions of the license they choose before applying it.\n     Licensors should also secure all rights necessary before\n     applying our licenses so that the public can reuse the\n     material as expected. Licensors should clearly mark any\n     material not subject to the license. This includes other CC-\n     licensed material, or material used under an exception or\n     limitation to copyright. More considerations for licensors:\n    wiki.creativecommons.org/Considerations_for_licensors\n\n     Considerations for the public: By using one of our public\n     licenses, a licensor grants the public permission to use the\n     licensed material under specified terms and conditions. If\n     the licensor's permission is not necessary for any reason--for\n     example, because of any applicable exception or limitation to\n     copyright--then that use is not regulated by the license. Our\n     licenses grant only permissions under copyright and certain\n     other rights that a licensor has authority to grant. Use of\n     the licensed material may still be restricted for other\n     reasons, including because others have copyright or other\n     rights in the material. A licensor may make special requests,\n     such as asking that all changes be marked or described.\n     Although not required by our licenses, you are encouraged to\n     respect those requests where reasonable. More considerations\n     for the public:\n    wiki.creativecommons.org/Considerations_for_licensees\n\n=======================================================================\n\nCreative Commons Attribution-ShareAlike 4.0 International Public\nLicense\n\nBy exercising the Licensed Rights (defined below), You accept and agree\nto be bound by the terms and conditions of this Creative Commons\nAttribution-ShareAlike 4.0 International Public License (\"Public\nLicense\"). To the extent this Public License may be interpreted as a\ncontract, You are granted the Licensed Rights in consideration of Your\nacceptance of these terms and conditions, and the Licensor grants You\nsuch rights in consideration of benefits the Licensor receives from\nmaking the Licensed Material available under these terms and\nconditions.\n\n\nSection 1 -- Definitions.\n\n  a. Adapted Material means material subject to Copyright and Similar\n     Rights that is derived from or based upon the Licensed Material\n     and in which the Licensed Material is translated, altered,\n     arranged, transformed, or otherwise modified in a manner requiring\n     permission under the Copyright and Similar Rights held by the\n     Licensor. For purposes of this Public License, where the Licensed\n     Material is a musical work, performance, or sound recording,\n     Adapted Material is always produced where the Licensed Material is\n     synched in timed relation with a moving image.\n\n  b. Adapter's License means the license You apply to Your Copyright\n     and Similar Rights in Your contributions to Adapted Material in\n     accordance with the terms and conditions of this Public License.\n\n  c. BY-SA Compatible License means a license listed at\n     creativecommons.org/compatiblelicenses, approved by Creative\n     Commons as essentially the equivalent of this Public License.\n\n  d. Copyright and Similar Rights means copyright and/or similar rights\n     closely related to copyright including, without limitation,\n     performance, broadcast, sound recording, and Sui Generis Database\n     Rights, without regard to how the rights are labeled or\n     categorized. For purposes of this Public License, the rights\n     specified in Section 2(b)(1)-(2) are not Copyright and Similar\n     Rights.\n\n  e. Effective Technological Measures means those measures that, in the\n     absence of proper authority, may not be circumvented under laws\n     fulfilling obligations under Article 11 of the WIPO Copyright\n     Treaty adopted on December 20, 1996, and/or similar international\n     agreements.\n\n  f. Exceptions and Limitations means fair use, fair dealing, and/or\n     any other exception or limitation to Copyright and Similar Rights\n     that applies to Your use of the Licensed Material.\n\n  g. License Elements means the license attributes listed in the name\n     of a Creative Commons Public License. The License Elements of this\n     Public License are Attribution and ShareAlike.\n\n  h. Licensed Material means the artistic or literary work, database,\n     or other material to which the Licensor applied this Public\n     License.\n\n  i. Licensed Rights means the rights granted to You subject to the\n     terms and conditions of this Public License, which are limited to\n     all Copyright and Similar Rights that apply to Your use of the\n     Licensed Material and that the Licensor has authority to license.\n\n  j. Licensor means the individual(s) or entity(ies) granting rights\n     under this Public License.\n\n  k. Share means to provide material to the public by any means or\n     process that requires permission under the Licensed Rights, such\n     as reproduction, public display, public performance, distribution,\n     dissemination, communication, or importation, and to make material\n     available to the public including in ways that members of the\n     public may access the material from a place and at a time\n     individually chosen by them.\n\n  l. Sui Generis Database Rights means rights other than copyright\n     resulting from Directive 96/9/EC of the European Parliament and of\n     the Council of 11 March 1996 on the legal protection of databases,\n     as amended and/or succeeded, as well as other essentially\n     equivalent rights anywhere in the world.\n\n  m. You means the individual or entity exercising the Licensed Rights\n     under this Public License. Your has a corresponding meaning.\n\n\nSection 2 -- Scope.\n\n  a. License grant.\n\n       1. Subject to the terms and conditions of this Public License,\n          the Licensor hereby grants You a worldwide, royalty-free,\n          non-sublicensable, non-exclusive, irrevocable license to\n          exercise the Licensed Rights in the Licensed Material to:\n\n            a. reproduce and Share the Licensed Material, in whole or\n               in part; and\n\n            b. produce, reproduce, and Share Adapted Material.\n\n       2. Exceptions and Limitations. For the avoidance of doubt, where\n          Exceptions and Limitations apply to Your use, this Public\n          License does not apply, and You do not need to comply with\n          its terms and conditions.\n\n       3. Term. The term of this Public License is specified in Section\n          6(a).\n\n       4. Media and formats; technical modifications allowed. The\n          Licensor authorizes You to exercise the Licensed Rights in\n          all media and formats whether now known or hereafter created,\n          and to make technical modifications necessary to do so. The\n          Licensor waives and/or agrees not to assert any right or\n          authority to forbid You from making technical modifications\n          necessary to exercise the Licensed Rights, including\n          technical modifications necessary to circumvent Effective\n          Technological Measures. For purposes of this Public License,\n          simply making modifications authorized by this Section 2(a)\n          (4) never produces Adapted Material.\n\n       5. Downstream recipients.\n\n            a. Offer from the Licensor -- Licensed Material. Every\n               recipient of the Licensed Material automatically\n               receives an offer from the Licensor to exercise the\n               Licensed Rights under the terms and conditions of this\n               Public License.\n\n            b. Additional offer from the Licensor -- Adapted Material.\n               Every recipient of Adapted Material from You\n               automatically receives an offer from the Licensor to\n               exercise the Licensed Rights in the Adapted Material\n               under the conditions of the Adapter's License You apply.\n\n            c. No downstream restrictions. You may not offer or impose\n               any additional or different terms or conditions on, or\n               apply any Effective Technological Measures to, the\n               Licensed Material if doing so restricts exercise of the\n               Licensed Rights by any recipient of the Licensed\n               Material.\n\n       6. No endorsement. Nothing in this Public License constitutes or\n          may be construed as permission to assert or imply that You\n          are, or that Your use of the Licensed Material is, connected\n          with, or sponsored, endorsed, or granted official status by,\n          the Licensor or others designated to receive attribution as\n          provided in Section 3(a)(1)(A)(i).\n\n  b. Other rights.\n\n       1. Moral rights, such as the right of integrity, are not\n          licensed under this Public License, nor are publicity,\n          privacy, and/or other similar personality rights; however, to\n          the extent possible, the Licensor waives and/or agrees not to\n          assert any such rights held by the Licensor to the limited\n          extent necessary to allow You to exercise the Licensed\n          Rights, but not otherwise.\n\n       2. Patent and trademark rights are not licensed under this\n          Public License.\n\n       3. To the extent possible, the Licensor waives any right to\n          collect royalties from You for the exercise of the Licensed\n          Rights, whether directly or through a collecting society\n          under any voluntary or waivable statutory or compulsory\n          licensing scheme. In all other cases the Licensor expressly\n          reserves any right to collect such royalties.\n\n\nSection 3 -- License Conditions.\n\nYour exercise of the Licensed Rights is expressly made subject to the\nfollowing conditions.\n\n  a. Attribution.\n\n       1. If You Share the Licensed Material (including in modified\n          form), You must:\n\n            a. retain the following if it is supplied by the Licensor\n               with the Licensed Material:\n\n                 i. identification of the creator(s) of the Licensed\n                    Material and any others designated to receive\n                    attribution, in any reasonable manner requested by\n                    the Licensor (including by pseudonym if\n                    designated);\n\n                ii. a copyright notice;\n\n               iii. a notice that refers to this Public License;\n\n                iv. a notice that refers to the disclaimer of\n                    warranties;\n\n                 v. a URI or hyperlink to the Licensed Material to the\n                    extent reasonably practicable;\n\n            b. indicate if You modified the Licensed Material and\n               retain an indication of any previous modifications; and\n\n            c. indicate the Licensed Material is licensed under this\n               Public License, and include the text of, or the URI or\n               hyperlink to, this Public License.\n\n       2. You may satisfy the conditions in Section 3(a)(1) in any\n          reasonable manner based on the medium, means, and context in\n          which You Share the Licensed Material. For example, it may be\n          reasonable to satisfy the conditions by providing a URI or\n          hyperlink to a resource that includes the required\n          information.\n\n       3. If requested by the Licensor, You must remove any of the\n          information required by Section 3(a)(1)(A) to the extent\n          reasonably practicable.\n\n  b. ShareAlike.\n\n     In addition to the conditions in Section 3(a), if You Share\n     Adapted Material You produce, the following conditions also apply.\n\n       1. The Adapter's License You apply must be a Creative Commons\n          license with the same License Elements, this version or\n          later, or a BY-SA Compatible License.\n\n       2. You must include the text of, or the URI or hyperlink to, the\n          Adapter's License You apply. You may satisfy this condition\n          in any reasonable manner based on the medium, means, and\n          context in which You Share Adapted Material.\n\n       3. You may not offer or impose any additional or different terms\n          or conditions on, or apply any Effective Technological\n          Measures to, Adapted Material that restrict exercise of the\n          rights granted under the Adapter's License You apply.\n\n\nSection 4 -- Sui Generis Database Rights.\n\nWhere the Licensed Rights include Sui Generis Database Rights that\napply to Your use of the Licensed Material:\n\n  a. for the avoidance of doubt, Section 2(a)(1) grants You the right\n     to extract, reuse, reproduce, and Share all or a substantial\n     portion of the contents of the database;\n\n  b. if You include all or a substantial portion of the database\n     contents in a database in which You have Sui Generis Database\n     Rights, then the database in which You have Sui Generis Database\n     Rights (but not its individual contents) is Adapted Material,\n     including for purposes of Section 3(b); and\n\n  c. You must comply with the conditions in Section 3(a) if You Share\n     all or a substantial portion of the contents of the database.\n\nFor the avoidance of doubt, this Section 4 supplements and does not\nreplace Your obligations under this Public License where the Licensed\nRights include other Copyright and Similar Rights.\n\n\nSection 5 -- Disclaimer of Warranties and Limitation of Liability.\n\n  a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE\n     EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS\n     AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF\n     ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,\n     IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,\n     WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR\n     PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,\n     ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT\n     KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT\n     ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.\n\n  b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE\n     TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,\n     NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,\n     INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,\n     COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR\n     USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN\n     ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR\n     DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR\n     IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.\n\n  c. The disclaimer of warranties and limitation of liability provided\n     above shall be interpreted in a manner that, to the extent\n     possible, most closely approximates an absolute disclaimer and\n     waiver of all liability.\n\n\nSection 6 -- Term and Termination.\n\n  a. This Public License applies for the term of the Copyright and\n     Similar Rights licensed here. However, if You fail to comply with\n     this Public License, then Your rights under this Public License\n     terminate automatically.\n\n  b. Where Your right to use the Licensed Material has terminated under\n     Section 6(a), it reinstates:\n\n       1. automatically as of the date the violation is cured, provided\n          it is cured within 30 days of Your discovery of the\n          violation; or\n\n       2. upon express reinstatement by the Licensor.\n\n     For the avoidance of doubt, this Section 6(b) does not affect any\n     right the Licensor may have to seek remedies for Your violations\n     of this Public License.\n\n  c. For the avoidance of doubt, the Licensor may also offer the\n     Licensed Material under separate terms or conditions or stop\n     distributing the Licensed Material at any time; however, doing so\n     will not terminate this Public License.\n\n  d. Sections 1, 5, 6, 7, and 8 survive termination of this Public\n     License.\n\n\nSection 7 -- Other Terms and Conditions.\n\n  a. The Licensor shall not be bound by any additional or different\n     terms or conditions communicated by You unless expressly agreed.\n\n  b. Any arrangements, understandings, or agreements regarding the\n     Licensed Material not stated herein are separate from and\n     independent of the terms and conditions of this Public License.\n\n\nSection 8 -- Interpretation.\n\n  a. For the avoidance of doubt, this Public License does not, and\n     shall not be interpreted to, reduce, limit, restrict, or impose\n     conditions on any use of the Licensed Material that could lawfully\n     be made without permission under this Public License.\n\n  b. To the extent possible, if any provision of this Public License is\n     deemed unenforceable, it shall be automatically reformed to the\n     minimum extent necessary to make it enforceable. If the provision\n     cannot be reformed, it shall be severed from this Public License\n     without affecting the enforceability of the remaining terms and\n     conditions.\n\n  c. No term or condition of this Public License will be waived and no\n     failure to comply consented to unless expressly agreed to by the\n     Licensor.\n\n  d. Nothing in this Public License constitutes or may be interpreted\n     as a limitation upon, or waiver of, any privileges and immunities\n     that apply to the Licensor or You, including from the legal\n     processes of any jurisdiction or authority.\n\n\n=======================================================================\n\nCreative Commons is not a party to its public\nlicenses. Notwithstanding, Creative Commons may elect to apply one of\nits public licenses to material it publishes and in those instances\nwill be considered the “Licensor.” The text of the Creative Commons\npublic licenses is dedicated to the public domain under the CC0 Public\nDomain Dedication. Except for the limited purpose of indicating that\nmaterial is shared under a Creative Commons public license or as\notherwise permitted by the Creative Commons policies published at\ncreativecommons.org/policies, Creative Commons does not authorize the\nuse of the trademark \"Creative Commons\" or any other trademark or logo\nof Creative Commons without its prior written consent including,\nwithout limitation, in connection with any unauthorized modifications\nto any of its public licenses or any other arrangements,\nunderstandings, or agreements concerning use of licensed material. For\nthe avoidance of doubt, this paragraph does not form part of the\npublic licenses.\n\nCreative Commons may be contacted at creativecommons.org.\n"
  },
  {
    "path": "README.md",
    "content": "# TON Docs\n\n**[Follow the full quickstart guide](https://www.mintlify.com/docs/quickstart)**\n\n## Development\n\nInstall the [Mintlify CLI](https://www.npmjs.com/package/mint) to preview your documentation changes locally. To install it alongside the necessary dependencies, use the following command:\n\n```shell\nnpm ci\n```\n\nTo start a local preview, run the following command at the root of your documentation, where your `docs.json` is located:\n\n```shell\nnpm start\n```\n\nView your local preview at `http://localhost:3000`.\n\n### Spell checks\n\n> \\[!NOTE]\n> Automatic spelling checks are performed for changed files in each Pull Request.\n\nTo check spelling of **all** files, run:\n\n```shell\nnpm run check:spell\n\n# or simply:\n\nnpm run spell\n```\n\nTo check spelling of some **selected** files, run:\n\n```shell\nnpm run spell:some <FILES...>\n```\n\n#### Adding new words to the spellchecking dictionary\n\nThe dictionaries (or vocabularies) for custom words are placed under `resources/dictionaries`. There, each dictionary describes additional allowed or invalid entries.\n\nThe primary dictionary is `resources/dictionaries/custom.txt` — extend it in case a word exists in American English but was flagged by CSpell as invalid, or in cases where the word does not exist and shall be prohibited. For the latter, add words to `resources/dictionaries/ban.txt` with the `!` prefix when there are no clear correct replacements.\n\nIf an existing two-letter word was flagged as forbidden, remove it from the `resources/dictionaries/two-letter-words-ban.txt` file. However, if a word happened to be a part of a bigger word, e.g., `CL` in `OpenCL`, do not ban it and instead add the bigger word to the primary dictionary in `resources/dictionaries/custom.txt`.\n\nSee more: [CSpell docs on custom dictionaries](https://cspell.org/docs/dictionaries/custom-dictionaries).\n\n### Format checks\n\n> \\[!NOTE]\n> Automatic formatting checks are performed for changed files in each Pull Request.\n\nTo check formatting of **all** files, run:\n\n```shell\nnpm run check:fmt\n```\n\nTo fix formatting of **all** files, run:\n\n```shell\nnpm run fmt\n```\n\nTo check and fix formatting of some **selected** files, run:\n\n```shell\nnpm run fmt:some <FILES...>\n```\n\n## Using components and snippets\n\nSee the [`snippets/` directory](./snippets) and the corresponding docs in [`contribute/snippets/` MDX files](./contribute/snippets/).\n\n## Publishing changes\n\n[Mintlify's GitHub app](https://dashboard.mintlify.com/settings/organization/github-app) is connected to this repository. Thus, changes are deployed to production automatically after pushing to the default branch (`main`).\n\n## Need help?\n\n### Troubleshooting\n\n- If your dev environment is not running: Run `mint update` to ensure you have the most recent version of the CLI.\n- If a page loads as a 404: Make sure you are running in a folder with a valid `docs.json`.\n\n### Resources\n\n- [Mintlify documentation](https://mintlify.com/docs)\n- [Mintlify community](https://mintlify.com/community)\n\n## License\n\nThis project is dual-licensed:\n\n- All documentation and non-code text are licensed under [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)\n- All code snippets are licensed under [MIT](https://opensource.org/license/mit)\n"
  },
  {
    "path": "contract-dev/blueprint/api.mdx",
    "content": "---\ntitle: \"Blueprint TypeScript API\"\n---\n\nBlueprint exports functions and classes for programmatic interaction with TON smart contracts.\n\n### `tonDeepLink`\n\nGenerates a TON deep-link for transfer.\n\n```typescript\nfunction tonDeepLink(\n  address: Address,\n  amount: bigint,\n  body?: Cell,\n  stateInit?: Cell,\n  testOnly?: boolean\n): string;\n```\n\n**Parameters:**\n\n- `address` — the recipient's TON address\n- `amount` — the amount of nanoTON to send\n- `body` — optional message body as a Cell\n- `stateInit` — optional [`StateInit`](/foundations/messages/deploy) cell for deploying a contract\n- `testOnly` — optional flag to determine output address format\n\n**Returns:** a URL deep link that can be opened in TON wallets\n\n**Example:**\n\n```typescript\nconst link = tonDeepLink(myAddress, 10_000_000n); // 0.01 TON\n// \"ton://transfer/...\"\n```\n\n### `getExplorerLink`\n\nGenerates a link to view a TON address in a selected blockchain explorer.\n\n```typescript\nfunction getExplorerLink(\n  address: string,\n  network: string,\n  explorer: 'tonscan' | 'tonviewer' | 'toncx' | 'dton'\n): string;\n```\n\n**Parameters:**\n\n- `address` — the TON address to view in explorer\n- `network` — the target network (`mainnet` or `testnet`)\n- `explorer` — the desired explorer (`tonscan`, `tonviewer`, `toncx`, `dton`)\n\n**Returns:** a full URL pointing to the address in the selected explorer\n\n**Example:**\n\n```typescript\nconst link = getExplorerLink(\"<ADDR>\", \"testnet\", \"tonscan\");\n// \"https://testnet.tonscan.org/address/EQC...9gA\"\n// <ADDR> — TON address to view.\n```\n\n### `getNormalizedExtMessageHash`\n\nGenerates a normalized hash of an `external-in` message for comparison.\n\n```typescript\nfunction getNormalizedExtMessageHash(message: Message): Buffer;\n```\n\nThis function ensures consistent hashing of external-in messages by following [TEP-467](https://github.com/ton-blockchain/TEPs/blob/8b3beda2d8611c90ec02a18bec946f5e33a80091/text/0467-normalized-message-hash.md).\n\n**Parameters:**\n\n- `message` — the message to be normalized and hashed (must be of type `external-in`)\n\n**Returns:** the hash of the normalized message as `Buffer`\n\n**Throws:** error if the message type is not `external-in`\n\n### `compile`\n\nCompiles a contract using the specified configuration for `tact`, `func`, or `tolk` languages.\n\n```typescript\nasync function compile(name: string, opts?: CompileOpts): Promise<Cell>\n```\n\n**Parameters:**\n\n- `name` — the name of the contract to compile (should correspond to a file named `<name>.compile.ts`)\n- `opts` — optional [`CompileOpts`](#compileopts), including user data passed to hooks\n\n**Returns:** a promise that resolves to the compiled contract code as a `Cell`\n\n**Example:**\n\n```typescript\nimport { compile } from '@ton/blueprint';\n\nasync function main() {\n    const codeCell = await compile('Contract');\n    console.log('Compiled code BoC:', codeCell.toBoc().toString('base64'));\n}\n```\n\n### `libraryCellFromCode`\n\nPacks the resulting code hash into a library cell.\n\n```typescript\nfunction libraryCellFromCode(code: Cell): Cell\n```\n\n**Parameters:**\n\n- `code` — the contract code cell\n\n**Returns:** a library cell containing the code hash\n\n### `NetworkProvider`\n\nInterface representing a network provider for interacting with the TON Blockchain.\n\n```typescript\ninterface NetworkProvider {\n  network(): 'mainnet' | 'testnet' | 'custom';\n  explorer(): Explorer;\n  sender(): SenderWithSendResult;\n  api(): BlueprintTonClient;\n  provider(address: Address, init?: { code?: Cell; data?: Cell }): ContractProvider;\n  isContractDeployed(address: Address): Promise<boolean>;\n  waitForDeploy(address: Address, attempts?: number, sleepDuration?: number): Promise<void>;\n  waitForLastTransaction(attempts?: number, sleepDuration?: number): Promise<void>;\n  getContractState(address: Address): Promise<ContractState>;\n  getConfig(configAddress?: Address): Promise<BlockchainConfig>;\n  open<T extends Contract>(contract: T): OpenedContract<T>;\n  ui(): UIProvider;\n}\n```\n\n#### `network()`\n\n```typescript\nnetwork(): 'mainnet' | 'testnet' | 'custom';\n```\n\n**Returns:** current network type that the provider is connected to\n\n#### `explorer()`\n\n```typescript\nexplorer(): Explorer;\n```\n\n**Returns:** [`Explorer`](#explorer) name for the current network\n\n#### `sender()`\n\n```typescript\nsender(): SenderWithSendResult\n```\n\n**Returns:** the [`SenderWithSendResult`](#senderwithsendresult) instance used for sending transactions\n\n#### `api()`\n\n```typescript\napi(): BlueprintTonClient\n```\n\n**Returns:** the underlying [`BlueprintTonClient`](#blueprinttonclient) API for direct blockchain interactions\n\n#### `provider()`\n\n```typescript\nprovider(address: Address, init?: { code?: Cell; data?: Cell }): ContractProvider\n```\n\nCreates a contract provider for interacting with a contract at the specified address.\n\n**Parameters:**\n\n- `address` — the contract address to interact with\n- `init` — optional contract initialization data\n  - `code` — Contract code cell\n  - `data` — Contract initial data cell\n\n**Returns:** `contractProvider` instance for the specified address\n\n#### `isContractDeployed()`\n\n```typescript\nisContractDeployed(address: Address): Promise<boolean>\n```\n\nChecks whether a contract is deployed at the specified address.\n\n**Parameters:**\n\n- `address` — the contract address to check\n\n**Returns:** promise resolving to `true` if contract is deployed, `false` otherwise\n\n**Usage example:**\n\n```typescript\nexport async function run(provider: NetworkProvider) {\n  const isDeployed = await provider.isContractDeployed(contractAddress);\n  if (!isDeployed) {\n    console.log('Contract not yet deployed');\n  }\n}\n```\n\n#### `waitForDeploy()`\n\n```typescript\nwaitForDeploy(address: Address, attempts?: number, sleepDuration?: number): Promise<void>\n```\n\nWaits for a contract to be deployed by polling the address until the contract appears on-chain.\n\n**Parameters:**\n\n- `address` — the contract address to monitor\n- `attempts` — maximum number of polling attempts (default: 20)\n- `sleepDuration` — delay between attempts in milliseconds (default: 2000)\n\n**Returns:** a promise that resolves when the contract is deployed\n\n**Throws:** error if the contract is not deployed within the specified attempts\n\n**Usage example:**\n\n```typescript\nexport async function run(provider: NetworkProvider) {\n  // Send deployment transaction\n  await contract.sendDeploy(provider.sender(), { value: toNano('0.01') });\n\n  // Wait for deployment to complete\n  await provider.waitForDeploy(contract.address);\n  console.log('Contract deployed successfully');\n}\n```\n\n#### `waitForLastTransaction()`\n\n```typescript\nwaitForLastTransaction(attempts?: number, sleepDuration?: number): Promise<void>\n```\n\nWaits for the last sent transaction to be processed and confirmed on the blockchain.\n\n**Parameters:**\n\n- `attempts` — maximum number of polling attempts (default: 20)\n- `sleepDuration` — delay between attempts in milliseconds (default: 2000)\n\n**Returns:** promise that resolves when the last transaction is confirmed\n\n**Usage example:**\n\n```typescript\nexport async function run(provider: NetworkProvider) {\n  await contract.sendIncrement(provider.sender(), { value: toNano('0.01') });\n  await provider.waitForLastTransaction();\n}\n```\n\n#### `getContractState()`\n\n```typescript\ngetContractState(address: Address): Promise<ContractState>\n```\n\nRetrieves the current state of a contract, including its balance, code, and data.\n\n**Parameters:**\n\n- `address` — the contract address to query\n\n**Returns:** promise resolving to `ContractState`.\n\n**Usage example:**\n\n```typescript\nexport async function run(provider: NetworkProvider) {\n  const state = await provider.getContractState(contractAddress);\n  console.log(`Contract balance: ${fromNano(state.balance)} TON`);\n}\n```\n\n#### `getConfig()`\n\n```typescript\ngetConfig(configAddress?: Address): Promise<BlockchainConfig>\n```\n\nFetches the current blockchain configuration parameters.\n\n**Parameters:**\n\n- `configAddress` — optional config contract address (uses default if not provided)\n\n**Returns:** promise resolving to `BlockchainConfig`\n\n#### `open()`\n\n```typescript\nopen<T extends Contract>(contract: T): OpenedContract<T>\n```\n\nOpens a contract instance for interaction, binding it to the current provider.\n\n**Parameters:**\n\n- `contract` — the contract instance to open\n\n**Returns:** `openedContract` wrapper that enables direct method calls\n\n**Usage example:**\n\n```typescript\nexport async function run(provider: NetworkProvider) {\n  const counter = provider.open(Counter.fromAddress(contractAddress));\n  const currentValue = await counter.getCounter();\n  console.log('Current counter value:', currentValue);\n}\n```\n\n#### `ui()`\n\n```typescript\nui(): UIProvider\n```\n\n**Returns:** [`UIProvider`](#uiprovider) instance for console interactions\n\n**Usage example:**\n\n```typescript\nexport async function run(provider: NetworkProvider) {\n  const ui = provider.ui();\n  ui.write('Deployment starting...');\n  const confirmed = await ui.prompt('Deploy to mainnet?');\n}\n```\n\n### `UIProvider`\n\nInterface for handling user interactions, such as displaying messages, prompting for input, and managing action prompts. This interface abstracts console interactions and can be used in both interactive and automated scenarios.\n\n```typescript\ninterface UIProvider {\n  write(message: string): void;\n  prompt(message: string): Promise<boolean>;\n  inputAddress(message: string, fallback?: Address): Promise<Address>;\n  input(message: string): Promise<string>;\n  choose<T>(message: string, choices: T[], display: (v: T) => string): Promise<T>;\n  setActionPrompt(message: string): void;\n  clearActionPrompt(): void;\n}\n```\n\n#### `write()`\n\n```typescript\nwrite(message: string): void\n```\n\nDisplays a message to the user console.\n\n**Parameters:**\n\n- `message` — the text message to display\n\n**Usage example:**\n\n```typescript\nexport async function run(provider: NetworkProvider) {\n  const ui = provider.ui();\n  ui.write('Starting contract deployment...');\n  ui.write(`Network: ${provider.network()}`);\n}\n```\n\n#### `prompt()`\n\n```typescript\nprompt(message: string): Promise<boolean>\n```\n\nDisplays a yes/no prompt to the user and waits for their response.\n\n**Parameters:**\n\n- `message` — the prompt message to display\n\n**Returns:** promise resolving to `true` for yes, `false` for no\n\n**Usage example:**\n\n```typescript\nexport async function run(provider: NetworkProvider) {\n  const ui = provider.ui();\n  const confirmed = await ui.prompt('Deploy to mainnet? This will cost real TON');\n  if (confirmed) {\n    ui.write('Proceeding with deployment...');\n  } else {\n    ui.write('Deployment cancelled');\n    return;\n  }\n}\n```\n\n#### `inputAddress()`\n\n```typescript\ninputAddress(message: string, fallback?: Address): Promise<Address>\n```\n\nPrompts the user to input a TON address with validation.\n\n**Parameters:**\n\n- `message` — the prompt message to display\n- `fallback` — optional default address to use if user provides empty input\n\n**Returns:** promise resolving to Address object\n\n**Usage example:**\n\n```typescript\nexport async function run(provider: NetworkProvider) {\n  const ui = provider.ui();\n  const targetAddress = await ui.inputAddress(\n    'Enter the contract address to interact with:',\n    Address.parse('EQD4FPq-PRDieyQKkizFTRtSDyucUIqrj0v_zXJmqaDp6_0t') // fallback\n  );\n  ui.write(`Using address: ${targetAddress.toString()}`);\n}\n```\n\n#### `input()`\n\n```typescript\ninput(message: string): Promise<string>\n```\n\nPrompts the user for a text input and returns the entered string.\n\n**Parameters:**\n\n- `message` — the prompt message to display\n\n**Returns:** promise resolving to the user's input as a string\n\n**Usage example:**\n\n```typescript\nexport async function run(provider: NetworkProvider) {\n  const ui = provider.ui();\n  const contractName = await ui.input('Enter the contract name:');\n  ui.write(`Deploying contract: ${contractName}`);\n}\n```\n\n#### `choose()`\n\n```typescript\nchoose<T>(message: string, choices: T[], display: (v: T) => string): Promise<T>\n```\n\nPresents a list of choices to the user and returns the selected option.\n\n**Parameters:**\n\n- `message` — the prompt message to display\n- `choices` — array of options to choose from\n- `display` — function to convert each choice to a display string\n\n**Returns:** promise resolving to the selected choice\n\n**Usage example:**\n\n```typescript\nexport async function run(provider: NetworkProvider) {\n  const ui = provider.ui();\n\n  const networks = ['mainnet', 'testnet'];\n  const selectedNetwork = await ui.choose(\n    'Select deployment network:',\n    networks,\n    (network) => network.toUpperCase()\n  );\n\n  ui.write(`Selected network: ${selectedNetwork}`);\n}\n```\n\n#### `setActionPrompt()`\n\n```typescript\nsetActionPrompt(message: string): void\n```\n\nSets a persistent action prompt that remains visible during operations.\n\n**Parameters:**\n\n- `message` — the action prompt message to display\n\n**Usage example:**\n\n```typescript\nexport async function run(provider: NetworkProvider) {\n  const ui = provider.ui();\n  ui.setActionPrompt('⏳ Waiting for transaction confirmation...');\n\n  await contract.send(provider.sender(), { value: toNano('0.01') }, 'increment');\n  await provider.waitForLastTransaction();\n\n  ui.clearActionPrompt();\n  ui.write('✅ Transaction confirmed');\n}\n```\n\n#### `clearActionPrompt()`\n\n```typescript\nclearActionPrompt(): void\n```\n\nClears the current action prompt, removing it from display.\n\n**Usage example:**\n\n```typescript\nexport async function run(provider: NetworkProvider) {\n  const ui = provider.ui();\n  ui.setActionPrompt('🔄 Processing...');\n\n  // Perform some operation\n  await someAsyncOperation();\n\n  ui.clearActionPrompt();\n  ui.write('Operation completed');\n}\n```\n\n## Type definitions\n\nBlueprint exports several TypeScript types for configuration and compilation options. These types provide type safety and IntelliSense support when working with Blueprint programmatically.\n\n### `CompileOpts`\n\nOptional compilation settings, including user data passed to hooks and compilation flags.\n\n```typescript\ntype CompileOpts = {\n  hookUserData?: any;\n  debugInfo?: boolean;\n  buildLibrary?: boolean;\n};\n```\n\n**Properties:**\n\n- `hookUserData` — optional user data passed to pre/post compile hooks\n- `debugInfo` — enable debug information in compiled output (default: `false`)\n- `buildLibrary` — build as a library instead of a regular contract (default: `false`)\n\n**Usage example:**\n\n```typescript\nimport { compile } from '@ton/blueprint';\n\nconst codeCell = await compile('MyContract', {\n  debugInfo: true,\n  hookUserData: { customFlag: true }\n});\n```\n\n### `CommonCompilerConfig`\n\nBase configuration shared by all compiler types. This interface defines common compilation hooks and options.\n\n```typescript\ntype CommonCompilerConfig = {\n  preCompileHook?: (params: HookParams) => Promise<void>;\n  postCompileHook?: (code: Cell, params: HookParams) => Promise<void>;\n  buildLibrary?: boolean;\n};\n```\n\n**Properties:**\n\n- `preCompileHook` — optional function called before compilation starts (receives [`HookParams`](#hookparams))\n- `postCompileHook` — optional function called after compilation completes (receives compiled `Cell` and [`HookParams`](#hookparams))\n- `buildLibrary` — whether to build as a library (default: `false`)\n\n**Usage example:**\n\n```typescript title=\"./wrappers/MyContract.compile.ts\"\nimport { CompilerConfig } from '@ton/blueprint';\n\nexport const compile: CompilerConfig = {\n  lang: 'func',\n  targets: ['contracts/my_contract.fc'],\n  preCompileHook: async (params) => {\n    console.log('Starting compilation...');\n  },\n  postCompileHook: async (code, params) => {\n    console.log('Compilation completed!');\n  }\n};\n```\n\n### `FuncCompilerConfig`\n\nConfiguration specific to the FunC compiler, including optimization levels and source file specifications.\n\n```typescript\ntype FuncCompilerConfig = {\n  lang?: 'func';\n  optLevel?: number;\n  debugInfo?: boolean;\n} & (\n  | {\n      targets: string[];\n      sources?: SourceResolver | SourcesMap;\n    }\n  | {\n      targets?: string[];\n      sources: SourcesArray;\n    }\n);\n```\n\n**Properties:**\n\n- `lang` — compiler language identifier (optional, defaults to `'func'`)\n- `optLevel` — optimization level (0-2, default: 2)\n- `debugInfo` — include debug information in output\n- `targets` — array of FunC source file paths to compile\n- `sources` — alternative source specification method\n\n**Usage example:**\n\n```typescript title=\"./wrappers/MyContract.compile.ts\"\nimport { CompilerConfig } from '@ton/blueprint';\n\nexport const compile: CompilerConfig = {\n  lang: 'func',\n  targets: [\n    'contracts/imports/stdlib.fc',\n    'contracts/my_contract.fc'\n  ],\n  optLevel: 2,\n  debugInfo: false\n};\n```\n\n### `TolkCompilerConfig`\n\nConfiguration for the Tolk compiler, including optimization and debugging options.\n\n```typescript\ntype TolkCompilerConfig = {\n  lang: 'tolk';\n  entrypoint: string;\n  optimizationLevel?: number;\n  withStackComments?: boolean;\n  withSrcLineComments?: boolean;\n  experimentalOptions?: string;\n};\n```\n\n**Properties:**\n\n- `lang` — compiler language identifier (must be `'tolk'`)\n- `entrypoint` — path to the main Tolk source file\n- `optimizationLevel` — optimization level\n- `withStackComments` — include stack operation comments in Fift output\n- `withSrcLineComments` — include source line comments in Fift output\n- `experimentalOptions` — additional experimental compiler flags\n\n**Usage example:**\n\n```typescript title=\"./wrappers/MyContract.compile.ts\"\nimport { CompilerConfig } from '@ton/blueprint';\n\nexport const compile: CompilerConfig = {\n  lang: 'tolk',\n  entrypoint: 'contracts/my_contract.tolk',\n  optimizationLevel: 2,\n  withStackComments: true,\n  withSrcLineComments: true\n};\n```\n\n### `TactLegacyCompilerConfig`\n\nConfiguration for the Tact compiler (legacy configuration format).\n\n```typescript\ntype TactLegacyCompilerConfig = {\n  lang: 'tact';\n  target: string;\n  options?: Options;\n};\n```\n\n**Properties:**\n\n- `lang` — compiler language identifier (must be `'tact'`)\n- `target` — path to the main Tact source file\n- `options` — additional Tact compiler options\n\n**Usage example:**\n\n```typescript title=\"./wrappers/MyContract.compile.ts\"\nimport { CompilerConfig } from '@ton/blueprint';\n\nexport const compile: CompilerConfig = {\n  lang: 'tact',\n  target: 'contracts/my_contract.tact',\n  options: {\n    debug: false,\n    external: true\n  }\n};\n```\n\n### `HookParams`\n\nParameters passed to compilation hooks, providing context about the compilation process.\n\n```typescript\ntype HookParams = {\n  userData?: any;\n};\n```\n\n**Properties:**\n\n- `userData` — optional user data passed from [`CompileOpts`](#compileopts)\n\n### `SenderWithSendResult`\n\nAn extended sender interface that tracks the result of the last send operation.\n\n```typescript\ninterface SenderWithSendResult extends Sender {\n  readonly lastSendResult?: unknown;\n}\n```\n\n**Properties:**\n\n- `lastSendResult` — optional result from the most recent send operation\n\n### `BlueprintTonClient`\n\nUnion type representing supported TON client implementations.\n\n```typescript\ntype BlueprintTonClient = TonClient4 | TonClient | ContractAdapter | LiteClient;\n```\n\n**Supported clients:**\n\n- `TonClient4` — TON HTTP API v4 client\n- `TonClient` — TON HTTP API v2/v3 client\n- `ContractAdapter` — TON API adapter\n- `LiteClient` — Lite client for direct node communication\n\n### `Explorer`\n\nSupported blockchain explorer types.\n\n```typescript\ntype Explorer = 'tonscan' | 'tonviewer' | 'toncx' | 'dton';\n```\n\n**Supported explorers:**\n\n- `'tonscan'` — Tonscan explorer\n- `'tonviewer'` — Tonviewer explorer (default)\n- `'toncx'` — TON.cx explorer\n- `'dton'` — dTON.io explorer\n\n## Configuration\n\nFor detailed configuration options, refer to the [Blueprint Configuration](/contract-dev/blueprint/config) guide.\n"
  },
  {
    "path": "contract-dev/blueprint/benchmarks.mdx",
    "content": "---\ntitle: \"Benchmarking performance\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\nimport { FenceTable } from \"/snippets/fence-table.jsx\";\n\nIn TON, a contract's performance is defined by its gas consumption, so it's important to design your logic efficiently.\nUnlike many other blockchains, TON also requires you to pay for storing contract data and forwarding messages between contracts.\n\n## Gas consumption\n\nAs you develop and iterate on a contract, even small changes to its logic can affect both gas usage and data size. Monitoring these changes helps ensure that your contract remains efficient and cost-effective.\n\n<Aside type=\"tip\">\n  For a deeper breakdown of how fees work in TON, refer to [Transaction fees](/foundations/fees)\n</Aside>\n\n## Gas metrics reporting\n\nTo simplify tracking changes in gas usage and data size,\nwe’ve introduced a reporting system that lets you collect and compare metrics across different versions of a contract.\n\nTo enable this, write test scenarios that cover the contract’s primary usage patterns and verify expected behavior. This approach is sufficient to gather relevant metrics, which you can later use to compare performance changes after updating the implementation.\n\nBefore running the tests, a store is created to collect metrics from all transactions generated during the tests. After test execution, the collected metrics are supplemented with [ABI information from the snapshot](https://github.com/ton-org/sandbox/blob/main/docs/collect-metric-api.md#abi-auto-mapping), and a report is generated based on this data.\n\nWhile more [metrics are collected](https://github.com/ton-org/sandbox/blob/main/docs/collect-metric-api.md#snapshot-structure), the current report format includes `gasUsed`, `cells`, and `bits`, which correspond to the internal metrics `compute.phase`, `state.code`, and `state.data`.\n\n## Metrics comparison example\n\nTo see how gas metrics can be collected and compared in practice, let’s walk through a complete example.\n\nStart by creating a new project using `npm create ton@latest`:\n\n```bash\nnpm create ton@latest -y -- sample --type func-counter --contractName Sample\ncd sample\n```\n\n**Note:**\n\n- The `-y` flag skips prompts and accepts defaults.\n- `--type` specifies the template (e.g., `func-counter`).\n- `--contractName` sets the contract name.\n\nAlternatively, you can run:\n\n```bash\nnpm create ton@latest sample\n```\n\nThis command scaffolds a project with a basic counter contract at `contracts/sample.fc`.\nIt defines a simple stateful contract that stores an `id` and a `counter` and supports an `increase` operation.\n\n```func title=\"sample.fc\"\n#include \"imports/stdlib.fc\";\n\nconst op::increase = \"op::increase\"c;\nglobal int ctx_id;\nglobal int ctx_counter;\n\n() load_data() impure {\n    var ds = get_data().begin_parse();\n\n    ctx_id = ds~load_uint(32);\n    ctx_counter = ds~load_uint(32);\n\n    ds.end_parse();\n}\n\n() save_data() impure {\n    set_data(\n        begin_cell()\n            .store_uint(ctx_id, 32)\n            .store_uint(ctx_counter, 32)\n            .end_cell()\n    );\n}\n\n() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure {\n    if (in_msg_body.slice_empty?()) { ;; ignore all empty messages\n        return ();\n    }\n\n    slice cs = in_msg_full.begin_parse();\n    int flags = cs~load_uint(4);\n    if (flags & 1) { ;; ignore all bounced messages\n        return ();\n    }\n\n    load_data();\n\n    int op = in_msg_body~load_uint(32);\n    int query_id = in_msg_body~load_uint(64);\n\n    if (op == op::increase) {\n        int increase_by = in_msg_body~load_uint(32);\n        ctx_counter += increase_by;\n        save_data();\n        return ();\n    }\n\n    throw(0xffff);\n}\n\nint get_counter() method_id {\n    load_data();\n    return ctx_counter;\n}\n\nint get_id() method_id {\n    load_data();\n    return ctx_id;\n}\n```\n\n### Generate a gas report\n\nLet’s now generate a gas usage report for the contract.\n\nRun the following command:\n\n```bash\nnpx blueprint test --gas-report\n```\n\nThis runs your tests with gas tracking enabled and outputs a `gas-report.json` with transaction metrics.\n\n<FenceTable>\n  ...\n  PASS  Comparison metric mode: gas depth: 1\n  Gas report write in 'gas-report.json'\n  ┌───────────┬──────────────┬───────────────────────────┐\n  │           │              │          current          │\n  │ Contract  │    Method    ├──────────┬────────┬───────┤\n  │           │              │ gasUsed  │ cells  │ bits  │\n  ├───────────┼──────────────┼──────────┼────────┼───────┤\n  │           │  sendDeploy  │   1937   │   11   │  900  │\n  │           ├──────────────┼──────────┼────────┼───────┤\n  │           │     send     │   515    │   11   │  900  │\n  │  Sample   ├──────────────┼──────────┼────────┼───────┤\n  │           │ sendIncrease │   1937   │   11   │  900  │\n  │           ├──────────────┼──────────┼────────┼───────┤\n  │           │  0x7e8764ef  │   2681   │   11   │  900  │\n  └───────────┴──────────────┴──────────┴────────┴───────┘\n</FenceTable>\n\n### Storage fee calculation\n\nYou can use the `cells` and `bits` values from the report to estimate the **storage fee** for your contract.\nHere’s the formula:\n\n```text\nstorage_fee = ceil(\n                  (account.bits * bit_price\n                  + account.cells * cell_price)\n               * time_delta / 2 ** 16)\n```\n\nTo try this in practice, use the [calculator example](/foundations/fees).\n\n### Regenerate the gas report\n\nNote that the `op::increase` method appears in the report as the raw opcode `0x7e8764ef`.\nTo display a human-readable name in the report, update the generated `contract.abi.json` by replacing the raw opcode with the name **increase** in both the `messages` and `types` sections:\n\n```diff\n--- a/contract.abi.json\n+++ b/contract.abi.json\n@@ -6,13 +6,13 @@\n         \"receiver\": \"internal\",\n         \"message\": {\n           \"kind\": \"typed\",\n-          \"type\": \"0x7e8764ef\"\n+          \"type\": \"increase\"\n         }\n       }\n     ],\n     \"types\": [\n       {\n-        \"name\": \"0x7e8764ef\",\n+        \"name\": \"increase\",\n         \"header\": 2122802415\n       }\n     ],\n```\n\nOnce you've updated the `contract.abi.json` file, rerun the command to regenerate the gas report:\n\n```bash\nnpx blueprint test --gas-report\n```\n\nNow the method name appears in the report as `increase`, making it easier to read:\n\n<FenceTable>\n  ...\n  │           ├──────────────┼──────────┼────────┼───────┤\n  │           │   increase   │   2681   │   11   │  900  │\n  └───────────┴──────────────┴──────────┴────────┴───────┘\n</FenceTable>\n\n### Save a snapshot for future comparison\n\nTo track how gas usage evolves, you can create a named snapshot of the current metrics. This allows you to compare future versions of the contract against this baseline:\n\n```bash\nnpx blueprint snapshot --label \"v1\"\n```\n\nThis creates a snapshot file in `.snapshot/`:\n\n```text\n...\nPASS  Collect metric mode: \"gas\"\nReport write in '.snapshot/1749821319408.json'\n```\n\n### Optimize the contract and compare the metrics\n\nLet’s try a simple optimization — adding the `inline` specifier to some functions.\n\n<Aside type=\"note\">\n  An [inline specifier](/languages/func/functions#inline-specifier) is directly substituted into the code wherever it’s called, which can help reduce gas usage by eliminating the overhead of a function call.\n</Aside>\n\nUpdate your contract like this:\n\n```diff\n--- a/contracts/sample.fc\n+++ b/contracts/sample.fc\n\n-() load_data() impure {\n+() load_data() impure inline {\n\n-() save_data() impure {\n+() save_data() impure inline {\n\n-() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure {\n+() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure inline {\n```\n\nNow regenerate the gas report. Since we already created a snapshot labeled `v1`, this report will include a comparison with the previous version:\n\n```bash\nnpx blueprint test --gas-report\n```\n\nYou see a side-by-side comparison of gas usage before and after the change:\n\n<FenceTable>\n  PASS  Comparison metric mode: gas depth: 2\n  Gas report write in 'gas-report.json'\n  ┌───────────┬──────────────┬─────────────────────────────────────────┬───────────────────────────┐\n  │           │              │                 current                 │            v1             │\n  │ Contract  │    Method    ├──────────────┬───────────┬──────────────┼──────────┬────────┬───────┤\n  │           │              │   gasUsed    │   cells   │     bits     │ gasUsed  │ cells  │ bits  │\n  ├───────────┼──────────────┼──────────────┼───────────┼──────────────┼──────────┼────────┼───────┤\n  │           │  sendDeploy  │  1937 same   │ 7 -36.36% │ 1066 +18.44% │   1937   │   11   │  900  │\n  │           ├──────────────┼──────────────┼───────────┼──────────────┼──────────┼────────┼───────┤\n  │           │     send     │ 446 -13.40%  │ 7 -36.36% │ 1066 +18.44% │   515    │   11   │  900  │\n  │  Sample   ├──────────────┼──────────────┼───────────┼──────────────┼──────────┼────────┼───────┤\n  │           │ sendIncrease │  1937 same   │ 7 -36.36% │ 1066 +18.44% │   1937   │   11   │  900  │\n  │           ├──────────────┼──────────────┼───────────┼──────────────┼──────────┼────────┼───────┤\n  │           │   increase   │ 1961 -26.86% │ 7 -36.36% │ 1066 +18.44% │   2681   │   11   │  900  │\n  └───────────┴──────────────┴──────────────┴───────────┴──────────────┴──────────┴────────┴───────┘\n</FenceTable>\n\n## Project setup instructions\n\nIf your project already exists, you need to configure **jest** to collect gas metrics.\nYou can do this in one of two ways:\n\n#### Option 1: update the existing `jest.config.ts`\n\nAdd the necessary environment and reporter settings:\n\n```diff title=\"jest.config.ts\"\nimport type { Config } from 'jest';\n\nconst config: Config = {\n    preset: 'ts-jest',\n+    testEnvironment: '@ton/sandbox/jest-environment',\n    testPathIgnorePatterns: ['/node_modules/', '/dist/'],\n+    reporters: [\n+        'default',\n+        ['@ton/sandbox/jest-reporter', {}],\n+    ]\n};\n\nexport default config;\n```\n\n<Aside type=\"tip\">\n  See the full list of options in the [Sandbox jest config docs](https://github.com/ton-org/sandbox/blob/main/README.md#setup-in-jestconfigts).\n</Aside>\n\n#### Option 2: create a separate config `gas-report.config.ts`\n\nIf you prefer not to modify your main `jest.config.ts`, you can create a dedicated config file:\n\n```ts title=\"gas-report.config.ts\"\nimport config from './jest.config';\n\n// use filter tests if needed, see https://jestjs.io/docs/cli#--testnamepatternregex\n// config.testNamePattern = '^Foo should increase counter$'\nconfig.testEnvironment = '@ton/sandbox/jest-environment'\nconfig.reporters = [\n    ['@ton/sandbox/jest-reporter', {\n    }],\n]\nexport default config;\n```\n\nWhen using this separate config, pass it using the `--config` option:\n\n```bash\nnpx blueprint test --gas-report -- --config gas-report.config.ts\nnpx blueprint snapshot --label \"v2\" -- --config gas-report.config.ts\n```\n\n## Collect metrics manually\n\nYou can collect metrics manually using the low-level API from `@ton/sandbox`.\n\n```typescript title=\"collect-metrics.ts\"\nimport {\n    Blockchain,\n    createMetricStore,\n    makeSnapshotMetric,\n    resetMetricStore\n} from '@ton/sandbox';\n\nconst store = createMetricStore();\n\nasync function someDo() {\n    const blockchain = await Blockchain.create();\n    const [alice, bob] = await blockchain.createWallets(2);\n    await alice.send({ to: bob.address, value: 1 });\n}\n\nasync function main() {\n    resetMetricStore();\n    await someDo();\n    const metric = makeSnapshotMetric(store);\n    console.log(metric);\n}\n\nmain().catch((error) => {\n    console.log(error.message);\n});\n```\n\nFor more details, see the [Collect Metric API documentation](https://github.com/ton-org/sandbox/blob/main/docs/collect-metric-api.md#example).\n"
  },
  {
    "path": "contract-dev/blueprint/cli.mdx",
    "content": "---\ntitle: \"Blueprint CLI\"\n---\n\nBlueprint is a CLI tool for TON smart contract development. This reference covers all available commands, options, configuration, and API methods.\n\n## CLI commands\n\nBlueprint provides a comprehensive set of CLI commands for smart contract development, testing, and deployment. Commands support both interactive and non-interactive modes.\n\n### `create`\n\n```bash\nnpx blueprint create <CONTRACT> --type <TYPE>\n```\n\nCreates a new smart contract with all necessary files, including the contract source, TypeScript wrapper, test file, and deployment script.\n\n#### Interactive mode\n\n```bash\nnpx blueprint create\n```\n\nLaunches an interactive wizard that guides you through:\n\n1. Contract name selection (validates CamelCase format)\n1. Programming language choice (Tolk, FunC, or Tact)\n1. Template type selection (empty or counter example)\n\n#### Non-interactive mode\n\n```bash\nnpx blueprint create <CONTRACT> --type <TYPE>\n```\n\n**Parameters:**\n\n- `<CONTRACT>` — contract name in CamelCase format (e.g., `MyAwesomeContract`)\n- `<TYPE>` — template type from available options\n\n**Available template types:**\n\n- `tolk-empty` — an empty contract (Tolk)\n- `func-empty` — an empty contract (FunC)\n- `tact-empty` — an empty contract (Tact)\n- `tolk-counter` — a simple counter contract (Tolk)\n- `func-counter` — a simple counter contract (FunC)\n- `tact-counter` — a simple counter contract (Tact)\n\n**Usage examples:**\n\n```bash\n# Create empty Tolk contract\nnpx blueprint create MyToken --type tolk-empty\n\n# Create Tolk counter example\nnpx blueprint create SimpleCounter --type tolk-counter\n\n# Create contract interactively\nnpx blueprint create\n```\n\n**Generated files:**\n\n- `contracts/MyContract.{tolk|fc|tact}` — contract source code\n- `wrappers/MyContract.ts` — TypeScript wrapper for contract interaction\n- `tests/MyContract.spec.ts` — Jest test suite with basic test cases\n- `scripts/deployMyContract.ts` — deployment script with network configuration\n\n### `build`\n\n```bash\nnpx blueprint build <CONTRACT> --all\n```\n\nCompiles smart contracts using their corresponding `.compile.ts` configuration files.\n\n#### Interactive mode\n\n```bash\nnpx blueprint build\n```\n\nDisplays a list of all available contracts with `.compile.ts` files for selection. Shows compilation status and allows building individual contracts or all at once.\n\n#### Non-interactive mode\n\n```bash\nnpx blueprint build <CONTRACT>\nnpx blueprint build --all\n```\n\n**Parameters:**\n\n- `<CONTRACT>` — specific contract name to build (matches the `.compile.ts` filename)\n- `--all` — build all contracts in the project that have compilation configurations\n\n**Usage examples:**\n\n```bash\n# Build specific contract\nnpx blueprint build MyToken\n\n# Build all contracts\nnpx blueprint build --all\n\n# Interactive selection\nnpx blueprint build\n```\n\nFor detailed information about build artifacts, see [Compiled Artifacts](/contract-dev/blueprint/develop#compiled-artifacts).\n\n### `run`\n\n```bash\nnpx blueprint run <SCRIPT> <ARGS...> <OPTIONS>\n```\n\nExecutes TypeScript scripts from the `scripts/` directory with full network provider access. Commonly used for contract deployment, interaction, and maintenance tasks.\n\n#### Interactive mode\n\n```bash\nnpx blueprint run\n```\n\nDisplays a list of all available scripts in the `scripts/` directory to select from.\n\n#### Non-interactive mode\n\n```bash\nnpx blueprint run <SCRIPT> <ARGS...>\n```\n\n**Parameters:**\n\n- `<SCRIPT>` — script name (without `.ts` extension)\n- `<ARGS...>` — optional arguments passed to the script\n- `--<NETWORK>` — network selection (`mainnet`, `testnet`)\n- `--<DEPLOY_METHOD>` — deployment method (`tonconnect`, `mnemonic`)\n\n**Network options:**\n\n- `--mainnet` — use TON Mainnet\n- `--testnet` — use TON Testnet\n- `--custom <URL>` — use custom network endpoint\n- `--custom-version <VERSION>` — API version (`v2`, `v4`)\n- `--custom-type <TYPE>` — network type (`custom`, `mainnet`, `testnet`)\n- `--custom-key <KEY>` — API key (`v2 only`)\n\n**Deploy options:**\n\n- `--tonconnect` — use TON Connect for deployment\n- `--deeplink` — use deep link for deployment\n- `--mnemonic` — use mnemonic for deployment\n\n**Explorer options:**\n\n- `--tonscan` — use Tonscan explorer\n- `--tonviewer` — use Tonviewer explorer (default)\n- `--toncx` — use TON.cx explorer\n- `--dton` — use dTON explorer\n\n**Usage examples:**\n\n```bash\n# Deploy contract to testnet with TON Connect\nnpx blueprint run deployCounter --testnet --tonconnect\n\n# Deploy to testnet with mnemonic\nnpx blueprint run deployCounter --testnet --mnemonic\n\n# Run script with custom arguments\nnpx blueprint run updateConfig arg1 arg2 --testnet\n\n# Use custom network configuration\nnpx blueprint run deployContract \\\n  --custom https://toncenter.com/api/v2/jsonRPC \\\n  --custom-version v2 \\\n  --custom-type mainnet \\\n  --custom-key <YOUR_API_KEY>\n```\n\n- `<YOUR_API_KEY>` — API key for the selected provider (`v2` only).\n\n**Requirements:**\n\n- Scripts must be located in the `scripts/` directory\n- Script files must export a `run` function:\n\n```typescript\nimport { NetworkProvider } from '@ton/blueprint';\n\nexport async function run(provider: NetworkProvider, args: string[]) {\n\n}\n```\n\n**Environment variables:**\n\nFor mnemonic-based deployments, configure these [environment variables](#environment-variables).\n\n### `test`\n\nRun the full project test suite with all `.spec.ts` files.\n\n#### Basic usage\n\n```bash\nnpx blueprint test\n```\n\nRun all test files in the `tests/` directory.\n\n#### Collecting coverage\n\n```bash\nnpx blueprint test --coverage\n```\n\nRun tests and collect coverage into the `coverage/` directory.\n\n#### Gas reporting\n\n```bash\nnpx blueprint test --gas-report\n# or\nnpx blueprint test -g\n```\n\nRun tests and compare with the last snapshot's metrics.\n\n#### Specific test file\n\n```bash\nnpx blueprint test <CONTRACT_NAME>\n```\n\n**Examples:**\n\n```bash\nnpx blueprint test\nnpx blueprint test MyContract\n```\n\n**Test file requirements:**\n\n- Test files should be located in the `tests/` directory\n- Use `.spec.ts` extension\n- Supports standard Jest syntax and matchers\n\n### `verify`\n\nVerify a deployed contract using [TON Contract Verifier](https://verifier.ton.org).\n\n#### Basic usage\n\n```bash\nnpx blueprint verify\n```\n\nInteractive mode to select the contract and network.\n\n#### Non-interactive mode\n\n```bash\nnpx blueprint verify <CONTRACT> --network <NETWORK>\n```\n\n**Parameters:**\n\n- `<CONTRACT>` — contract name to verify\n- `--network <NETWORK>` — network (`mainnet`, `testnet`)\n- `--compiler-version <VERSION>` — compiler version used for building\n- `--custom <URL>` — custom network endpoint\n- `--custom-version <VERSION>` — API version (`v2` default)\n- `--custom-type <TYPE>` — network type (`mainnet`, `testnet`)\n- `--custom-key <KEY>` — API key (`v2` only)\n\n**Examples:**\n\n```bash\nnpx blueprint verify MyContract --network mainnet\nnpx blueprint verify MyContract --network testnet --compiler-version 0.4.4-newops.1\n```\n\n**Custom network verification:**\n\n```bash\nnpx blueprint verify MyContract \\\n  --custom https://toncenter.com/api/v2/jsonRPC \\\n  --custom-version v2 \\\n  --custom-type mainnet \\\n  --custom-key <YOUR_API_KEY> \\\n  --compiler-version 0.4.4-newops.1\n```\n\n### `help`\n\nShow detailed help.\n\n```bash\nnpx blueprint help\nnpx blueprint help <COMMAND>\n```\n\n**Examples:**\n\n```bash\nnpx blueprint help\nnpx blueprint help create\nnpx blueprint help run\n```\n\n### `set`\n\nSets language versions.\n\n```bash\nnpx blueprint set <KEY> <VALUE>\n```\n\n**Available keys:**\n\n- `func` — overrides `@ton-community/func-js-bin` version\n\n### `convert`\n\nConverts legacy bash build scripts to Blueprint wrappers.\n\n```bash\nnpx blueprint convert <PATH_TO_BUILD_SCRIPT>\n```\n\n### `rename`\n\nRenames a contract by matching in wrappers, scripts, and tests.\n\n```bash\nnpx blueprint rename <OLD_NAME> <NEW_NAME>\n```\n\n### `pack`\n\nBuilds and prepares a publish-ready package of wrappers.\n\n```bash\nnpx blueprint pack\n```\n\n**Flags:**\n\n- `--no-warn`, `-n` — ignore warnings about modifying `tsconfig.json` and `package.json`, and about removing the `dist` directory\n\n**Output:**\n\n- Creates a deployment-ready package\n- Includes compiled artifacts\n- Bundles dependencies\n\n### `snapshot`\n\nCreates snapshots with gas usage and cell sizes.\n\n```bash\nnpx blueprint snapshot\n```\n\n**Flags:**\n\n- `--label=<COMMENT>`, `-l=<COMMENT>` — add a comment label to the snapshot\n\n**Features:**\n\n- Run with gas usage and cell sizes collected\n- Write a new snapshot\n- Useful for regression testing\n\n## Environment variables\n\nBlueprint supports environment variables for wallet configuration when using the mnemonic provider:\n\n- `WALLET_MNEMONIC` — wallet mnemonic phrase (space-separated words).\n- `WALLET_VERSION` — wallet contract version (`v1r1`, `v1r2`, `v1r3`, `v2r1`, `v2r2`, `v3r1`, `v3r2`, `v4r1`, `v4r2`, `v4`, `v5r1`).\n- `WALLET_ID` — wallet ID for versions earlier than `v5r1`.\n- `SUBWALLET_NUMBER` — subwallet number for `v5r1` wallets.\n\n### Example .env file\n\n```bash\nWALLET_MNEMONIC=\"<MNEMONIC_24_WORDS>\"\nWALLET_VERSION=v4\nWALLET_ID=698983191\nSUBWALLET_NUMBER=0\n```\n\n- `<MNEMONIC_24_WORDS>` — 24-word wallet mnemonic (space-separated).\n"
  },
  {
    "path": "contract-dev/blueprint/config.mdx",
    "content": "---\ntitle: \"Configuring Blueprint\"\n---\n\nA [configuration file](https://github.com/ton-org/blueprint/blob/develop/src/config/Config.ts) allows you\nto customize certain blueprint features.\n\nCreate a `blueprint.config.ts` file in the root of your project, and export the configuration as a named `config`;\ndo not use a `default` export:\n\n```typescript\nimport { Config } from '@ton/blueprint';\n\nexport const config: Config = {\n    // configuration options\n};\n```\n\nThe configuration supports the following options:\n\n| Field                                                                    |                     Type/Values                     | Description                                                                              |\n| ------------------------------------------------------------------------ | :-------------------------------------------------: | ---------------------------------------------------------------------------------------- |\n| [`plugins`](/contract-dev/blueprint/config#plugins)                      |                      `Plugin[]`                     | Extend or customize the behavior.                                                        |\n| [`network`](/contract-dev/blueprint/config#custom-network)               | `'mainnet' `<br />`'testnet'`<br />` CustomNetwork` | Specifies the target network for deployment or interaction.                              |\n| `separateCompilables`                                                    |                      `boolean`                      | If `true`, `*.compile.ts` files go to `compilables/`. <br /> If `false`, to `wrappers/`. |\n| [`requestTimeout`](/contract-dev/blueprint/config#request-timeouts)      |                       `number`                      | HTTP request timeout in milliseconds.                                                    |\n| [`recursiveWrappers`](/contract-dev/blueprint/config#recursive-wrappers) |                      `boolean`                      | If `true`, searches `wrappers/` or `compilables/` recursively for contracts.             |\n| [`manifestUrl`](/contract-dev/blueprint/config#ton-connect-manifest)     |                       `string`                      | Overrides the default TON Connect manifest URL.                                          |\n\n## Plugins\n\nBlueprint includes a plugin system, allowing the community to extend its functionality without modifying Blueprint’s core code.\nTo use plugins, add a `plugins` array to your config:\n\n```typescript\nimport { Config } from '@ton/blueprint';\nimport { ScaffoldPlugin } from 'blueprint-scaffold';\n\nexport const config: Config = {\n    plugins: [new ScaffoldPlugin()],\n};\n```\n\nThis example adds the [scaffold plugin](https://github.com/1IxI1/blueprint-scaffold).\n\nSome community-developed plugins include:\n\n- [scaffold](https://github.com/1IxI1/blueprint-scaffold) – creates a simple DApp using the wrappers’ code.\n- [misti](https://github.com/nowarp/blueprint-misti) – simplifies workflow with the [Misti](https://nowarp.github.io/tools/misti/) static analyzer.\n\n## Custom network\n\nA custom network can be set as the default by adding a `network` object to your configuration:\n\n```typescript\nimport { Config } from '@ton/blueprint';\n\nexport const config: Config = {\n    network: {\n        endpoint: 'https://toncenter.com/api/v2/jsonRPC',\n        type: 'mainnet',\n        version: 'v2',\n        key: <YOUR_API_KEY>,\n    },\n};\n```\n\nUsing the `--custom` flags achieves the same result, but it can be tiresome to provide them every time.\nThe above configuration is equivalent to running:\n\n```bash\nnpx blueprint run \\\n  --custom https://toncenter.com/api/v2/jsonRPC \\\n  --custom-version v2 \\\n  --custom-type mainnet \\\n  --custom-key <YOUR_API_KEY>\n```\n\nEach property of the `network` object has the same meaning as its corresponding `--custom` flag. See the `blueprint help run` for details.\n\n## Liteclient support\n\nLiteclient can be configured using the `network` object in your configuration:\n\n```typescript\nimport { Config } from '@ton/blueprint';\n\nexport const config: Config = {\n    network: {\n        endpoint: 'https://ton.org/testnet-global.config.json', // Use https://ton.org/global.config.json for Mainnet or any custom configuration\n        version: 'liteclient',\n        type: 'testnet',\n    }\n};\n```\n\nYou can also specify these parameters using CLI:\n\n```bash\nnpx blueprint run \\\n  --custom https://ton.org/testnet-global.config.json \\\n  --custom-version liteclient \\\n  --custom-type testnet\n```\n\n## Request timeouts\n\nYou can configure how long HTTP requests should wait before timing out using the `requestTimeout` field.\nThis is useful when working with unstable or slow networks.\n\n```typescript\nimport { Config } from '@ton/blueprint';\n\nexport const config: Config = {\n    requestTimeout: 10000, // 10 seconds\n};\n```\n\n## Recursive wrappers\n\nThe `recursiveWrappers` field controls whether the `wrappers` directory is searched recursively for contract configurations.\n\n```typescript\nimport { Config } from '@ton/blueprint';\n\nexport const config: Config = {\n    recursiveWrappers: true,\n};\n```\n\nBy default, it's set to `false`.\n\n## TON Connect manifest\n\nIf you're using a TON Connect provider, you can override the default manifest URL by setting the `manifestUrl` field:\n\n```typescript\nimport { Config } from '@ton/blueprint';\n\nexport const config: Config = {\n    manifestUrl: 'https://yourdomain.com/custom-manifest.json',\n};\n```\n\nBy default, the manifest URL is:\n\n```\nhttps://raw.githubusercontent.com/ton-org/blueprint/main/tonconnect/manifest.json\n```\n"
  },
  {
    "path": "contract-dev/blueprint/coverage.mdx",
    "content": "---\ntitle: \"Collecting test coverage\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\nimport { Image } from \"/snippets/image.jsx\";\n\n<Aside>\n  This page covers coverage calculated on TVM assembly instructions. Path- and source-line coverage is not implemented.\n</Aside>\n\nThere are two main ways to calculate coverage of your `@ton/sandbox` tests.\n\n## Easy way\n\n<Aside\n  type=\"caution\"\n  title=\"Library compatibility\"\n>\n  For this way to work correctly, a version of `@ton/sandbox >= 0.37.2` and `@ton/blueprint >= 0.41.0` is needed.\n</Aside>\n\nWhen using Blueprint, the only thing you need to collect coverage is to run the following command:\n\n```bash\nblueprint test --coverage\n```\n\nResults will appear in the `coverage/` directory as HTML files with reports for each of your contracts.\n\n## Customizable way\n\nThere might be some reasons why you don't want to simply use `--coverage`.\n\n- You don't want to collect coverage for all contracts.\n- You use `@ton/sandbox` but don't use `@ton/blueprint`.\n- Not all contracts have source code. (For example, for each transaction, you deploy a new contract, and you don't have wrappers for it.)\n- You want to get the raw data and customize the output.\n\n### 1. Enable coverage collection\n\nBefore running tests, add `blockchain.enableCoverage()` to collect coverage data:\n\n```typescript\nimport {Blockchain} from '@ton/sandbox';\n\ndescribe('Contract Tests', () => {\n    let blockchain: Blockchain;\n    let contract: SandboxContract<MyContract>;\n\n    beforeEach(async () => {\n        blockchain = await Blockchain.create();\n\n        blockchain.enableCoverage();\n        // or for COVERAGE=true mode only\n        // blockchain.enableCoverage(process.env[\"COVERAGE\"] === \"true\");\n\n        // Deploy your contract\n        contract = blockchain.openContract(MyContract.fromInit());\n        // ... deployment logic\n    });\n\n    // Your tests here...\n});\n```\n\n### 2. Collect coverage after tests\n\n```typescript\nafterAll(() => {\n    const coverage = blockchain.coverage(contract);\n    console.log(coverage?.summary());\n})\n```\n\n### 3. Generate reports\n\n```typescript\nimport {writeFileSync} from 'fs';\n\nafterAll(() => {\n    const coverage = blockchain.coverage(contract);\n    if (!coverage) return;\n\n    // Generate HTML report for detailed analysis\n    const htmlReport = coverage.report(\"html\");\n    writeFileSync(\"coverage.html\", htmlReport);\n\n    // Print text report to console\n    const textReport = coverage.report(\"text\");\n    console.log(textReport);\n});\n```\n\n## Understanding coverage data\n\n### Coverage summary\n\nThe coverage summary provides key metrics about your test coverage:\n\n```typescript\nconst summary = coverage.summary();\n\nconsole.log(`Total lines: ${summary.totalLines}`);\nconsole.log(`Covered lines: ${summary.coveredLines}`);\nconsole.log(`Coverage percentage: ${summary.coveragePercentage.toFixed(2)}%`);\nconsole.log(`Total gas consumed: ${summary.totalGas}`);\nconsole.log(`Total hits: ${summary.totalHits}`);\n\n// Instruction-level statistics\nsummary.instructionStats.forEach(stat => {\n    console.log(`${stat.name}: ${stat.totalHits} hits, ${stat.totalGas} gas, avg ${stat.avgGas}`);\n});\n```\n\n### Coverage reports\n\n- **HTML Report**: Interactive report with highlighting and line-by-line coverage details\n- **Text Report**: Console-friendly report with coverage information and marked code\n\n## Advanced usage patterns\n\n### Multiple test suites\n\nWhen running multiple test files, you might want to merge coverage data:\n\n```typescript\n// In first test file\nconst coverage1 = blockchain.coverage(contract);\nif (!coverage1) return;\nconst coverage1Json = coverage1.toJson();\nwriteFileSync(\"coverage1.json\", coverage1Json);\n\n// In second test file\nconst coverage2 = blockchain.coverage(contract);\nif (!coverage2) return;\nconst coverage2Json = coverage2.toJson();\nwriteFileSync(\"coverage2.json\", coverage2Json);\n\n// Merge coverage data in separate script after tests\nconst savedCoverage1 = Coverage.fromJson(readFileSync(\"coverage1.json\", \"utf-8\"));\nconst savedCoverage2 = Coverage.fromJson(readFileSync(\"coverage2.json\", \"utf-8\"));\nconst totalCoverage = savedCoverage1.mergeWith(savedCoverage2);\n\nconsole.log(`Combined coverage: ${totalCoverage.summary().coveragePercentage}%`);\n```\n\n## Coverage for multiple contracts\n\nWhen testing systems with multiple contracts:\n\n```typescript not runnable\ndescribe('Multi-Contract System', () => {\n    let blockchain: Blockchain;\n    let contract1: SandboxContract<Contract1>;\n    let contract2: SandboxContract<Contract2>;\n\n    beforeEach(async () => {\n        blockchain = await Blockchain.create();\n        blockchain.enableCoverage();\n\n        // Deploy multiple contracts\n        contract1 = blockchain.openContract(Contract1.fromInit());\n        contract2 = blockchain.openContract(Contract2.fromInit());\n    });\n\n    afterAll(() => {\n        // Get coverage for each contract separately\n        const coverage1 = blockchain.coverage(contract1);\n        const coverage2 = blockchain.coverage(contract2);\n\n        if (!coverage1 || !coverage2) return;\n\n        console.log('Contract 1 Coverage:', coverage1.summary().coveragePercentage);\n        console.log('Contract 2 Coverage:', coverage2.summary().coveragePercentage);\n\n        // Generate separate reports\n        writeFileSync(\"contract1-coverage.html\", coverage1.report(\"html\"));\n        writeFileSync(\"contract2-coverage.html\", coverage2.report(\"html\"));\n    });\n});\n```\n\n## Interpret results\n\nThe usual report looks like this:\n\n<Image\n  src=\"/resources/images/coverage-report.png\"\n/>\n\nApart from the header statistics, the line-by-line coverage report is the most informative. Most fields are self‑explanatory; the code section shows per‑instruction hit counts (blue) and gas cost (red). This helps you analyze both coverage and gas efficiency.\n\n<Aside>\n  To understand the TVM assembly output, read [TVM](/foundations/whitepapers/tvm).\n</Aside>\n\n## Limitations\n\nNote that when code of other contracts is stored directly in the code of the contract ([Tact](/languages/tact) does that automatically if a contract system does not contain circular dependencies), that affects the overall code coverage percentage.\n\nTo mitigate this effect in coverage estimation, add a circular dependency. For example, import a file with the following content.\n\n```tact title=\"Tact\"\ncontract A {\n    receive() {\n        let x = initOf B();\n        drop2(x);\n    }\n}\n\ncontract B() {\n    receive() {\n        let x = initOf A();\n        drop2(x);\n    }\n}\n\nasm fun drop2(x: StateInit) {\n    DROP2\n}\n```\n"
  },
  {
    "path": "contract-dev/blueprint/deploy.mdx",
    "content": "---\ntitle: \"Deployment and interaction\"\n---\n\nFollowing development and testing, contracts can be deployed and interacted with. This section outlines deployment scripts, provider configuration, and interaction workflows.\n\n## Running scripts\n\nBlueprint allows you to run scripts directly from the project.\n\n1. Place your script in the `scripts/` folder.\n1. Each script file must export a `run` function:\n   ```typescript\n   export async function run(provider: NetworkProvider, args: string[]) {\n     //\n   }\n   ```\n1. Run the script with: `npx blueprint run <SCRIPT> [arg1, arg2, ...]` command.\n\n## Deploying contracts\n\nTo deploy a smart contract, create a deployment script in `scripts/deploy<Contract>.ts` with the following content.\n\n```typescript title=\"./scripts/deploy<Contract>.ts\" expandable\nimport { toNano } from '@ton/core';\nimport { MyContract } from '../wrappers/MyContract';\nimport { compile, NetworkProvider } from '@ton/blueprint';\n\nexport async function run(provider: NetworkProvider) {\n    const myContract = provider.open(MyContract.createFromConfig({}, await compile('MyContract')));\n\n    await myContract.sendDeploy(provider.sender(), toNano('0.05'));\n\n    await provider.waitForDeploy(myContract.address);\n\n    // run methods on `myContract`\n}\n```\n\n### Interactive mode\n\nTo launch a guided prompt to create a contract step by step, use:\n\n```bash\nnpx blueprint run\n```\n\n### Non-interactive mode\n\nTo create a contract without prompts, provide the contract name and template type:\n\n```bash\nnpx blueprint run deploy<CONTRACT> --<NETWORK> --<DEPLOY_METHOD>\n```\n\n**Example:**\n\n```bash\nnpx blueprint run deployCounter --mainnet --tonconnect\n```\n\n## Deploying methods\n\n### Mnemonic provider\n\nRun scripts with a wallet using mnemonic authentication by configuring environment variables and specifying the `--mnemonic` for a non-interactive method.\n\n**Required variables:**\n\nSet the following variables in the `.env` file:\n\n- `WALLET_MNEMONIC` — wallet mnemonic phrase (space-separated words).\n- `WALLET_VERSION` — wallet contract version.\n- **Supported versions:** `v1r1`, `v1r2`, `v1r3`, `v2r1`, `v2r2`, `v3r1`, `v3r2`, `v4r1`, `v4r2` (or `v4`), `v5r1`.\n\n```env\nWALLET_MNEMONIC=\"word1 word2 ... word24\"   # Your wallet's mnemonic phrase\nWALLET_VERSION=\"v4r2\"                      # Wallet contract version\n```\n\n**Optional variables:**\n\n- `WALLET_ID` — wallet ID for versions earlier than `v5r1`, excluding `v5r1`.\n- `SUBWALLET_NUMBER` — subwallet number for `v5r1` wallets.\n\n_See the [wallet v5 reference](https://github.com/ton-org/ton/blob/master/src/wallets/v5r1/WalletV5R1WalletId.ts) for `WALLET_ID` construction._\n\nOnce your environment is set up, you can use the mnemonic wallet for deployment with the appropriate configuration.\n\n### TON Connect\n\nRun scripts with a wallet using TON Connect by specifying the `--tonconnect` option.\n\n**Steps:**\n\n1. After running the command, select a wallet from the available options.\n1. Scan the generated QR code in your wallet app or open the provided link.\n1. Confirm the transaction in the wallet's interface.\n\nOnce confirmed, the contract is deployed.\n\n## Interaction\n\nAfter deploying your contracts, you can interact with them using Blueprint scripts. These scripts use the [wrappers](/contract-dev/blueprint/develop#wrappers) you've created to send messages and call get methods on your deployed contracts.\n\nTo run the following scripts, refer to the [Running scripts](#runningscripts) section.\n\n### Sending messages\n\nTo send [messages](/foundations/messages/ordinary-tx) to your deployed contracts, create a script that calls the `send` methods defined in your wrapper. These methods trigger contract execution and modify the contract's state.\n\n```typescript title=\"./scripts/sendIncrease.ts\"\nimport { Address, toNano } from '@ton/core';\nimport { MyContract } from '../wrappers/MyContract';\nimport { NetworkProvider } from '@ton/blueprint';\n\nconst contractAddress = Address.parse('<CONTRACT_ADDRESS>');\n\nexport async function run(provider: NetworkProvider) {\n    const myContract = provider.open(MyContract.createFromAddress(contractAddress));\n\n    await myContract.sendIncrease(provider.sender(), {\n        value: toNano('0.05'),\n        increaseBy: 42\n    });\n\n    await provider.waitForLastTransaction();\n    console.log('Message sent successfully!');\n}\n```\n\n### Executing get methods\n\nGet methods allow you to read data from your deployed contracts without creating transactions. These methods are free to call and don't modify the contract's state.\n\n```typescript title=\"./scripts/getCounter.ts\"\nimport { Address } from '@ton/core';\nimport { MyContract } from '../wrappers/MyContract';\nimport { NetworkProvider } from '@ton/blueprint';\n\nconst contractAddress = Address.parse('<CONTRACT_ADDRESS>');\n\nexport async function run(provider: NetworkProvider) {\n    const myContract = provider.open(MyContract.createFromAddress(contractAddress));\n\n    const counter = await myContract.getCounter();\n    const id = await myContract.getId();\n\n    console.log('Counter:', counter);\n    console.log('ID:', id);\n}\n```\n"
  },
  {
    "path": "contract-dev/blueprint/develop.mdx",
    "content": "---\ntitle: \"Smart contract development\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\n\nEnsure your current directory is the root of the project initialized with `npm create ton@latest`.\n\n## Contract creation\n\nUse Blueprint to create a new contract.\n\n### Interactive mode\n\nTo launch a guided prompt to create a contract step by step, use:\n\n```bash\nnpx blueprint create\n```\n\n### Non-interactive mode\n\nTo create a contract without prompts, provide the contract name and template type:\n\n```bash\nnpx blueprint create <CONTRACT> --type <TYPE>\n```\n\n- `<CONTRACT>`- contract name\n- `<TYPE>`- template type, e.g., tolk-empty, func-empty, tact-empty, tolk-counter, func-counter, tact-counter\n\n**Example:**\n\n```bash\nnpx blueprint create MyNewContract --type tolk-empty\n```\n\n## Contract code writing\n\nAfter creation, contracts are placed in the `contracts/` folder.\nEach file uses the extension that matches its language.\nFor example, creating a Tolk contract `MyNewContract` results in `contracts/my_new_contract.tolk`.\n\n## Building\n\nBlueprint compiles your contracts into build artifacts.\n\n### Interactive mode\n\nRun without arguments to select contracts from a prompt:\n\n```bash\nnpx blueprint build\n```\n\n### Non-interactive mode\n\nSpecify a contract name or use flags to skip prompts:\n\n```bash\nnpx blueprint build <CONTRACT>\n```\n\n**Example:**\n\n```bash\nnpx blueprint build MyNewContract\nnpx blueprint build --all # build all contracts\n```\n\n### Compiled artifacts\n\nCompiled outputs are stored in the `build/` directory.\n\n- `build/<CONTRACT>.compiled.json`- serialized contract representation used for deployment and testing.\n\n  Each file contains three fields:\n\n  - `hash` — hash of the compiled contract code in hexadecimal format.\n  - `hashBase64`  — the same hash encoded in Base64.\n  - `hex` — the compiled contract code in hexadecimal form.\n\n  Example:\n\n  ```json title='<CONTRACT>.compiled.json'\n  {\n      \"hash\":\"21eabd3331276c532778ad3fdcb5b78e5cf2ffefbc0a6dc...\",\n      \"hashBase64\":\"Ieq9MzEnbFMneK0/3LW3jlzy/++8Cm3Dxkt+I3yRe...\",\n      \"hex\":\"b5ee9c72410106010082000114ff00f4a413f4bcf2c80b01...\"\n  }\n  ```\n\n- `build/<CONTRACT>/<CONTRACT>.fif` — Fift code derived from the contract.\n\n## Wrappers\n\nWrappers are TypeScript classes that **you write** to interact with your smart contracts. They act as a bridge between your application code and the blockchain, encapsulating contract deployment, message sending, and data retrieval logic. Each wrapper implements the `Contract` interface from [`@ton/core`](https://github.com/ton-org/ton-core).\n\nWhen you create a new contract with Blueprint, you need to write your own wrapper class in the `wrappers/` folder to define how your application will interact with the contract.\n\n<Aside\n  type=\"tip\"\n  title=\"Naming Convention\"\n>\n  Methods that send messages should start with `send` (e.g., `sendDeploy`, `sendIncrement`), and methods that read data should start with `get` (e.g., `getCounter`).\n\n  This convention works seamlessly with the `open()` method, which automatically provides the `ContractProvider` as the first argument to your wrapper methods.\n</Aside>\n\n### Static creating methods\n\nWrappers typically include two main static methods for creating contract instances:\n\n#### `createFromAddress(address: Address)`\n\nCreates a wrapper instance for an **already deployed** contract using its address. This method is used when you want to interact with an existing contract on the blockchain.\n\n```typescript title=\"./wrappers/Counter.ts\"\nimport { Address, Cell, Contract } from '@ton/core';\n\nexport class Counter implements Contract {\n    constructor(readonly address: Address, readonly init?: { code: Cell; data: Cell }) {}\n\n    static createFromAddress(address: Address) {\n        return new Counter(address);\n    }\n}\n```\n\n#### `createFromConfig(config, code, workchain)`\n\nCreates a wrapper instance for a **new contract** that hasn't been deployed yet. This method calculates the contract's future address based on its initial state and code.\n\n```typescript title=\"./wrappers/Counter.ts\"\nimport { Address, beginCell, Cell, Contract, contractAddress } from '@ton/core';\n\nexport type CounterConfig = {\n    id: number;\n    counter: number;\n};\n\nexport function counterConfigToCell(config: CounterConfig): Cell {\n    return beginCell().storeUint(config.id, 32).storeUint(config.counter, 32).endCell();\n}\n\nexport class Counter implements Contract {\n    constructor(readonly address: Address, readonly init?: { code: Cell; data: Cell }) {}\n\n    static createFromConfig(config: CounterConfig, code: Cell, workchain = 0) {\n        const data = counterConfigToCell(config);\n        const init = { code, data };\n        return new Counter(contractAddress(workchain, init), init);\n    }\n}\n```\n\n**Parameters:**\n\n- `config` - Initial configuration data for your contract\n- `code` - Compiled contract code (usually loaded from build artifacts)\n- `workchain` - workchain ID (0 for basechain, -1 for masterchain)\n\n<Aside type=\"tip\">\n  Contracts created with `createFromAddress()` cannot be deployed since they lack the `init` data required for deployment. Use `createFromConfig()` for new contracts that need to be deployed.\n</Aside>\n\n### Sending messages\n\nMessage sending methods allow your application to trigger contract execution by sending [internal or external messages](/foundations/messages/ordinary-tx). These methods handle the construction of message bodies and transaction parameters.\n\nAll sending methods follow a similar pattern and should start with `send`:\n\n```typescript title=\"./wrappers/Counter.ts\"\nimport { ContractProvider, Sender, SendMode, beginCell, Cell } from '@ton/core';\n\nexport class Counter implements Contract {\n    async sendDeploy(provider: ContractProvider, via: Sender, value: bigint) {\n        await provider.internal(via, {\n            value,\n            sendMode: SendMode.PAY_GAS_SEPARATELY,\n            body: beginCell().endCell(), // empty body for deployment\n        });\n    }\n\n    async sendIncrement(provider: ContractProvider, via: Sender, opts: { value: bigint; queryId?: number }) {\n        await provider.internal(via, {\n            value: opts.value,\n            sendMode: SendMode.PAY_GAS_SEPARATELY,\n            body: beginCell()\n                .storeUint(0x7e8764ef, 32) // opcode for increment\n                .storeUint(opts.queryId ?? 0, 64) // queryId\n                .endCell(),\n        });\n    }\n\n    async sendExternal(provider: ContractProvider, body: Cell) {\n        await provider.external(body);\n    }\n}\n```\n\n**Parameters:**\n\n- `provider` - `ContractProvider` instance that handles blockchain communication\n- `via` - `Sender` object representing the transaction sender\n- `opts` - Options object containing transaction value and method-specific parameters\n\n### Calling get methods\n\nGet methods allow you to read data from smart contracts without creating transactions. These methods are read-only operations that query the contract's current state.\n\nAll get methods should start with `get` and return a Promise:\n\n```typescript title=\"./wrappers/Counter.ts\"\nimport { Contract, ContractProvider } from '@ton/core';\n\nexport class Counter implements Contract {\n\n    async getCounter(provider: ContractProvider): Promise<number> {\n        const result = await provider.get('currentCounter', []);\n        return result.stack.readNumber();\n    }\n\n    async getItemById(provider: ContractProvider, id: number): Promise<number> {\n        const result = await provider.get('itemById', [\n            { type: 'int', value: BigInt(id) }\n        ]);\n        return result.stack.readNumber();\n    }\n\n    async getContractData(provider: ContractProvider): Promise<{ counter: number; id: number }> {\n        const result = await provider.get('contractData', []);\n        return {\n            counter: result.stack.readNumber(),\n            id: result.stack.readNumber(),\n        };\n    }\n}\n```\n\n### Complete example\n\n```typescript title=\"./wrappers/Counter.ts\" expandable\nimport { Address, beginCell, Cell, Contract, contractAddress, ContractProvider, Sender, SendMode } from '@ton/core';\n\nexport type NewContractConfig = {\n    id: number;\n    counter: number;\n};\n\nexport function newContractConfigToCell(config: NewContractConfig): Cell {\n    return beginCell().storeUint(config.id, 32).storeUint(config.counter, 32).endCell();\n}\n\nexport const Opcodes = {\n    OP_INCREASE: 0x7e8764ef,\n    OP_RESET: 0x3a752f06,\n};\n\nexport class NewContract implements Contract {\n    constructor(readonly address: Address, readonly init?: { code: Cell; data: Cell }) {}\n\n    static createFromAddress(address: Address) {\n        return new NewContract(address);\n    }\n\n    static createFromConfig(config: NewContractConfig, code: Cell, workchain = 0) {\n        const data = newContractConfigToCell(config);\n        const init = { code, data };\n        return new NewContract(contractAddress(workchain, init), init);\n    }\n\n    async sendDeploy(provider: ContractProvider, via: Sender, value: bigint) {\n        await provider.internal(via, {\n            value,\n            sendMode: SendMode.PAY_GAS_SEPARATELY,\n            body: beginCell().endCell(),\n        });\n    }\n\n    async sendIncrease(\n        provider: ContractProvider,\n        via: Sender,\n        opts: {\n            increaseBy: number;\n            value: bigint;\n            queryID?: number;\n        }\n    ) {\n        await provider.internal(via, {\n            value: opts.value,\n            sendMode: SendMode.PAY_GAS_SEPARATELY,\n            body: beginCell()\n                .storeUint(Opcodes.OP_INCREASE, 32)\n                .storeUint(opts.queryID ?? 0, 64)\n                .storeUint(opts.increaseBy, 32)\n                .endCell(),\n        });\n    }\n\n    async sendReset(\n        provider: ContractProvider,\n        via: Sender,\n        opts: {\n            value: bigint;\n            queryID?: number;\n        }\n    ) {\n        await provider.internal(via, {\n            value: opts.value,\n            sendMode: SendMode.PAY_GAS_SEPARATELY,\n            body: beginCell()\n                .storeUint(Opcodes.OP_RESET, 32)\n                .storeUint(opts.queryID ?? 0, 64)\n                .endCell(),\n        });\n    }\n\n    async getCounter(provider: ContractProvider) {\n        const result = await provider.get('currentCounter', []);\n        return result.stack.readNumber();\n    }\n\n    async getID(provider: ContractProvider) {\n        const result = await provider.get('initialId', []);\n        return result.stack.readNumber();\n    }\n}\n```\n\n## Testing\n\nTo test contracts, follow the [Smart contract testing](/contract-dev/testing/overview).\n\n## Deployment\n\nTo deploy contracts, follow the [Deployment and interaction](/contract-dev/blueprint/deploy#deploying-contracts) section.\n"
  },
  {
    "path": "contract-dev/blueprint/overview.mdx",
    "content": "---\ntitle: \"Blueprint overview\"\nsidebarTitle: \"Overview\"\n---\n\nFor smart contract development on TON Blockchain, **Blueprint** is an all-in-one development environment designed to enhance the process of creating, testing, and deploying smart contracts.\n\nIt includes:\n\n- [Blueprint](https://github.com/ton-org/blueprint/blob/develop/README.md) — core tools for building contracts.\n- [Sandbox](https://github.com/ton-org/sandbox) — fast local testing in an isolated blockchain.\n- [Create TON App](https://github.com/ton-org/create-ton) — scaffolding a ready-to-use project.\n- [Testing utils](https://github.com/ton-org/test-utils) — testing helpers and unit test matchers.\n\nThis section covers development, testing, smart contracts deployment and interaction, performance benchmarks, and blueprint configuration and reference.\n\n## Quick start\n\nTo get started immediately, run the following command to create a new project and follow the on-screen instructions:\n\n```console\nnpm create ton@latest\n```\n\n## Key features\n\n- **Project scaffolding** — create a ready-to-use development environment with `npm create ton@latest`.\n- **Streamlined workflow** — build, test, and deploy smart contracts efficiently.\n- **Simple deployment** — publish contracts to Mainnet and Testnet directly from your wallet.\n- **Fast local testing** — run multiple contracts in an isolated in-process blockchain.\n\n## Requirements\n\n- [Node.js](https://nodejs.org) version 22 or later\n- Verify the version with `node -v`\n\n## IDE plugins\n\n- [List of plugins](/contract-dev/ide/overview)\n- [JetBrains IDEs](/contract-dev/ide/jetbrains)\n- [Visual Studio Code](/contract-dev/ide/vscode)\n\n## Environment setup\n\n1. Run and follow the on-screen instructions: `npm create ton@latest`.\n1. From the project directory, run `npm install` to install dependencies.\n\n## Project structure\n\n- `contracts/` — smart contract source code and imports.\n- `scripts/` — deployment scripts for Mainnet and Testnet, as well as scripts for interacting with live contracts.\n- `tests/` — TypeScript test suite for all contracts, using [Sandbox](https://github.com/ton-org/sandbox) for in-process execution.\n- `wrappers/` — TypeScript interface classes for all contracts **except Tact**.\n  - Each wrapper implements the `Contract` interface from [`@ton/core`](https://www.npmjs.com/package/@ton/core).\n    - Provides message serialization and deserialization, getter wrappers, and compilation helpers.\n    - Used in both the test suite and client code to interact with contracts from TypeScript.\n- `build/` — compilation artifacts generated by the build command.\n"
  },
  {
    "path": "contract-dev/contract-sharding.mdx",
    "content": "---\ntitle: \"Contract sharding\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\nimport { Image } from '/snippets/image.jsx';\n\nSome protocols need to store a lot of information in contracts, for example, tokens that have many users. In TON, there is a limit on how much can be stored in a single contract. The solution in TON is to split the data across many different contracts, where you can quickly find the right contract by a key and retrieve the required information from it.\n\nIn such protocols, there is a child contract that initially contains the information identified by a key. In some protocols, it is important to know the Parent contract, which acts as the information manager.\n\nTo avoid having to know the key upfront, we do not populate that field in `StateInit`; we only populate the key field. This makes it easy to locate the required contract later.\n\n<Aside\n  type=\"caution\"\n>\n  Child contracts should store information about the Parent so that only it can authorize important state changes.\n</Aside>\n\n<Image\n  src=\"/resources/images/child_light.png\"\n  darkSrc=\"/resources/images/child_dark.png\"\n  alt=\"Shard pattern\"\n/>\n\nConsider NFTs: the collection serves as the Parent contract, and the NFT items are the child contracts. The key in this case is the index, and only a message from the collection can set the initial owner.\n\nFor Jettons, the Parent is the minter and the Children are user wallets. The key is the user's smart contract address, and the value is the user's token balance.\n\nIn general, jettons and NFTs share this principle, but broadly speaking, jetton protocols have a unique contract per user, while NFTs have a single contract per item (by index) that is shared across all users.\n\n## Unbounded data structures\n\nAn interesting property of this pattern is that the number of potential children is unbounded! We can have an infinite number of children.\n\nIn general, infinite data structures that can actually scale to billions are very difficult to implement on blockchain efficiently. This pattern showcases the power of TON.\n\n```tact Tact\nimport \"@stdlib/deploy\";\n\n// we have multiple instances of the children\ncontract TodoChild {\n\n    seqno: Int as uint64;\n\n    // when deploying an instance, we must specify its index (sequence number)\n    init(seqno: Int) {\n        self.seqno = seqno;\n    }\n\n    // this message handler will just debug print the seqno so we can see when it's called\n    receive(\"identify\") {\n        dump(self.seqno);\n    }\n}\n\n// we have one instance of the parent\ncontract TodoParent with Deployable {\n\n    numChildren: Int as uint64;\n\n    init() {\n        self.numChildren = 0;\n    }\n\n    // this message handler will cause the contract to deploy another child\n    receive(\"deploy another\") {\n        self.numChildren = self.numChildren + 1;\n        let init: StateInit = initOf TodoChild(self.numChildren);\n        send(SendParameters{\n            to: contractAddress(init),\n            value: ton(\"0.1\"),              // pay for message, the deployment, and give some TON for storage\n            mode: SendIgnoreErrors,\n            code: init.code,                // attaching the `StateInit` will cause the message to deploy\n            data: init.data,\n            body: \"identify\".asComment()    // we must piggyback the deployment on another message\n        });\n    }\n\n    get fun numChildren(): Int {\n        return self.numChildren;\n    }\n}\n```\n"
  },
  {
    "path": "contract-dev/debug.mdx",
    "content": "---\ntitle: \"Debugging smart contracts\"\n---\n\nimport {Aside} from \"/snippets/aside.jsx\";\n\n<Aside>\n  All examples from this article are available on [GitHub](https://github.com/ton-org/docs-examples/tree/main/guidebook/debug).\n</Aside>\n\nErrors 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.\n\n## Log to the console\n\nMost commonly used to print common values: transactions and get-method results.\n\n- Use `findTransaction()` to find a transaction by its properties.\n- Use `flattenTransaction()` to inspect transactions in a more human-readable format.\n\n{/* NB! There are two imports from @ton/test-utils, so that it's easier for a user to copy the one they need. */}\n\n```ts TypeScript\nimport '@ton/test-utils';\nimport { toNano } from '@ton/core';\nimport { Blockchain } from '@ton/sandbox';\nimport { Test } from './output/sample_Test';\nimport { findTransaction } from '@ton/test-utils';\nimport { flattenTransaction } from '@ton/test-utils';\n\nconst setup = async () => {\n    const blockchain = await Blockchain.create();\n    const owner = await blockchain.treasury('deployer');\n    const contract = blockchain.openContract(\n        await Test.fromInit(),\n    );\n    const deployResult = await contract.send(\n        owner.getSender(),\n        { value: toNano(0.5), bounce: true },\n        null,\n    );\n    return { blockchain, owner, contract, deployResult };\n};\n\nit('should deploy correctly', async () => {\n    const { contract, deployResult } = await setup();\n\n    const txToInspect = findTransaction(\n        deployResult.transactions,\n        {\n            to: contract.address,\n            deploy: true,\n        },\n    );\n    if (txToInspect === undefined) {\n        throw new Error('Requested tx was not found.');\n    }\n    // User-friendly output\n    console.log(flattenTransaction(txToInspect));\n    // Verbose output\n    console.log(txToInspect);\n});\n```\n\n## Dump values from a contract\n\nThere are three TVM debug [instructions](/tvm/instructions#fe-debug): `DUMPSTK`, `STRDUMP`, and `DUMP`.\n\nThese instructions are wrapped in functions with different names in each language:\n\n- Tolk: Functions on a global `debug` object.\n- FunC: Global functions from `stdlib.fc`.\n- 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.\n\n<Aside\n  type=\"caution\"\n>\n  Debug instructions consume gas and affect gas measurement. Remove them before measuring gas or deploying to production.\n</Aside>\n\n## Explore TVM logs\n\n```ts TypeScript\nconst blockchain = await Blockchain.create();\nblockchain.verbosity.vmLogs = \"vm_logs\";\n```\n\nOf all [verbosity levels](/contract-dev/testing/reference#verbosity-2), the two are the most useful:\n\n- `vm_logs` — outputs VM logs for each transaction; includes executed instructions and occurred exceptions.\n- `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.\n\nTypical output for `vm_logs` looks like this:\n\n```text\n...\nexecute SWAP\nexecute PUSHCONT x30\nexecute IFJMP\nexecute LDU 64\nhandling exception code 9: cell underflow\ndefault exception handler, terminating vm with exit code 9\n```\n\nThe 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).\n\nInspect the same code with the `vm_logs_full` verbosity level. The output is heavily truncated at the top.\n\n```text\n...\nexecute PUSHCONT x30\ngas remaining: 999018\nstack: [ 500000000 CS{Cell{02b168008d0d4580cd8f09522be7c0390a7a632bda4a99291c435b767c95367ebe78e9af0023d36bc5f97853f4c898f868f95b035ae8f555a321d0ffce8d9f6165e2252d7a9077359400060e9fc800000000003d0902d1b85b3919} bits: 711..711; refs: 2..2} 0 Cont{vmc_std} ]\ncode cell hash: F9EAC82B7999AEEF696D592FE2469B9069FB05ED35C92213D7EE516F45AB97CA offset: 344\nexecute IFJMP\ngas remaining: 999000\nstack: [ 500000000 CS{Cell{02b168008d0d4580cd8f09522be7c0390a7a632bda4a99291c435b767c95367ebe78e9af0023d36bc5f97853f4c898f868f95b035ae8f555a321d0ffce8d9f6165e2252d7a9077359400060e9fc800000000003d0902d1b85b3919} bits: 711..725; refs: 2..2} ]\ncode cell hash: F9EAC82B7999AEEF696D592FE2469B9069FB05ED35C92213D7EE516F45AB97CA offset: 352\nexecute LDU 64\nhandling exception code 9: cell underflow\ndefault exception handler, terminating vm with exit code 9\n```\n\n<Aside type=\"tip\">\n  To investigate the error in more detail, examine the TVM source code for the `LDU` instruction.\n  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`).\n\n  Check how `LDU` [is implemented](https://github.com/ton-blockchain/ton/blob/34823b1ea378edbe3bc59f3bcc48126480a0b768/crypto/vm/cellops.cpp#L981).\n</Aside>\n\nStack is printed as `[bottom, ..., top]`, where `top` is the top of the stack.\n\nHere, the stack contains two values:\n\n- **Top:** the slice from which data is being read — `CS{Cell{...} bits: 711..725; refs: 2..2}`\n- **Bottom:** an integer value — `500000000`\n\nHowever, 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.\n\nIn FunC, locate the `load_uint(64)` call causing the issue and ensure enough bits are available or adjust the read width.\n\n### TVM log limits\n\nThe size of TVM debug output depends on the verbosity level:\n\n| Level | Setting                                                                        | Max size              |\n| ----- | :----------------------------------------------------------------------------- | :-------------------- |\n| 0     | `none`                                                                         | 256 bytes _(default)_ |\n| 1–4   | `vm_logs` <br /> `vm_logs_location` <br /> `vm_logs_gas` <br /> `vm_logs_full` | 1 MB                  |\n| 5     | `vm_logs_verbose`                                                              | 32 MB                 |\n\nWhen 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**.\n\n## Explore the trace\n\nFor traces that are not too large, print all transactions and inspect them.\n\n```ts TypeScript\nconst result = await contract.send(\n    owner.getSender(),\n    { value: toNano(0.5), bounce: true },\n    null,\n);\nfor (const tx of result.transactions) {\n    console.log(flattenTransaction(tx));\n}\n```\n\nFor large traces, use a GUI tool. Two tools are commonly used:\n\n- [TonDevWallet trace view](https://github.com/TonDevWallet/TonDevWallet) — requires the TonDevWallet application; does not require a custom `@ton/sandbox`; requires the `@tondevwallet/traces` package.\n- [TxTracer Sandbox](/tvm/tools/txtracer) — requires a custom `@ton/sandbox` package; runs in the browser.\n\nAlso, these tools allow to explore logs of each transaction.\n\n## Inspect BoC returned by APIs\n\nWhen 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.\n\nIn API responses, BoC is typically represented as a base64-encoded string, which is not human-readable. Example API response:\n\n```json\n{\n  \"stack\": [\n    {\n      \"type\": \"cell\",\n      \"value\": \"te6cckEBAQEAFwAAKSioyuboQNrK5ubCzspA0txAxsrY2Whv0fw=\"\n    }\n  ]\n}\n```\n\nThe `\"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:\n\n```json\n{\n  \"success\": true,\n  \"value\": {\n    \"kind\": \"Message\",\n    \"len\": 20,\n    \"text\": \"Test message in cell\"\n  }\n}\n```\n\n### How to use\n\n1. Copy the base64 BoC string or hex, if applicable, from the API response.\n1. Paste it into the [`ton-cell-abi-viewer`](https://ton-cell-abi-viewer.vercel.app/).\n1. Provide the TL-B schema for the cell, if available.\n1. Inspect the decoded structure.\n\n<Aside type=\"note\">\n  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.\n</Aside>\n\nUse this tool when API responses contain serialized cells that require structural inspection during debugging.\n\n## Debug with TVM Retracer\n\nEven 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.\n\n### Scenarios for retracing\n\n- All [execution phases](/foundations/phases) complete without errors, yet the expected outcome is missing.\n- An action is skipped, or a transfer does not reach its destination.\n- 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.\n\n### How to analyze a transaction\n\n1. Obtain the transaction hash from a [blockchain explorer](/ecosystem/explorers/overview).\n1. Open [TVM Retracer](/tvm/tools/retracer) and enter the transaction hash.\n1. Review the execution:\n   - Inspect **Logs section** for executed instructions and exceptions.\n   - Examine **Actions cell (C5)** to review data passed between contracts.\n   - Check **message modes** — some modes can suppress errors, causing actions to be skipped.\n"
  },
  {
    "path": "contract-dev/first-smart-contract.mdx",
    "content": "---\ntitle: \"Your first smart contract\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\nimport { FenceTable } from \"/snippets/fence-table.jsx\";\n\nThis tutorial covers building, deploying, and interacting with a smart contract on TON from start to finish.\n\n## Prerequisites\n\n- Basic programming: variables, functions, if/else statements\n- Basic familiarity with a command‑line interface and executing commands\n- Node.js—`v22` or later— [download here](https://nodejs.org/)\n  - Check if installed: `node -v` in terminal\n- Installed [TON wallet](/ecosystem/wallet-apps/tonkeeper) with [Toncoin on testnet](/ecosystem/wallet-apps/get-coins)\n\n## Development environment\n\n<Steps>\n  <Step\n    title=\"Set up development environment\"\n  >\n    Use the [Blueprint](/contract-dev/blueprint/overview) development toolkit for smart contracts. Start a new project with:\n\n    ```bash\n    npm create ton@latest -- Example --contractName FirstContract --type tolk-empty\n    ```\n\n    This command creates a project named \"Example\", containing a contract named \"FirstContract\".\n\n    The generated project structure is:\n\n    <FenceTable\n\n    >\n      Example/\n      ├──contracts/                        # smart contract source code\n      │   └── first\\_contract.tolk          # main contract file\n      ├── scripts/                         # deployment and on-chain interaction scripts\n      │   └── deployFirstContract.ts       # script to deploy the contract\n      ├── tests/                           # testing specifications\n      │   └── FirstContract.spec.ts        # contract test file\n      ├── wrappers/                        # TypeScript wrappers for contract interaction\n      │   ├── FirstContract.ts             # wrapper class for the smart contract\n      │   └── FirstContract.compile.ts     # configuration for compiling contract\n    </FenceTable>\n  </Step>\n\n  <Step\n    title=\"Move into the project directory\"\n  >\n    ```bash\n    cd Example\n    ```\n  </Step>\n</Steps>\n\n## What is a smart contract\n\nA smart contract is a program stored on <Tooltip tip=\"A distributed database that many computers maintain together.\" cta=\"Learn more\" href=\"/foundations/shards\">TON blockchain</Tooltip> and executed by the <Tooltip tip=\"The “computer” which executes smart contracts on TON blockchain.\" cta=\"Learn more\" href=\"/tvm/overview\">TVM</Tooltip>.\nOn-chain, every contract consists of two components:\n\n- Code — compiled [TVM instructions](/tvm/instructions), defines the contract's logic.\n- Data — persistent state, stores information between interactions.\n\nBoth are stored at a specific [address](/foundations/addresses/overview) on TON blockchain, which is a unique identifier for each smart contract. Smart contracts interact with each other only through [messages](/foundations/messages/overview).\n\n### Smart contract layout\n\nA contract's code consists of three functional sections: storage, messages, and get methods:\n\n- Storage holds the contract’s persistent state. Example: the `counter` variable keeps its value across calls from different users.\n- Messages are receivers defined in the contract’s code that specify how the contract should react to each incoming message. Each message triggers a specific action or changes the state according to the contract's logic.\n- [Get methods](/tvm/get-method) are read-only functions that return contract data without modifying state. Example: a get method that returns the current `counter` value.\n\n  Due to the [TON architecture](/from-ethereum#on-chain-get-methods), get methods cannot be called from other contracts. Inter-contract communication uses **messages** only.\n\n## Write a smart contract\n\nTo build a simple counter contract:\n\n- Start with an initial `counter` value.\n- Send `increase` messages to add to the counter or `reset` messages to set it to 0.\n- Call a get method to return the current `counter` value.\n\nThe contract uses [**Tolk**](/languages/tolk) language.\n\nThe TON ecosystem provides editor plugins with syntax support for IDEs and code editors. View them [here](/contract-dev/ide/overview).\n\n<Steps>\n  <Step\n    title=\"Define contract storage\"\n  >\n    Open the `./contracts/first_contract.tolk` file.\n\n    To define contract storage, store the `counter` value. Tolk makes it simple with <Tooltip tip=\"A structure is a composite data type that groups named fields, each having its own type, into one unit.\" cta=\"Learn more\" href=\"/languages/tolk\">structures</Tooltip>:\n\n    ```tolk title=\"./contracts/first_contract.tolk\"\n    struct Storage {\n        // the current counter value\n        counter: uint64;\n    }\n\n    // load contract data from persistent storage\n    fun Storage.load() {\n        return Storage.fromCell(contract.getData())\n    }\n\n    // save contract data to persistent storage\n    fun Storage.save(self) {\n        contract.setData(self.toCell())\n    }\n    ```\n\n    Structures serialize and deserialize automatically into [cells](/foundations/serialization/cells), the storage unit in TON. The `fromCell` and `toCell` functions handle conversion between structures and cells.\n  </Step>\n\n  <Step\n    title=\"Implement message handlers\"\n  >\n    To process messages, implement the `onInternalMessage` function. It receives one argument — the incoming message. Focus on the `body` field, which contains the payload sent by a user or another contract.\n\n    Define two message structures:\n\n    - `IncreaseCounter` — contains one field `increaseBy` to increment the counter.\n    - `ResetCounter` — resets the counter to 0.\n\n    Each structure has a unique prefix —`0x7e8764ef` and `0x3a752f06`— called opcodes, that allows the contract to distinguish between messages.\n\n    ```tolk title=\"./contracts/first_contract.tolk\"\n    struct(0x7e8764ef) IncreaseCounter {\n        increaseBy: uint32\n    }\n\n    struct(0x3a752f06) ResetCounter {}\n    ```\n\n    To avoid manual deserialization of each message, group the messages into a union. A union bundles multiple types into a single type and supports automatic serialization and deserialization.\n\n    ```tolk title=\"./contracts/first_contract.tolk\"\n    type AllowedMessage = IncreaseCounter | ResetCounter;\n    ```\n\n    Now implement the message handler:\n\n    ```tolk title=\"./contracts/first_contract.tolk\"\n    fun onInternalMessage(in: InMessage) {\n        // use `lazy` to defer parsing until fields are accessed\n        val msg = lazy AllowedMessage.fromSlice(in.body);\n\n        // matching the union to determine body structure\n        match (msg) {\n            IncreaseCounter => {\n                // load contract storage lazily (efficient for large or partial reads/updates)\n                var storage = lazy Storage.load();\n                storage.counter += msg.increaseBy;\n                storage.save();\n        }\n\n            ResetCounter => {\n                var storage = lazy Storage.load();\n                storage.counter = 0;\n                storage.save();\n            }\n\n            // this match branch would be executed if the message body does not match IncreaseCounter or ResetCounter structures\n            else => {\n                // reject user message (throw) if body is not empty\n                assert(in.body.isEmpty()) throw 0xFFFF\n            }\n        }\n    }\n    ```\n  </Step>\n\n  <Step\n    title=\"Add getter functions\"\n  >\n    Write a getter function to return the current counter:\n\n    ```tolk title=\"./contracts/first_contract.tolk\"\n    get fun currentCounter(): int {\n        val storage = lazy Storage.load();\n        return storage.counter;\n    }\n    ```\n  </Step>\n\n  <Step\n    title=\"Complete contract code\"\n  >\n    The contract now includes:\n\n    - Storage — persistent `counter` value\n    - Messages — `IncreaseCounter` and `ResetCounter` handlers\n    - Get methods — `currentCounter`\n\n    <Accordion\n      title=\"Full source code\"\n    >\n      ```tolk title=\"./contracts/first_contract.tolk\"\n      struct Storage {\n          counter: uint64;\n      }\n\n      fun Storage.load() {\n          return Storage.fromCell(contract.getData());\n      }\n\n      fun Storage.save(self) {\n          contract.setData(self.toCell());\n      }\n\n      struct(0x7e8764ef) IncreaseCounter {\n          increaseBy: uint32\n      }\n\n      struct(0x3a752f06) ResetCounter {}\n\n      type AllowedMessage = IncreaseCounter | ResetCounter;\n\n      fun onInternalMessage(in: InMessage) {\n          val msg = lazy AllowedMessage.fromSlice(in.body);\n\n          match (msg) {\n              IncreaseCounter => {\n                  var storage = lazy Storage.load();\n                  storage.counter += msg.increaseBy;\n                  storage.save();\n              }\n\n              ResetCounter => {\n                  var storage = lazy Storage.load();\n                  storage.counter = 0;\n                  storage.save();\n              }\n\n              else => {\n                  assert(in.body.isEmpty()) throw 0xFFFF;\n              }\n          }\n      }\n\n      get fun currentCounter(): int {\n          val storage = lazy Storage.load();\n          return storage.counter;\n      }\n      ```\n    </Accordion>\n  </Step>\n</Steps>\n\n## Compile the contract\n\nTo build the contract, compile it into bytecode for execution by the TVM. Use Blueprint with command:\n\n```bash\nnpx blueprint build FirstContract\n```\n\nExpected output:\n\n```ansi\nBuild script running, compiling FirstContract\n🔧 Using tolk version 1.1.0...\n\n✅ Compiled successfully! Cell BOC result:\n\n{\n  \"hash\": \"fbfb4be0cf4ed74123b40d07fb5b7216b0f7d3195131ab21115dda537bad2baf\",\n  \"hashBase64\": \"+/tL4M9O10EjtA0H+1tyFrD30xlRMashEV3aU3utK68=\",\n  \"hex\": \"b5ee9c7241010401005b000114ff00f4a413f4bcf2c80b0102016202030078d0f891f24020d72c23f43b277c8e1331ed44d001d70b1f01d70b3fa0c8cb3fc9ed54e0d72c21d3a9783431983070c8cb3fc9ed54e0840f01c700f2f40011a195a1da89a1ae167fe3084b2d\"\n}\n\n✅ Wrote compilation artifact to build/FirstContract.compiled.json\n```\n\nThe compilation artifact contains the contract bytecode. This file is required for deployment.\n\nNext, deploy the contract to the TON blockchain and interact with it using scripts and wrappers.\n\n## Deploy to testnet\n\n<Steps>\n  <Step\n    title=\"Create a wrapper file\"\n  >\n    To deploy, create a wrapper class. Wrappers make it easy to interact with contracts from TypeScript.\n\n    Open the `./wrappers/FirstContract.ts` file and replace its content with the following code:\n\n    ```typescript title=\"./wrappers/FirstContract.ts\"\n    import { Address, beginCell, Cell, Contract, contractAddress, ContractProvider, Sender, SendMode } from '@ton/core';\n\n    export class FirstContract implements Contract {\n        constructor(\n            readonly address: Address,\n            readonly init?: { code: Cell; data: Cell },\n        ) {}\n\n        static createFromConfig(config: { counter: number }, code: Cell, workchain = 0) {\n            const data = beginCell().storeUint(config.counter, 64).endCell();\n            const init = { code, data };\n            return new FirstContract(contractAddress(workchain, init), init);\n        }\n\n        async sendDeploy(provider: ContractProvider, via: Sender, value: bigint) {\n            await provider.internal(via, {\n                value,\n                sendMode: SendMode.PAY_GAS_SEPARATELY,\n            });\n        }\n    }\n    ```\n\n    Wrapper class details:\n\n    - [`@ton/core`](https://www.npmjs.com/package/@ton/core) — a library with base TON types.\n    - The function `createFromConfig` builds a wrapper using:\n      - code — compiled bytecode\n      - data — the initial storage layout\n    - The contract [address](/foundations/addresses/overview) is derived deterministically from `code` and `data` using `contractAddress`.\n    - The method `sendDeploy` sends the first message with `stateInit`, the structure holding the contract's initial code and data, which triggers deployment. In practice, this can be an empty message with Toncoin attached.\n  </Step>\n\n  <Step\n    title=\"Create the deployment script\"\n  >\n    Open the `./scripts/deployFirstContract.ts` file and replace its content with the following code.\n    It deploys the contract.\n\n    ```typescript title=\"./scripts/deployFirstContract.ts\"\n    import { toNano } from '@ton/core';\n    import { FirstContract } from '../wrappers/FirstContract';\n    import { compile, NetworkProvider } from '@ton/blueprint';\n\n    export async function run(provider: NetworkProvider) {\n        const firstContract = provider.open(\n            FirstContract.createFromConfig(\n                { counter: Math.floor(Math.random() * 10000000) },\n                await compile('FirstContract')\n            )\n        );\n\n        await firstContract.sendDeploy(provider.sender(), toNano('0.05'));\n\n        await provider.waitForDeploy(firstContract.address);\n    }\n    ```\n\n    The `sendDeploy` method accepts three arguments. Only two arguments are passed because `provider.open` automatically provides the `ContractProvider` as the first argument.\n  </Step>\n\n  <Step\n    title=\"Run the script\"\n  >\n    TON provides two networks for deployment:\n\n    - **testnet** — developer sandbox.\n    - **mainnet** — production blockchain.\n\n    This tutorial uses testnet. Mainnet deployment is possible once the contract is verified and ready for production.\n\n    <Aside\n      type=\"danger\"\n      title=\"Funds at risk\"\n    >\n      On-chain deployments spend Toncoin and are irreversible. Verify the network before executing. Use testnet for practice; use mainnet only for actual deployment.\n    </Aside>\n\n    Run the script with:\n\n    ```bash\n    npx blueprint run deployFirstContract --testnet --tonconnect --tonviewer\n    ```\n\n    For flags and options, see the [Blueprint deployment guide](/contract-dev/blueprint/deploy).\n  </Step>\n\n  <Step\n    title=\"Confirm transaction\"\n  >\n    <Aside\n      title=\"Wallet required\"\n      type=\"note\"\n    >\n      If a wallet is not installed, check the [wallet section](/ecosystem/wallet-apps/tonkeeper) to select and install a wallet before deploying the contract. Make sure the wallet is funded with [Toncoin on the testnet](/ecosystem/wallet-apps/get-coins).\n    </Aside>\n\n    Scan the QR code displayed in the console, and confirm the transaction in the wallet app.\n\n    Expected output:\n\n    ```text\n    Using file: deployFirstContract\n    ? Choose your wallet Tonkeeper\n\n    <QR_CODE_HERE>\n\n    Connected to wallet at address: ...\n    Sending transaction. Approve in your wallet...\n    Sent transaction\n    Contract deployed at address kQBz-OQQ0Olnd4IPdLGZCqHkpuAO3zdPqAy92y6G-UUpiC_o\n    You can view it at https://testnet.tonviewer.com/kQBz-OQQ0Olnd4IPdLGZCqHkpuAO3zdPqAy92y6G-UUpiC_o\n    ```\n\n    The link opens the contract on [Tonviewer](/ecosystem/explorers/tonviewer), a [blockchain explorer](/ecosystem/explorers/overview) showing transactions, messages and [account states](/foundations/status).\n\n    Next, interact with the contract by sending messages and calling getter functions.\n  </Step>\n</Steps>\n\n## Contract interaction\n\nDeployment also counts as a message sent to the contract. The next step is to send a message with a body to trigger contract logic.\n\n<Steps>\n  <Step\n    title=\"Update wrapper class\"\n  >\n    Update the wrapper class with three methods: `sendIncrease`, `sendReset`, and `getCounter`:\n\n    ```typescript title=\"./wrappers/FirstContract.ts\" expandable\n    import { Address, beginCell, Cell, Contract, contractAddress, ContractProvider, Sender, SendMode } from '@ton/core';\n\n    export class FirstContract implements Contract {\n        constructor(\n            readonly address: Address,\n            readonly init?: { code: Cell; data: Cell },\n        ) {}\n\n        static createFromConfig(config: { counter: number }, code: Cell, workchain = 0) {\n            const data = beginCell().storeUint(config.counter, 64).endCell();\n            const init = { code, data };\n            return new FirstContract(contractAddress(workchain, init), init);\n        }\n\n        async sendDeploy(provider: ContractProvider, via: Sender, value: bigint) {\n            await provider.internal(via, {\n                value,\n                sendMode: SendMode.PAY_GAS_SEPARATELY,\n                body: beginCell().endCell(),\n            });\n        }\n\n        async sendIncrease(\n            provider: ContractProvider,\n            via: Sender,\n            opts: {\n                increaseBy: number;\n                value: bigint;\n                },\n            ) {\n            await provider.internal(via, {\n                value: opts.value,\n                sendMode: SendMode.PAY_GAS_SEPARATELY,\n                body: beginCell().storeUint(0x7e8764ef, 32).storeUint(opts.increaseBy, 32).endCell(),\n            });\n        }\n\n        async sendReset(\n            provider: ContractProvider,\n            via: Sender,\n            opts: {\n                value: bigint;\n                },\n            ) {\n            await provider.internal(via, {\n                value: opts.value,\n                sendMode: SendMode.PAY_GAS_SEPARATELY,\n                body: beginCell().storeUint(0x3a752f06, 32).endCell(),\n            });\n        }\n\n        async getCounter(provider: ContractProvider) {\n            const result = await provider.get('currentCounter', []);\n            return result.stack.readNumber();\n        }\n    }\n    ```\n\n    The main difference from the deploy message is that these methods include a message body. The body is a cell that contains the instructions.\n\n    **Building message bodies**\n\n    Cells are constructed using the `beginCell` method:\n\n    - `beginCell()` creates a new cell builder.\n    - `storeUint(value, bits)` appends an unsigned integer with a fixed bit length.\n    - `endCell()` finalizes the cell.\n\n    **Example**\n\n    `beginCell().storeUint(0x7e8764ef, 32).storeUint(42, 32).endCell()`\n\n    - First 32 bits: `0x7e8764ef` — opcode for \"increase\"\n    - Next 32 bits: `42` — increase by this amount\n  </Step>\n\n  <Step\n    title=\"Send messages to the contract\"\n  >\n    With the contract deployed and wrapper methods in place, the next step is to send messages to it.\n\n    Create a script `./scripts/sendIncrease.ts` that increases the counter:\n\n    ```typescript title=\"./scripts/sendIncrease.ts\"\n    import { Address, toNano } from '@ton/core';\n    import { FirstContract } from '../wrappers/FirstContract';\n    import { NetworkProvider } from '@ton/blueprint';\n\n    // `Address.parse()` converts string to address object\n    const contractAddress = Address.parse('<CONTRACT_ADDRESS>');\n\n    export async function run(provider: NetworkProvider) {\n      // `provider.open()` creates a connection to the deployed contract\n      const firstContract = provider.open(new FirstContract(contractAddress));\n      // `toNano('0.05')` converts 0.05 TON to nanotons\n      // `increaseBy: 42` tells the contract to increase the counter by 42\n      await firstContract.sendIncrease(provider.sender(), { value: toNano('0.05'), increaseBy: 42 });\n      // `waitForLastTransaction()` waits for the transaction to be processed on-chain\n      await provider.waitForLastTransaction();\n    }\n    ```\n\n    Replace `<CONTRACT_ADDRESS>` with the address obtained in the deployment step.\n\n    <Aside\n      type=\"danger\"\n      title=\"Funds at risk\"\n    >\n      On-chain deployments spend Toncoin and are irreversible. Verify the network before executing. Use testnet for practice; use mainnet only for actual deployment.\n    </Aside>\n\n    To run this script:\n\n    ```bash\n    npx blueprint run sendIncrease --testnet --tonconnect --tonviewer\n    ```\n\n    Expected result:\n\n    ```text\n    Using file: sendIncrease\n    Connected to wallet at address: ...\n    Sending transaction. Approve in your wallet...\n    Sent transaction\n    Transaction 0fc1421b06b01c65963fa76f5d24473effd6d63fc4ea3b6ea7739cc533ba62ee successfully applied!\n    You can view it at https://testnet.tonviewer.com/transaction/fe6380dc2e4fab5c2caf41164d204e2f41bebe7a3ad2cb258803759be41b5734\n    ```\n\n    What happens during execution:\n\n    1. Blueprint connects to the wallet using the [TON Connect](/ecosystem/ton-connect/overview) protocol.\n    1. The script builds a transaction with a message body containing opcode `0x7e8764ef` and value `42`.\n    1. The wallet displays transaction details for confirmation.\n    1. After approval, the transaction is sent to the network.\n    1. Validators include the transaction in a newly produced block.\n    1. The contract receives the message, processes it in `onInternalMessage`, and updates the counter.\n    1. The script returns the resulting transaction hash; inspect it in the explorer.\n\n    <Aside\n      title={\"Composability\"}\n      type={\"tip\"}\n    >\n      Other contracts can also send messages to this contract. This enables composition: different contracts can combine their logic with this one, reuse it as a component, and build new behaviors that were not originally anticipated.\n    </Aside>\n  </Step>\n\n  <Step\n    title=\"Reset the counter\"\n  >\n    To reset the counter, create a script `./scripts/sendReset.ts`:\n\n    ```typescript title=\"./scripts/sendReset.ts\"\n    import { Address, toNano } from '@ton/core';\n    import { FirstContract } from '../wrappers/FirstContract';\n    import { NetworkProvider } from '@ton/blueprint';\n\n    const contractAddress = Address.parse('<CONTRACT_ADDRESS>');\n\n    export async function run(provider: NetworkProvider) {\n      const firstContract = provider.open(new FirstContract(contractAddress));\n      await firstContract.sendReset(provider.sender(), { value: toNano('0.05') });\n      await provider.waitForLastTransaction();\n    }\n    ```\n\n    To run this script:\n\n    ```bash\n    npx blueprint run sendReset --testnet --tonconnect --tonviewer\n    ```\n\n    Expected result:\n\n    ```text\n    Using file: sendReset\n    Connected to wallet at address: ...\n    Sending transaction. Approve in your wallet...\n    Sent transaction\n    Transaction 0fc1421b06b01c65963fa76f5d24473effd6d63fc4ea3b6ea7739cc533ba62ee successfully applied!\n    You can view it at https://testnet.tonviewer.com/transaction/fe6380dc2e4fab5c2caf41164d204e2f41bebe7a3ad2cb258803759be41b5734\n    ```\n  </Step>\n\n  <Step\n    title=\"Read contract data with get methods\"\n  >\n    Get methods are special functions in TON smart contracts that run locally on a node. Unlike message-based interactions, get methods are:\n\n    - Free — no gas fees, as the call does not modify the blockchain state.\n    - Instant — no need to wait for blockchain confirmation.\n    - Read-only — can only read data; cannot modify storage or send messages.\n\n    To call a get method, use `getCounter()`, which calls the contract's getter `provider.get('currentCounter')`:\n\n    ```typescript title=\"./scripts/getCounter.ts\"\n    import { Address } from '@ton/core';\n    import { FirstContract } from '../wrappers/FirstContract';\n    import { NetworkProvider } from '@ton/blueprint';\n\n    const contractAddress = Address.parse('<CONTRACT_ADDRESS>');\n\n      export async function run(provider: NetworkProvider) {\n        const firstContract = provider.open(new FirstContract(contractAddress));\n        //  `getCounter()` сalls the contract's `currentCounter` getter\n        const counter = await firstContract.getCounter(); // returns instantly\n        console.log('Counter: ', counter); // wrapper parses stack into JS number\n      }\n    ```\n\n    <Aside>\n      Get methods are available **off-chain only** — JavaScript clients, web apps, etc. — through RPC providers. Contracts cannot call getters on other contracts — inter-contract interaction uses only messages.\n    </Aside>\n\n    <Aside\n      type=\"danger\"\n      title=\"Funds at risk\"\n    >\n      On-chain deployments spend Toncoin and are irreversible. Verify the network before executing. Use testnet for practice; use mainnet only for actual deployment.\n    </Aside>\n\n    To run this script:\n\n    ```bash\n    npx blueprint run getCounter --testnet --tonconnect\n    ```\n\n    After resetting the counter, the expected output:\n\n    ```bash\n    Using file: getCounter\n    Counter: 0\n    ```\n  </Step>\n</Steps>\n\nThe full code for this tutorial is available in the [GitHub repository](https://github.com/ton-org/docs-examples/tree/main/guidebook/first-smart-contract/Example). It includes all contract files, scripts, and wrappers ready to use.\n"
  },
  {
    "path": "contract-dev/gas.mdx",
    "content": "---\ntitle: \"Estimate gas usage in TON contracts\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\n\nContracts which receive a user's message are referred to as **receiver** contracts. Other contracts in the same system are called **internal** contracts. This terminology is local to the current article. Consider a contract system with three contracts: receiver, and internal contracts **A** and **B**. In that system the typical trace looks like this (transactions move from left to right):\n\n```mermaid\nflowchart LR\n    User1((User)) --> Receiver((Receiver)) --> A((A)) --> B((B)) --> User2((User))\n\n    style User1 r:50\n    style Receiver r:50\n    style A r:50\n    style B r:50\n    style User2 r:50\n```\n\n<Aside type=\"tip\">\n  This article covers abstract contracts system, not connected to any existing project. However, it's primarily applicable to contract systems that use a carry-value pattern.\n</Aside>\n\nIt is important to understand that there is _no separate_ message balance and contract balance. After the message is received, coins from the message are stored to the contract balance, and then the contract is executed. [Sending message modes](/foundations/messages/modes) and [reserve actions](/foundations/actions/reserve) help to properly divide contract balance in the action phase. This diagram of a possible value flow illustrates this.\n\n```mermaid\nflowchart LR\n    User1((User)) --> A((A)) --> B((B)) --> User2((User))\n\n    style User1 r:50\n    style A r:50\n    style B r:50\n    style User2 r:50\n```\n\n```mermaid\n---\nconfig:\n  sankey:\n    showValues: false\n---\nsankey-beta\n%% source,target,value\nValue of message,A,100\nOld balance on A,A,20\nA,B,80\nA,Storage fee (A),5\nA,Compute fee (A),15\nA,Forward fee (A->B),20\nOld balance on B,B,20\nB,Storage fee (B),5\nB,Compute fee (B),10\nB,Forward fee (B->C),15\nB,Remaining value on B,70\n```\n\nReceiver contracts must verify that the attached Toncoin is sufficient to cover fees for all contracts in the subsequent trace. If an entry contract accepts a user message it must guarantee that the message will not later fail due to insufficient attached TON. \"Accept\" doesn't mean the call to `accept_message()`, but semantic acceptance, i.e., no throw and no asset returns.\n\nThe reason for this requirement is that reverting the contract system state is usually not possible, because the Toncoin is already spent.\n\nWhen a contract system's correctness depends on successful execution of the remaining transaction trace, it must guarantee that an incoming message carries enough attached Toncoin to cover all fees. This article describes how to compute those fees.\n\nDefine variables for limits and initialize them with zero. We will set them to actual values afterwards.\n\nUse descriptive names for the operation and the contract. It's best to store them in a dedicated file with constants.\n\n```tact\nconst GasSwapRequest: Int = 0;\n```\n\n- Run tests covering all execution paths. Missing a path might hide the most expensive one.\n- Extract resource consumption from the `send()` method's return value. The sections below describe ways to compute consumption of different kinds of resources.\n- Use `expect(extractedValue).toBeLessThanOrEqual(hardcodedConstant)` to verify that the hardcoded limit was not exceeded.\n\n```ts\nimport {findTransactionRequired} from \"@ton/test-utils\";\n\nconst result = await contract.send(/* params */);\nconst vaultTx = findTransactionRequired(result.transactions, {\n    on: contract.address,\n    op: 0x12345678,\n});\nexpect(\n    getComputeGasForTx(vaultTx),\n).toBeLessThanOrEqual(GasSwapRequest);\n```\n\nAfter the first run, use the displayed error message to find the actual value for the constant.\n\n```text\nexpect(received).toBeLessThanOrEqual(expected)\n\nExpected: <= 0n\nReceived:    11578n\n```\n\n```tact\nconst GasSwapRequest: Int = 12000;\n```\n\n### Compute fees\n\nThere are two kinds of values: gas units and Toncoin. The price of contract execution is fixed in gas units. However, the price of the gas itself is determined by the blockchain configuration.\n\nConversion of gas to Toncoin on-chain using currently set blockchain config parameters can be performed with\n\n```tact\nlet fee = getComputeFee(hardcodedGasValue, isAccountInMasterchain);\n```\n\nThis function uses the [`GETGASFEE`](/tvm/instructions#f836-getgasfee) TVM opcode.\n\n### Forward fees\n\nForward fee is calculated with this formula:\n\n```\nfwdFee = lumpPrice\n       + priceForCells * (msgSizeInCells - 1)\n       + priceForBits * (msgSizeInBits - bitsInRoot)\n```\n\nwhere\n\n- `lumpPrice` is the fixed value [from config](/foundations/config#param-24-and-25%3A-message-price) paid once for the message.\n- `msgSizeInCells` is the number of cells in the message.\n- `msgSizeInBits` is the number of bits in all the cells of the message.\n\nIn Tolk, `cell.calculateSizeStrict()` can be used to compute `msgSizeInCells` and `msgSizeInBits`. In TVM, it's implemented as [`CDATASIZE`](/tvm/instructions#f941-cdatasize) instruction.\n\nIn Tolk, the formula above is implemented in `calculateForwardFee()`. In TVM, it's implemented as [`GETFORWARDFEE`](/tvm/instructions#f838-getforwardfee) instruction.\n\n```tact\nlet sizeMsg = computeDataSize(\n    msg.toCell(),\n    8192\n);\n\nlet fwdFee = getForwardFee(\n    sizeMsg.cells - 1,\n    sizeMsg.bits - msg.toCell().bits(),\n    isAccountInMasterchain\n);\n```\n\n<Aside\n  type=\"caution\"\n>\n  The `computeDataSize()` function consumes large, unpredictable amount of gas. If at all it is possible to precompute the size, it is recommended to do so.\n\n  If required, the function has the second argument: maximum number of cells to visit. Usually it is set to 8192 since it is the [limit for message size](/foundations/limits#message-and-transaction-limits). It might be used to limit amount of spent gas.\n</Aside>\n\nIn Tolk, both computations can be performed with a call to `msg.send()` with mode 1024. In TVM, it's implemented as [`SENDRAWMSG`](/tvm/instructions#fb00-sendrawmsg). It will consume approximately the same amount of gas.\n\n### Optimized forward fee calculation\n\nIf the size of the outgoing message is bounded by the size of the incoming message, we can estimate the forward fee of an outgoing message to be no larger than the forward fee of the incoming message, that was already computed by TVM. Thus, we don't have to calculate it again. Note that this estimation is correct only for a contract system in the same workchain, because gas prices depend on the workchain.\n\n```tolk title=\"Tolk\"\nfun onInternalMessage(in: InMessage) {\n    val fwdFee = in.originalForwardFee;\n    // ...\n}\n```\n\n### Complex forward fee calculation\n\nAssume the contract receives a message with an unknown size and forwards it further adding fields with total of `a` bits and `b` cells to the message, e.g., [`StateInit`](/foundations/messages/deploy).\n\nFor this case, in Tolk, there is a function `calculateForwardFeeWithoutLumpPrice()`. In TVM, it's implemented as [`GETFORWARDFEESIMPLE`](/tvm/instructions#f83c-getforwardfeesimple). This function does not take `lumpPrice` into account.\n\n```tolk title=\"Tolk\"\nfun onInternalMessage(in: InMessage) {\n    val origFwdFee = in.originalForwardFee;\n\n    // \"Out\" message will consist of fields from\n    // \"in\" message, and some extra fields.\n    // Forward fee for \"out\" message is estimated\n    // from a forward fee for \"in\" message\n    val additionalFwdFee = getSimpleForwardFee(\n        additionalFieldsSize.cells,\n        additionalFieldsSize.bits,\n        isAccountInMasterchain\n    );\n    val totalFwdFee = origFwdFee + additionalFwdFee;\n\n    // Remember to multiply totalFwdFee by the number\n    // of hops in the trace\n}\n```\n\n### Storage fees\n\n<Aside>\n  For calculating storage fees, maximum possible size of the contract in `cells` and `bits` should be known. Calculating it manually might be hard, if the contract stores a hashmap or some other complex data structure in its state.\n\n  It might be easier to compute it by writing a test that will occupy maximum possible size, and use the measured value. There are [helper functions](#helper-functions) for doing these measurements.\n</Aside>\n\nWe cannot predict storage fees that we have to pay for sending messages because it depends on how long the target contract didn't pay storage fee. Storage fees differ in this way from forward and compute fees, as they should be handled both in receiver and internal contracts.\n\n#### Maintain a positive reserve\n\nAlways keep a minimum balance on all contracts in the system. Storage fees get deducted from this reserve. The reserve get replenished with each user interaction. Do not hardcode Toncoin values for fees. Instead, hardcode the maximum possible contract size in cells and bits.\n\nThis approach affects code of internal contracts.\n\n<Aside type=\"tip\">\n  It is the developer's decision for how long the storage fees should be reserved. Popular options are 5 and 10 years.\n</Aside>\n\n```tact\nconst secondsInFiveYears: Int = 5 * 365 * 24 * 60 * 60;\nreceive(msg: Transfer) {\n    let minTonsForStorage: Int = getStorageFee(\n        maxCells,\n        maxBits,\n        secondsInFiveYears,\n        isAccountInMasterchain\n    );\n    nativeReserve(\n        max(oldBalance, minTonsForStorage),\n        ReserveAtMost\n    );\n    // Process operation with remaining value...\n}\n// Also this contract probably will require some code, that will allow owner to withdraw TONs from this contract.\n```\n\nIn this approach, a receiver contract should calculate maximum possible storage fees for all contracts in trace.\n\n```tact\nconst secondsInFiveYears: Int = 5 * 365 * 24 * 60 * 60;\nreceive(msg: UserIn) {\n    // Suppose trace will be\n    // receiver -> A -> B\n    let storageForA = getStorageFee(\n        maxCellsInA,\n        maxBitsInA,\n        secondsInFiveYears,\n        isAccountInMasterchain\n    );\n    let storageForB = getStorageFee(\n        maxCellsInB,\n        maxBitsInB,\n        secondsInFiveYears,\n        isAccountInMasterchain\n    );\n    let totalStorageFees = storageForA + storageForB;\n    // compute compute + forward fees here\n    let otherFees = 0;\n    require(\n        messageValue() >= totalStorageFees + otherFees,\n        \"Not enough TONs\"\n    );\n}\n```\n\n<Aside\n  type=\"caution\"\n>\n  Verify the hardcoded contract size in tests.\n</Aside>\n\n#### Cover storage on demand\n\nThe order of phases [depends](/foundations/phases) on the `bounce` flag of an incoming message. If all messages in the protocol are unbounceable, then the storage phase comes after the credit phase. So, the contract's storage fees are deducted from the joint balance of the contract and incoming message. In this case the pattern where the contract's balance is zero and incoming messages cover storage fees can be applied.\n\nIt is impossible to know in advance what the storage fee due will be on the contract, so a threshold must be selected depending on the network configuration. It is a good practice to use [`freeze_due_limit`](/foundations/config#param-20-and-21%3A-gas-prices) as the threshold. Otherwise, the contract likely is already frozen and a transaction chain is likely to fail anyway.\n\nThis pattern can be generalized to both bounceable and unbounceable messages with `myStorageDue()` function that returns [`storage_fees_due`](/foundations/phases#storage-phase)\n\nThis approach affects code of internal contracts.\n\n```tact\nreceive(msg: Operation) {\n    // Reserve original balance plus any storage debt\n    nativeReserve(\n        myStorageDue(),\n        ReserveAddOriginalBalance | ReserveExact\n    );\n\n    // Send remaining value onward\n    send(SendParameters{\n        value: 0,\n        mode: SendRemainingBalance,\n        // ...\n    });\n}\n```\n\nIf we expect that the rest of trace uses `n` unique contracts, then it won't take more than `n` freeze limits to pay their storage fees. So, in the receiver contract, the check should be:\n\n```tact\nreceive(msg: Operation) {\n    // The trace is still receiver -> A -> B\n    let freezeLimit = getFreezeLimit(isAccountsInMasterchain);\n    let otherFees = ...;\n    // n equals 3 because receiver -> A -> B\n    require(\n        messageValue() >= freezeLimit * 3 + otherFees,\n        \"Not enough TONs\"\n    );\n}\n```\n\nFor contracts using this approach, confirm there is no excess accumulation:\n\n```typescript\nit(\"should not accumulate excess balance\", async () => {\n    await pool.sendSwap(amount);\n    const contract = await blockchain.getContract(\n        pool.address,\n    );\n    const balance = contract.balance;\n    expect(balance).toEqual(0n);\n});\n```\n\nThis confirms that all incoming value was consumed or forwarded, with none left behind. It helps identify any bugs that cause accumulation of TON on any contract.\n\n## Implement fee validation\n\nThe final code in the receiver contract could look like this:\n\n```tact\nreceive(msg: SwapRequest) {\n    let ctx = context();\n    let fwdFee = ctx.readForwardFee();\n\n    // Count all messages in the operation chain\n    // IMPORTANT: We know that each of messages is\n    // less or equal to `SwapRequest`.\n    let messageCount = 3;  // receiver -> vault → pool → vault\n\n    // Calculate minimum required\n    let minFees =\n        messageCount * fwdFee +\n        // Operation in first vault\n        getComputeFee(GasSwapRequest, isInMasterchain) +\n        // Operation in pool\n        getComputeFee(GasPoolSwap, isInMasterchain) +\n        // Operation in second vault\n        getComputeFee(GasVaultPayout, isInMasterchain) +\n        3 * getFreezeLimit();\n\n    require(\n        ctx.value >= msg.amount + minFees,\n        \"Insufficient TON attached\"\n    );\n\n    // Send remaining value for fees...\n\n    // It may also be necessary to handle fees on this exact\n    // contract if it is not supposed to hold users' TONs.\n    // That can be done in either of the two approaches\n    // described above.\n}\n```\n\n## Helper functions\n\nGetting gas for transaction in sandbox is quite easy:\n\n```ts\nfunction getComputeGasForTx(tx: Transaction): bigint {\n    if (tx.description.type !== \"generic\") {\n        throw new Error(\"Expected generic transaction\");\n    }\n    if (tx.description.computePhase.type !== \"vm\") {\n        throw new Error(\"Expected VM compute phase\");\n    }\n    return tx.description.computePhase.gasUsed;\n}\n```\n\nTo calculate the size of a message in cells, use this function:\n\n```ts\nconst calculateCellsAndBits = (\n    root: Cell,\n    visited: Set<string> = new Set<string>()\n) => {\n    const hash = root.hash().toString(\"hex\");\n    if (visited.has(hash)) {\n        return { cells: 0, bits: 0 };\n    }\n    visited.add(hash)\n    let cells = 1;\n    let bits = root.bits.length;\n    for (const ref of root.refs) {\n        const childRes = calculateCellsAndBits(\n            ref,\n            visited,\n        );\n        cells += childRes.cells;\n        bits += childRes.bits;\n    }\n    return { cells, bits, visited };\n};\n```\n\nTo extract a contract's size in tests, use this function:\n\n```ts\nexport async function getStateSizeForAccount(\n    blockchain: Blockchain,\n    address: Address,\n): Promise<{cells: number; bits: number}> {\n    const contract = await blockchain.getContract(address);\n    const accountState = contract.accountState;\n    if (!accountState || accountState.type !== \"active\") {\n        throw new Error(\"Account state not found\");\n    }\n    if (!accountState.state.code || !accountState.state.data) {\n        throw new Error(\"Account state code or data not found\");\n    }\n    const accountCode = accountState.state.code;\n    const accountData = accountState.state.data;\n    const codeSize = calculateCellsAndBits(\n        accountCode,\n    );\n    const dataSize = calculateCellsAndBits(\n        accountData,\n        codeSize.visited,\n    );\n    return {\n        cells: codeSize.cells + dataSize.cells,\n        bits: codeSize.bits + dataSize.bits,\n    };\n};\n```\n\nMessage-size constants should be verified across all possible paths in tests. Otherwise, the resulting gas estimates might be wrong.\n"
  },
  {
    "path": "contract-dev/ide/jetbrains.mdx",
    "content": "---\ntitle: \"TON plugin for IDEs from JetBrains\"\nsidebarTitle: \"JetBrains IDEs\"\n---\n\nimport { Image } from '/snippets/image.jsx';\n\nTON plugin for IntelliJ IDEA (Ultimate and Community), WebStorm, CLion, GoLand, PyCharm, RustRover, and all other JetBrains IDEs.\n\n<Columns cols={3}>\n  <Card\n    title=\"Installation\"\n    icon=\"floppy-disk\"\n    horizontal=\"true\"\n    href=\"#installation\"\n  />\n\n  <Card\n    title=\"Features\"\n    icon=\"sparkles\"\n    horizontal=\"true\"\n    href=\"#features-and-language-support\"\n  />\n\n  <Card\n    title=\"Community\"\n    icon=\"user-group\"\n    horizontal=\"true\"\n    href=\"#community\"\n  />\n</Columns>\n\n## Installation\n\n### From marketplace\n\n1. In the IDE, open <kbd><Icon icon=\"gear\" size={16} /> Settings</kbd><br />\n   Skip this step if you do not have open projects and are in the Start menu\n1. Go to <kbd>Plugins</kbd>\n1. Select the <kbd>Marketplace</kbd> tab (default)\n1. Search for `TON`\n1. Select the official plugin from TON Core and click <kbd>Install</kbd>\n\nThe plugin would be fetched and installed in your current JetBrains IDE. You might need to restart it for changes to take effect.\n\nHere is how the plugin installation page may look in the start menu of WebStorm, before pressing the <kbd>Install</kbd> button:\n\n<Image\n  src=\"/resources/images/intellij-ton/install-from-settings.png\"\n  darkSrc=\"/resources/images/intellij-ton/install-from-settings-dark.png\"\n  alt=\"Screenshot of the plugin installation\"\n/>\n\nAlternatively, you can press <kbd>Get</kbd> on the [plugin homepage in the JetBrains Marketplace](https://plugins.jetbrains.com/plugin/23382-ton) and then follow subsequent instructions.\n\n### From disk\n\nTo manually install the plugin:\n\n1. Download the plugin archive from the [latest GitHub release](https://github.com/ton-blockchain/intellij-ton/releases/latest) or from the exact version [on the marketplace](https://plugins.jetbrains.com/plugin/23382-ton/versions)\n1. In the IDE, open <kbd><Icon icon=\"gear\" size={16} /> Settings</kbd><br />\n   Skip this step if you do not have open projects and are in the Start menu\n1. Go to <kbd>Plugins</kbd>\n1. Click the gear icon on top <kbd><Icon icon=\"gear\" size={16} /></kbd> and then select `Install Plugin from Disk...`\n1. Select the plugin archive in the pop-up and complete the installation\n\nSee also: [Installing a plugin from the command line in IntelliJ IDEA](https://www.jetbrains.com/help/idea/managing-plugins.html#install_plugin_cmd).\n\n## Features and language support\n\nThis plugin provides first-class support for TON-specific languages, schemas, and data formats in IntelliJ-based IDEs. Everything you need to develop, test, debug, and deploy TON smart contracts is made available right from your favorite JetBrains-made editor.\n\n<Columns cols={2}>\n  <Card\n    title=\"Tolk\"\n    icon=\"star\"\n    horizontal=\"true\"\n    href=\"#tolk\"\n  >\n    Recommended language for TON smart contract development\n  </Card>\n\n  <Card\n    title=\"FunC\"\n    icon=\"building-columns\"\n    horizontal=\"true\"\n    href=\"#func\"\n  >\n    Legacy TON smart contract programming language\n  </Card>\n\n  <Card\n    title=\"Fift\"\n    icon=\"layer-group\"\n    horizontal=\"true\"\n    href=\"#fift\"\n  >\n    Low-level stack-based language with deep TVM integration\n  </Card>\n\n  <Card\n    title=\"TL-B\"\n    icon=\"table-cells\"\n    horizontal=\"true\"\n    href=\"#tl-b\"\n  >\n    Cell-based data serialization and markup language\n  </Card>\n\n  <Card\n    title=\"TON Assembly (TASM)\"\n    icon=\"binary\"\n    horizontal=\"true\"\n    href=\"#tasm\"\n  >\n    Textual TVM bitcode assembly language and corresponding (dis)assembler\n  </Card>\n\n  <Card\n    title=\"Integrations\"\n    icon=\"toolbox\"\n    horizontal=\"true\"\n    href=\"#integrations\"\n  >\n    Work with Blueprint projects, Sandbox TON emulator, and other popular tools for TON development\n  </Card>\n</Columns>\n\n### Tolk\n\n**File extension:** `.tolk`\n\n<Image\n  src=\"/resources/images/intellij-ton/tolk.png\"\n  darkSrc=\"/resources/images/intellij-ton/tolk-dark.png\"\n  alt=\"Screenshot of the Tolk language support\"\n/>\n\nThe plugin provides the following features for Tolk files:\n\n- Syntax and error highlighting\n- [Code completion] — context-specific suggestions as you type\n- [Parameter info] — names of parameters in function calls, with option to enable complete function signatures info\n- [Quick documentation] — pop-up and hover documentation for any symbol right from the editor\n- [Declarations] — go to declarations, implementations, and types\n- [Usages] — search for references and usages of a code element throughout the codebase\n- [Inlay hints] — special in-editor markers, like parameter name blobs next to the corresponding argument values\n- [Inspections] — detects, finds, and highlights various problems and abnormal code\n- [Intention actions] — contextual code edits and quick fixes\n- [Formatting] — rearrangements and code cleanup\n- [Rename refactorings] — change names of symbols and files\n- [Code fragment surrounding] — templates for wrapping code fragments in various constructs, such as `try...catch` blocks.\n- [File structure] — view and navigate the code structure of the open file.\n- [Navigation bar] — structure of the project from directories down to code elements, usually located at the bottom of the status bar.\n\n### FunC\n\n**File extensions:** `.fc`, `.func`\n\n<Image\n  src=\"/resources/images/intellij-ton/func.png\"\n  darkSrc=\"/resources/images/intellij-ton/func-dark.png\"\n  alt=\"Screenshot of the FunC language support\"\n/>\n\nThe plugin provides the following features for FunC files:\n\n- Syntax and error highlighting\n- [Code completion]\n- [Quick documentation]\n- [Declarations]\n- [Usages]\n- [Inlay hints]\n- [Inspections]\n\n### Fift\n\n**File extensions:** `.fif`, `.fift`\n\n<Image\n  src=\"/resources/images/intellij-ton/fift.png\"\n  darkSrc=\"/resources/images/intellij-ton/fift-dark.png\"\n  alt=\"Screenshot of the Fift language support\"\n/>\n\n<Image\n  src=\"/resources/images/intellij-ton/fift-asm.png\"\n  darkSrc=\"/resources/images/intellij-ton/fift-asm-dark.png\"\n  alt=\"Screenshot of the Fift assembly support\"\n/>\n\nThe plugin provides the following features for Fift:\n\n- Syntax and error highlighting, with better support for Fift assembly\n- [Code completion]\n- [Declarations]\n- [Usages]\n- [Inspections]\n\n### TL-B\n\n**File extension:** `.tlb`\n\n<Image\n  src=\"/resources/images/intellij-ton/tlb.png\"\n  darkSrc=\"/resources/images/intellij-ton/tlb-dark.png\"\n  alt=\"Screenshot of the TL-B data scheme support\"\n/>\n\nThe plugin provides the following features for TL-B files:\n\n- Syntax and error highlighting\n- [Code completion]\n- [Declarations]\n- [Usages]\n- [Inspections]\n\n### TASM\n\n**File extensions:**\n\n- `.tasm` — textual bitcode assembly\n- `.boc` — serialized binary smart contract code\n\n<Image\n  src=\"/resources/images/intellij-ton/tasm.png\"\n  darkSrc=\"/resources/images/intellij-ton/tasm-dark.png\"\n  alt=\"Screenshot of the TON Assembly (TASM) language support\"\n/>\n\nThe plugin provides the following features for TON Assembly (TASM):\n\n- Syntax and error highlighting of `.tasm` files\n- [Code completion]\n- [Declarations]\n- [Usages]\n- [Inspections]\n\n### Integrations\n\nThe plugin integrates with:\n\n- [Blueprint](/contract-dev/blueprint/overview) — all-in-one development environment for TON smart contract development\n- [Sandbox](https://github.com/ton-org/sandbox) — local TON emulator\n\n## Community\n\nFollow news of TON plugin development in the [`@intellijton` Telegram channel](https://t.me/intellijton).\n\n[Code completion]: https://www.jetbrains.com/help/idea/auto-completing-code.html\n\n[Parameter info]: https://www.jetbrains.com/help/idea/viewing-reference-information.html#view-parameter-info\n\n[Quick documentation]: https://www.jetbrains.com/help/idea/viewing-reference-information.html#inline-quick-documentation\n\n[Intention actions]: https://www.jetbrains.com/help/idea/intention-actions.html\n\n[Declarations]: https://www.jetbrains.com/help/idea/navigating-through-the-source-code.html#go_to_declaration\n\n[Usages]: https://www.jetbrains.com/help/idea/find-highlight-usages.html\n\n[Inlay hints]: https://www.jetbrains.com/help/idea/inlay-hints.html\n\n[Inspections]: https://www.jetbrains.com/help/idea/code-inspection.html\n\n[Formatting]: https://www.jetbrains.com/help/idea/reformat-and-rearrange-code.html\n\n[Rename refactorings]: https://www.jetbrains.com/help/idea/rename-refactorings.html\n\n[Code fragment surrounding]: https://www.jetbrains.com/help/idea/surrounding-blocks-of-code-with-language-constructs.html\n\n[Navigation bar]: https://www.jetbrains.com/help/idea/guided-tour-around-the-user-interface.html#navigation-bar\n\n[File structure]: https://www.jetbrains.com/help/idea/viewing-structure-of-a-source-file.html\n"
  },
  {
    "path": "contract-dev/ide/overview.mdx",
    "content": "---\ntitle: \"IDEs and editor plugins for smart contract development\"\nsidebarTitle: \"Overview\"\nmode: \"wide\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nA table of plugins and extensions is organized by the editors and IDEs they are made for. Entries marked with ⭐ are recommended.\n\n|    | Editor                     | Plugin                       | Tolk | TL-B | Fift | FunC | Tact |\n| -- | -------------------------- | ---------------------------- | ---- | ---- | ---- | ---- | ---- |\n| ⭐ | VSCode                     | [TON][vs-1]                  | ✅   | ✅   | ✅   | ✅   |      |\n| ⭐ | VSCodium and forks         | [TON][vs-1]                  | ✅   | ✅   | ✅   | ✅   |      |\n| ⭐ | JetBrains IDEs             | [TON][jb-1]                  | ✅   | ✅   | ✅   | ✅   |      |\n| ⭐ | All LSP-compatible editors | [TON Language Server][ls-1]  | ✅   | ✅   | ✅   | ✅   |      |\n|    | VSCode                     | [Tact Language][vs-2]        |      |      |      |      | ✅   |\n|    | VSCodium and forks         | [Tact Language][vs-2]        |      |      |      |      | ✅   |\n|    | JetBrains IDEs             | [Tact][jb-2]                 |      |      |      |      | ✅   |\n|    | All LSP-compatible editors | [Tact Language Server][ls-2] |      |      |      |      | ✅   |\n|    | Vim 8+ and Neovim          | [`tact.vim`][vi-1]           |      |      |      |      | ✅   |\n|    | Sublime Text 4             | [`tact-sublime`][st-1]       |      |      |      |      | ✅   |\n\n[vs-1]: /contract-dev/ide/vscode\n[vs-2]: https://github.com/tact-lang/tact-language-server/blob/master/README.md\n[jb-1]: /contract-dev/ide/jetbrains\n[jb-2]: https://plugins.jetbrains.com/plugin/27290-tact\n[ls-1]: https://github.com/ton-blockchain/ton-language-server/releases/latest\n[ls-2]: https://github.com/tact-lang/tact-language-server/releases/latest\n[vi-1]: https://github.com/tact-lang/tact.vim#installation\n[st-1]: https://packagecontrol.io/packages/Tact\n\n<Aside>\n  For minor testing and quick experiments, use the [Web IDE](https://ide.ton.org) as an online playground for smart contracts written in FunC and Tact languages.\n</Aside>\n"
  },
  {
    "path": "contract-dev/ide/vscode.mdx",
    "content": "---\ntitle: \"TON extension for Visual Studio Code (VS Code) and VSCode-based editors\"\nsidebarTitle: \"VSCode and forks\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\nimport { Image } from '/snippets/image.jsx';\n\nTON extension for Visual Studio Code (VS Code) and VSCode-based editors, such as VSCodium, Cursor, Windsurf, and others.\n\n<Columns cols={3}>\n  <Card\n    title=\"Installation\"\n    icon=\"floppy-disk\"\n    horizontal=\"true\"\n    href=\"#installation\"\n  />\n\n  <Card\n    title=\"Features\"\n    icon=\"sparkles\"\n    horizontal=\"true\"\n    href=\"#features-and-language-support\"\n  />\n\n  <Card\n    title=\"Usage\"\n    icon=\"hammer\"\n    horizontal=\"true\"\n    href=\"#usage\"\n  />\n</Columns>\n\n## Installation\n\n### From Visual Studio Marketplace\n\nApplicable for: VSCode <br />\nExtension on: [Marketplace](https://marketplace.visualstudio.com/items?itemName=ton-core.vscode-ton \"TON extension on the Visual Studio Marketplace\")\n\n1. In the editor, open the Command Palette with <kbd>Ctrl+Shift+P</kbd> (or <kbd>⌘+⇧+P</kbd> on macOS)\n1. Type and select `Extensions: Install Extensions`\n1. Search for `TON`\n1. Select the official extension from TON Core and click <kbd>Install</kbd>\n\nThe editor fetches and installs the extension. Restart the editor to apply changes if prompted.\n\nHere is how the extension page may look in VSCode, before pressing the <kbd>Install</kbd> button:\n\n<Image\n  src=\"/resources/images/vscode-ton/install.png\"\n  darkSrc=\"/resources/images/vscode-ton/install-dark.png\"\n  alt=\"Screenshot of extension installation\"\n/>\n\n### From Open VSX Registry\n\nApplicable for: VSCodium, Cursor, Windsurf, and other VSCodium-based editors <br />\nExtension in: [Registry](https://open-vsx.org/extension/ton-core/vscode-ton \"TON extension in the Open VSX Registry\")\n\nInstallation steps are identical to the [VSCode setup](#from-visual-studio-marketplace). Additionally, one can download the exact extension version from the [Open VSX Registry](https://open-vsx.org/extension/ton-core/vscode-ton) and then proceed with [installation from disk](#from-disk).\n\n### From disk\n\nApplicable for: any VSCodium-based editor <br />\nVSIX file: [latest GitHub release](https://github.com/ton-blockchain/ton-language-server/releases/latest)\n\nTo manually install the extension:\n\n1. Download the `.vsix`-packaged plugin archive from the [latest GitHub release](https://github.com/ton-blockchain/ton-language-server/releases/latest) or from the exact version [in the registry](https://open-vsx.org/extension/ton-core/vscode-ton)\n1. In the editor, open the Command Palette with <kbd>Ctrl+Shift+P</kbd> (or <kbd>⌘+⇧+P</kbd> on macOS)\n1. Type and select `Extensions: Install from VSIX...`\n1. Browse and select the downloaded `.vsix` file\n\nThe editor installs the extension. Restart the editor to apply changes if prompted.\n\n<Aside>\n  To install the extension using CLI, specify the editor executable and the `--install-extension` command-line switch, followed by the path to a `.vsix` file:\n\n  ```shell\n  # Command for VSCode\n  code --install-extension <PATH_TO_EXTENSION.vsix>\n\n  # Command for VSCodium\n  codium --install-extension <PATH_TO_EXTENSION.vsix>\n\n  # Other VSCodium-based editors have similar commands\n  ```\n</Aside>\n\nVisual Studio Code’s [“Installing an extension from a VSIX”](https://code.visualstudio.com/docs/configure/extensions/extension-marketplace#_install-from-a-vsix) guide explains the process.\n\n## Features and language support\n\nExtension provides support for TON Blockchain languages and tools in VSCode and VSCode-based editors: from syntax highlighting to on-the-fly inspections and toolchain management.\n\n<Columns cols={2}>\n  <Card\n    title=\"Tolk\"\n    icon=\"star\"\n    horizontal=\"true\"\n    href=\"#tolk\"\n  >\n    Recommended language for TON smart contract development\n  </Card>\n\n  <Card\n    title=\"FunC\"\n    icon=\"building-columns\"\n    horizontal=\"true\"\n    href=\"#func\"\n  >\n    Legacy TON smart contract programming language\n  </Card>\n\n  <Card\n    title=\"Fift\"\n    icon=\"layer-group\"\n    horizontal=\"true\"\n    href=\"#fift\"\n  >\n    Low-level stack-based language with deep TVM integration\n  </Card>\n\n  <Card\n    title=\"TL-B\"\n    icon=\"table-cells\"\n    horizontal=\"true\"\n    href=\"#tl-b\"\n  >\n    Cell-based data serialization and markup language\n  </Card>\n\n  <Card\n    title=\"TON Assembly (TASM)\"\n    icon=\"binary\"\n    horizontal=\"true\"\n    href=\"#tasm\"\n  >\n    Textual TVM bitcode assembly language and corresponding (dis)assembler\n  </Card>\n\n  <Card\n    title=\"Integrations\"\n    icon=\"toolbox\"\n    horizontal=\"true\"\n    href=\"#integrations\"\n  >\n    Work with Blueprint projects, Sandbox TON emulator, and other popular tools for TON development\n  </Card>\n</Columns>\n\n### Tolk\n\n**File extension:** `.tolk`\n\n<Image\n  src=\"/resources/images/vscode-ton/tolk.png\"\n  darkSrc=\"/resources/images/vscode-ton/tolk-dark.png\"\n  alt=\"Screenshot of the Tolk language support\"\n/>\n\nTolk support includes:\n\n- Semantic syntax highlighting\n- Code completion with auto import, postfix completion, snippets, imports completion\n- Go to definition, type definition\n- Find all references, workspace symbol search, symbol renaming\n- Automatic import updates when renaming and moving files\n- Types and documentation on hover\n- Various inlay hints, including hints for types and parameter names.\n- On-the-fly inspections with quick fixes\n- Signature help inside calls\n- Build, test, and debug [Blueprint](/contract-dev/blueprint/overview)-based projects\n- Flexible toolchain management\n\n### FunC\n\n**File extensions:** `.fc`, `.func`\n\n<Image\n  src=\"/resources/images/vscode-ton/func.png\"\n  darkSrc=\"/resources/images/vscode-ton/func-dark.png\"\n  alt=\"Screenshot of the FunC language support\"\n/>\n\nFunC support includes:\n\n- Semantic syntax highlighting\n- Code completion, imports completion\n- Go to definition\n- Find all references, workspace symbol search, symbol renaming\n- Automatic import updates when renaming and moving files\n- Types and documentation on hover\n- Inlay hints for method IDs\n- On-the-fly inspections\n- Build, test, and debug [Blueprint](/contract-dev/blueprint/overview)-based projects\n\n### Fift\n\n**File extensions:** `.fif`, `.fift`\n\n<Image\n  src=\"/resources/images/vscode-ton/fift.png\"\n  darkSrc=\"/resources/images/vscode-ton/fift-dark.png\"\n  alt=\"Screenshot of the Fift language support\"\n/>\n\n<Image\n  src=\"/resources/images/vscode-ton/fift-asm.png\"\n  darkSrc=\"/resources/images/vscode-ton/fift-asm-dark.png\"\n  alt=\"Screenshot of the Fift assembly support\"\n/>\n\nFift support includes:\n\n- Basic and semantic syntax highlighting\n- Go-to definition\n- Inlay hints with instruction gas consumption\n- Hover documentation for instructions\n\n### TL-B\n\n**File extension:** `.tlb`\n\n<Image\n  src=\"/resources/images/vscode-ton/tlb.png\"\n  darkSrc=\"/resources/images/vscode-ton/tlb-dark.png\"\n  alt=\"Screenshot of the TL-B data scheme support\"\n/>\n\nTL-B support includes:\n\n- Basic and semantic syntax highlighting\n- Go-to definition\n- Completion for fields, parameters, and types\n- Go-to references for types\n- Hover documentation for declarations\n\n### TASM\n\n**File extensions:**\n\n- `.tasm` — textual bitcode assembly\n- `.boc` — serialized binary smart contract code\n\n<Image\n  src=\"/resources/images/vscode-ton/tasm.png\"\n  darkSrc=\"/resources/images/vscode-ton/tasm-dark.png\"\n  alt=\"Screenshot of the TON Assembly (TASM) language support\"\n/>\n\nTON Assembly (TASM) support includes:\n\n- Basic syntax highlighting\n- Go-to definition\n- Inlay hints with instruction gas consumption\n- Hover documentation for instructions\n- Code completion for instructions\n\nAdditionally, BoC support includes:\n\n- Automatic BoC disassembly with syntax highlighting\n- Automatic updates on changes in BoC\n\n### Integrations\n\nThe extension integrates with:\n\n- [Sandbox](#sandbox) — Local TON emulator used to [test](/contract-dev/testing/overview) smart contracts\n- [Blueprint](/contract-dev/blueprint/overview) — a popular development environment for TON smart contract development\n\n#### Sandbox\n\nThere is a graphical interface for local TON Blockchain emulation testing. By using it in Blueprint-based projects or any projects that use Sandbox (`@ton/sandbox`) for contract emulation, one can:\n\n- Deploy contracts directly from source code\n- Send internal and external messages\n- Execute get-methods\n- Inspect all transactions and messages\n- Inspect storage and balances in real time\n- Rollback to previous states and export or import various scenarios\n\nIt is suited for prototyping, interactive debugging, and educational purposes. To start, open the \"TON Sandbox\" panel in the primary sidebar after installing the extension, then follow instructions on top.\n\nThe [Sandbox wiki page](https://github.com/ton-blockchain/ton-language-server/wiki/Sandbox:-1.-Overview) provides more detail.\n\n## Usage\n\n- Customize the default config by [setting various options](#configuration-options)\n- Utilize commands from the [Command Palette](#command-palette)\n\n### Configuration options\n\nThis extension provides a wide range of options configurable in the [settings editor](https://code.visualstudio.com/docs/getstarted/extensions#_open-extension-settings).\n\n#### General\n\n<ParamField\n  path=\"ton.tolk.stdlib.path\"\n  type=\"string\"\n  default=\"auto\"\n>\n  Path to Tolk standard library. If empty, will try to find in `node_modules`.\n</ParamField>\n\n#### Toolchain\n\n<ParamField\n  path=\"ton.tolk.toolchain.toolchains\"\n  type=\"object\"\n>\n  Configured Tolk toolchains. Each key serves as a unique identifier for the toolchain, which is an object with the following properties:\n\n  - `\"name\"` (required) — Display name for the toolchain\n  - `\"path\"` (required) — Path to the Tolk compiler executable\n  - `\"description\"` — Optional description for the toolchain\n\n  Default configuration:\n\n  ```json\n  \"ton.tolk.toolchain.toolchains\": {\n    \"auto\": {\n      \"name\": \"Auto-detected\",\n      \"path\": \"\",\n      \"description\": \"Automatically detect Tolk compiler in node_modules\"\n    }\n  }\n  ```\n</ParamField>\n\n<ParamField\n  path=\"ton.tolk.toolchain.activeToolchain\"\n  type=\"string\"\n  default=\"auto\"\n>\n  Name of the active Tolk toolchain to use. The `\"auto\"` is a default toolchain that is automatically detected in `node_modules/`.\n</ParamField>\n\n<ParamField\n  path=\"ton.tolk.toolchain.showShortCommitInStatusBar\"\n  type=\"boolean\"\n  default={false}\n>\n  Whether to add a short commit hash after Tolk version in the status bar.\n</ParamField>\n\n#### Editor → Hints\n\n<ParamField\n  path=\"ton.tolk.hints.disable\"\n  type=\"boolean\"\n  default={false}\n>\n  Tolk: Disable all inlay hints.\n</ParamField>\n\n<ParamField\n  path=\"ton.tolk.hints.types\"\n  type=\"boolean\"\n  default={true}\n>\n  Tolk: Show type hints for variables and expressions.\n</ParamField>\n\n<ParamField\n  path=\"ton.tolk.hints.parameters\"\n  type=\"boolean\"\n  default={true}\n>\n  Tolk: Show parameter name hints in function calls.\n</ParamField>\n\n<ParamField\n  path=\"ton.tolk.hints.showMethodId\"\n  type=\"boolean\"\n  default={true}\n>\n  Tolk: Show method ID hints for get methods.\n</ParamField>\n\n<ParamField\n  path=\"ton.tolk.hints.constantValues\"\n  type=\"boolean\"\n  default={true}\n>\n  Tolk: Show computed values for constants.\n</ParamField>\n\n<ParamField\n  path=\"ton.func.hints.disable\"\n  type=\"boolean\"\n  default={false}\n>\n  FunC: Disable all inlay hints.\n</ParamField>\n\n<ParamField\n  path=\"ton.func.hints.showMethodId\"\n  type=\"boolean\"\n  default={true}\n>\n  FunC: Show method ID hints for functions with `method_id`.\n</ParamField>\n\n<ParamField\n  path=\"ton.func.hints.implicitConstantType\"\n  type=\"boolean\"\n  default={true}\n>\n  FunC: Show type hints for constants without explicit type.\n</ParamField>\n\n#### Editor → Completion\n\n<ParamField\n  path=\"ton.tolk.completion.typeAware\"\n  type=\"boolean\"\n  default={true}\n>\n  Tolk: Sort completion items by relevance to the current context type.\n</ParamField>\n\n<ParamField\n  path=\"ton.tolk.completion.addImports\"\n  type=\"boolean\"\n  default={true}\n>\n  Tolk: Automatically add necessary imports for symbols from other files.\n</ParamField>\n\n#### Editor → Inspections\n\n<ParamField\n  path=\"ton.tolk.inspections.disabled\"\n  type=\"string[]\"\n  default={[]}\n>\n  Tolk: List of disabled code inspections. All available inspections are enabled by default:\n\n  - `\"unused-parameter\"`\n  - `\"unused-type-parameter\"`\n  - `\"unused-variable\"`\n  - `\"unused-top-level-declaration\"`\n  - `\"unused-import\"`\n  - `\"deprecated-symbol-usage\"`\n  - `\"struct-initialization\"`\n  - `\"cannot-reassign\"`\n  - `\"need-not-null-unwrapping\"`\n  - `\"missed-semicolon\"`\n  - `\"call-arguments-count-mismatch\"`\n</ParamField>\n\n<ParamField\n  path=\"ton.func.inspections.disabled\"\n  type=\"string[]\"\n  default={[]}\n>\n  FunC: List of disabled code inspections. All available inspections are enabled by default:\n\n  - `\"unused-parameter\"`\n  - `\"unused-type-parameter\"`\n  - `\"unused-variable\"`\n  - `\"unused-import\"`\n</ParamField>\n\n#### Editor → Find Usages\n\n<ParamField\n  path=\"ton.tolk.findUsages.scope\"\n  type=\"string\"\n  default=\"workspace\"\n>\n  Tolk: Where to search when using \"Find Usages\". Allowed values:\n\n  - `\"workspace\"` (default) — Search only in workspace files\n  - `\"everywhere\"` — Search everywhere, including the standard library\n</ParamField>\n\n#### Fift\n\n<ParamField\n  path=\"ton.fift.hints.showGasConsumption\"\n  type=\"boolean\"\n  default={true}\n>\n  Show gas consumption hints for Fift instructions.\n</ParamField>\n\n<ParamField\n  path=\"ton.fift.semanticHighlighting.enabled\"\n  type=\"boolean\"\n  default={true}\n>\n  Enable/disable semantic highlighting for Fift files.\n</ParamField>\n\n#### BoC\n\n<ParamField\n  path=\"ton.boc.openDecompiledOnOpen\"\n  type=\"boolean\"\n  default={true}\n>\n  Automatically open decompiled Fift assembly when opening BoC files (with `.boc` extension).\n</ParamField>\n\n#### Formatter\n\n<ParamField\n  path=\"ton.tolk.formatter.useFormatter\"\n  type=\"boolean\"\n  default={true}\n>\n  Use experimental Tolk formatter.\n</ParamField>\n\n<ParamField\n  path=\"ton.tolk.formatter.sortImports\"\n  type=\"boolean\"\n  default={true}\n>\n  Sort imports on format.\n</ParamField>\n\n#### Sandbox\n\n<ParamField\n  path=\"ton.sandbox.port\"\n  type=\"number\"\n  default={3000}\n>\n  Port of the TON Sandbox server.\n</ParamField>\n\n<ParamField\n  path=\"ton.sandbox.binaryPath\"\n  type=\"string\"\n  default=\"./node_modules/.bin/ton-sandbox-server\"\n>\n  Path to the TON Sandbox server binary.\n</ParamField>\n\n### Command Palette\n\nThe <kbd>Ctrl+Shift+P</kbd> on Windows and Linux (and <kbd>⌘+⇧+P</kbd> on macOS) brings up the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette). This plugin provides a number of custom commands available for launch from the palette.\n\n#### General\n\n- `TON: Open decompiled BoC file`\n- `TON: Decompile BoC to TON Assembly file`\n- `TON: Debug contract`\n\n#### Tolk\n\n- `Tolk: Build project`\n- `Tolk: Get type at position`\n- `Tolk: Get contract ABI`\n- `Tolk: Get documentation at position`\n- `Tolk: Get scope information`\n- `Tolk: Get unresolved identifiers`\n- `Tolk: Show toolchain information`\n- `Tolk: Select active toolchain` — modifies the config\n- `Tolk: Add new toolchain` — modifies the config\n- `Tolk: Remove toolchain` — modifies the config\n- `Tolk: Manage toolchains` — modifies the config\n\n#### Sandbox\n\nWork everywhere:\n\n- `TON: Install TON Sandbox Server` — modifies the config\n- `TON: Start TON Sandbox Server`\n- `TON: Stop TON Sandbox Server`\n- `TON: Open Sandbox Terminal`\n\nOnly work in the Sandbox panel:\n\n- `TON: Refresh`\n- `TON: Refresh history`\n- `TON: Import history`\n- `TON: Export history`\n- `TON: Reset history`\n- `TON: Delete message template`\n- `TON: Copy contract ABI`\n- `TON: Copy address`\n"
  },
  {
    "path": "contract-dev/on-chain-jetton-processing.mdx",
    "content": "---\ntitle: \"On-chain Jetton processing\"\nsidebarTitle: \"Jetton processing\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside>\n  Read this article after understanding the [Jetton](/standard/tokens/jettons/overview) architecture.\n</Aside>\n\nContracts routinely process jettons for DEX, escrow, and lending protocols. Each contract must determine which jetton type arrived when a `JettonNotify` message shows up.\n\n```mermaid\ngraph LR\nA((Jetton Wallet)) -->|JettonNotify 0x7362d09c| B((Contract))\n```\n\n## Known Jetton or trusted deployer\n\nWhen someone does a Jetton transfer, they deploy a new `JettonWallet`, that has an address depending on the address of `JettonMinter` and the address of the receiver, and then send a message with a type `JettonNotify` to the regular wallet (or other kind of contract) that tells the transfer succeeded. The attacker might send a `JettonNotify` message from a contract that is not a valid `JettonWallet`, so handling it requires care.\n\nTo handle the `JettonNotify` message, it's preferable to precompute the address of the `JettonWallet` for a specific minter (i.e. Jetton type) in advance, so that the validation only consists of checking two addresses for equality.\n\nHere is an example of a contract that handles `JettonNotify` messages. It's deployed along with a `SetTrustedJettonWallet` message with an address of `JettonWallet` that is owned by this same contract.\n\nWhen deploying with this pattern, [calculate](/standard/tokens/jettons/find) the Jetton wallet address that must receive top-ups. It is impossible to hardcode the jetton wallet address in the contract's [`StateInit`](/foundations/messages/deploy), because the wallet address depends on the contract address and creates a circular dependency.\n\nTo handle several Jetton types with a single contract, `trustedJettonWallet` should be modified to store several addresses.\n\nThe `jettonMinter` address is included in `Storage`, because otherwise every instance of this contract owned by the same owner will deploy to the same address, even if there was an intent to have them with different `trustedJettonWallet`s.\n\nThis approach is used by [Bidask](https://bidask.finance/en/).\n\n```tolk expandable\ntolk 1.2;\n\nstruct Storage {\n    owner: address;\n    trustedJettonWallet: address?;\n    jettonMinter: address;\n}\n\nfun Storage.load(): Storage {\n    return Storage.fromCell(contract.getData());\n}\n\nfun Storage.save(self) {\n    return contract.setData(self.toCell())\n}\n\nstruct (0x7362d09c) JettonNotify {\n    queryId: uint64\n    jettonAmount: coins\n    transferInitiator: address\n    jettonVaultPayload: RemainingBitsAndRefs\n}\n\nstruct (0x12345678) SetTrustedJettonWallet {\n    trustedJettonWallet: address\n}\n\ntype AllowedMessage = JettonNotify | SetTrustedJettonWallet;\n\nfun onInternalMessage(in: InMessage) {\n    val msg = lazy AllowedMessage.fromSlice(in.body);\n    match (msg) {\n        SetTrustedJettonWallet => {\n            var storage = Storage.load();\n            if (storage.owner != in.senderAddress || storage.trustedJettonWallet != null) {\n                return;\n            }\n            storage.trustedJettonWallet = msg.trustedJettonWallet;\n            storage.save();\n        },\n        JettonNotify => {\n            var storage = Storage.load();\n            if (storage.trustedJettonWallet == null || storage.trustedJettonWallet != in.senderAddress) {\n                return;\n            }\n            // Process jettons\n        }\n    }\n}\n```\n\n## Unknown TEP-89 Jetton or untrusted deployer\n\nIn the previous example, addresses of `jettonMinter` and `trustedJettonWallet` are chosen off-chain by a deploying party. Someone who depends on this contract has to trust that the wallet belongs to this minter, which is not a problem, for example, for an exchange. If deployer might be monetarily interested to break this invariant, the previous approach is not suitable, and the address of the `trustedJettonWallet` address must be computed on-chain.\n\nMost modern Jettons implement [TEP-89](https://github.com/ton-blockchain/TEPs/blob/66675fc7ecda1e3dc1524159d6bfcaa2ed2372fe/text/0089-jetton-wallet-discovery.md), that defines a message `provide_wallet_address` that requests a Jetton wallet address for an arbitrary owner, and `take_wallet_address` message with a response.\n\nThe contract works similarly to the example above, except it's deployed along with a `InitContract` message, that asks a `JettonMinter` what `jettonWalletAddress` should be.\n\nThis approach is used by [DeDust](https://dedust.io/).\n\n```mermaid\ngraph LR\nA((Deployer))\nB((Contract))\nC((Jetton minter))\nD((Contract))\n\n    A -->|InitContract| B\n    B -->|ProvideWalletAddress| C\n    C -->|TakeWalletAddress| D\n```\n\nThe contract that initializes the jetton wallet with this pattern can look like this:\n\n```tolk expandable\ntolk 1.2\n\nstruct Storage {\n    jettonMinterAddress: address\n    jettonWalletAddress: address?\n}\n\nfun Storage.load(): Storage {\n    return Storage.fromCell(contract.getData());\n}\n\nfun Storage.save(self) {\n    return contract.setData(self.toCell())\n}\n\nstruct (0x2c76b973) ProvideWalletAddress {\n    queryId: uint64\n    ownerAddress: address\n    includeAddress: bool\n}\n\nstruct (0xd1735400) TakeWalletAddress {\n    queryId: uint64\n    walletAddress: address\n    ownerAddress: Cell<address>?\n}\n\nstruct (0x7362d09c) JettonNotify {\n    queryId: uint64\n    jettonAmount: coins\n    transferInitiator: address\n    jettonVaultPayload: RemainingBitsAndRefs\n}\n\n// Unlike other opcodes here, this can be set arbitrarily\nstruct (0x12345678) InitContract {}\n\ntype AllowedMessage = InitContract | TakeWalletAddress | JettonNotify\n\nfun onInternalMessage(in: InMessage) {\n    val msg = lazy AllowedMessage.fromSlice(in.body);\n    match (msg) {\n        InitContract => {\n            var storage = Storage.load();\n            val msg = createMessage({\n                bounce: true,\n                value: 0,\n                dest: storage.jettonMinterAddress,\n                body: ProvideWalletAddress {\n                    queryId: 0,\n                    ownerAddress: contract.getAddress(),\n                    includeAddress: false,\n                },\n            });\n            msg.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE);\n        }\n        TakeWalletAddress => {\n            var storage = Storage.load();\n            if (storage.jettonMinterAddress != in.senderAddress) {\n                return;\n            }\n            storage.jettonWalletAddress = msg.walletAddress;\n            storage.save();\n            // After receiving such message contract is initialized\n        }\n        JettonNotify => {\n            var storage = Storage.load();\n            if (storage.jettonWalletAddress == null || storage.jettonWalletAddress != in.senderAddress) {\n                return;\n            }\n            // Process jettons\n        }\n    }\n}\n```\n\n## Unknown TEP-74 Jetton and untrusted deployer\n\nJettons that do not have TEP-89 methods for computing a wallet address on-chain are rare. [TONCO DEX](https://tonco.io/) rejects them, while platforms such as [DeDust](https://dedust.io/) allow them after a manual approval flow. There are two approaches, both using get-method emulation.\n\n### Running get-method on-chain\n\nGiven a Jetton minter state, we can emulate execution of the minter on-chain via [RUNVM](/tvm/instructions#db4-runvm) instruction. During the emulation, it calls the `get_wallet_address` [get-method](/tvm/get-method) to derive the wallet address for any owner.\n\nThis helper uses [Fift](/languages/fift/overview), because it's impossible to assign a type to `c7`.\n\n```tolk expandable\nfun calculateJettonWallet(owner: address, jettonData: cell, jettonCode: cell, jettonMinter: address): address asm \"\"\"\n    c7 PUSHCTR\n    // Unpack environment information from c7\n    // https://docs.ton.org/tvm/registers#c7-%E2%80%94-environment-information-and-global-variables\n    0 INDEX\n    SWAP\n    8 SETINDEX\n    SWAP\n    DUP\n    ROTREV\n    10 SETINDEX\n    // Make it singleton\n    1 TUPLE\n    // owner md mc c7\n    ROTREV\n    CTOS            // owner_addr c7 md mc\"\n    2 PUSHINT       // owner_addr c7 md mc args\"\n    103289 PUSHINT  // owner_addr c7 md mc args get_jwa_method_id\"\n    5 0 REVERSE     // owner_addr get_jwa_method_id args mc md c7\"\n    // Moves the top stack value (ONE) to the third position: [A, B, C] -> [B, C, A]. We expect only 1 return value. Flag +256 for runvm enables this argument\n    ONE 2 -ROLL\n    // We use only these modes:\n    // +1 = same_c3 (set c3 to code)\n    // +4 = load c4 (persistent data) from stack and return its final value\n    // +16 = load c7 (smart-contract context)\n    // +256 = pop number N, return exactly N values from stack (only if res=0 or 1; if not enough then res=stk_und)\n    // Mode 256 is crucial, because it ignores all stack values except the first one, and protects us from stack poisoning\n    277 RUNVM        // address exit_code c4'\"\n    2 BLKDROP       // address\";\n\"\"\"\n```\n\n### Approach 1: non-vanity addresses\n\nIf the `JettonMinter` was not deployed with a [vanity](/contract-dev/vanity) contract, address and `StateInit` match. The logic for the contract that handles `JettonNotify` messages is thus\n\n1. get the `StateInit` of `JettonMinter` off-chain;\n1. deploy the contract with the address of `JettonMinter` in its data;\n1. send a message to the contract with the `StateInit` of `JettonMinter`;\n1. contract validates that this `StateInit` matches the address of the `JettonMinter`;\n1. contract runs `calculateJettonWallet`\n   - `owner` - address of the contract (`contract.getAddress()`);\n   - `jettonData`, `jettonCode` - `StateInit` of `JettonMinter`;\n   - `jettonMinter` - address of `JettonMinter`.\n\n### Approach 2: where the previous method fails\n\nIf the `JettonMinter` was deployed with a vanity contract, or otherwise lacks `get_wallet_address` method, or `get_wallet_address` returns incorrect addresses, we have to use the current state of the contract instead.\n\nTo prove that the state is currently at the Jetton minter address, a full [state proof](/foundations/proofs/overview) is required.\n"
  },
  {
    "path": "contract-dev/random.mdx",
    "content": "---\ntitle: \"Random number generation\"\nsidebarTitle: \"Random numbers\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nGenerating random numbers is a common task in smart contracts for applications such as gaming, NFT trait generation, and decentralized lotteries. TON provides built-in functions like [`random()`](/languages/func/stdlib#random), but their results can be predicted by validators unless additional techniques are used.\n\n<Aside\n  type=\"caution\"\n>\n  Single-block randomness (such as [`randomize_lt()`](/languages/func/stdlib#randomize-lt)) is not secure against validators who can influence or predict values. For stronger guarantees, use multi-phase schemes such as commit-reveal.\n</Aside>\n\n## Why on-chain randomness is challenging\n\nComputers cannot generate truly random information because they strictly follow instructions. Instead, pseudorandom number generators (PRNGs) rely on a _seed_ value to produce a sequence of pseudorandom numbers. Running the same program with the same seed will always produce identical results.\n\nIn TON, the seed varies for each block and is generated by validators. While this prevents regular users from predicting random values before block production, validators themselves can influence randomness in two ways:\n\n1. Generating different seeds when creating blocks\n1. Choosing which blocks to include external messages in\n\nThis fundamental limitation means all approaches to on-chain randomness involve trade-offs between speed, security, and decentralization guarantees.\n\n## Approach 1: Single-block randomness with `randomize\\_lt()`\n\n### Mechanism\n\nThe [`randomize_lt()`](/languages/func/stdlib#randomize-lt) function mixes the transaction's logical time into the random seed before generating random numbers. This provides basic entropy from blockchain state.\n\n### How it works\n\nCall [`randomize_lt()`](/languages/func/stdlib#randomize-lt) once before using [`random()`](/languages/func/stdlib#random) or [`rand()`](/languages/func/stdlib#rand) functions. The logical time adds variability to the seed, making it harder for observers to predict the outcome without executing the transaction.\n\n```func\nrandomize_lt();\n// Generates values from 0 to 99\nint random_number = rand(100);\n```\n\n### Security model\n\n- ✅ Safe against regular users who cannot predict logical time\n- ⚠️ Vulnerable to colluding validators who can generate seeds or choose message inclusion blocks\n\n### Speed\n\nFast (single-block operation)\n\n### Use cases\n\n- Non-critical applications (gaming, cosmetic features)\n- NFT trait randomization\n- Scenarios where validator trust is assumed\n\n<Aside\n  type=\"caution\"\n>\n  Validators can predict single-block randomness. Do not use it for high-value applications such as financial lotteries or significant asset distribution.\n</Aside>\n\n## Approach 2: Block skipping\n\n### Mechanism\n\nInstead of using randomness from the current block, the contract waits for several blocks to pass before using their entropy. This approach sends messages across multiple blocks, making it harder for a single validator to control the final outcome.\n\n### How it works\n\nThe contract initiates an operation, then waits for responses that arrive several blocks later. The random seed from future blocks—which the initiating validator does not control—determines the result.\n\n### Security model\n\n- ✅ Resistant to regular users\n- ✅ More resistant to single validators than `randomize_lt()`\n- ⚠️ Still vulnerable to determined validators who can coordinate timing across multiple blocks they generate\n\n### Speed\n\nSlow (requires multiple blocks to finalize)\n\n### Use cases\n\n- Medium-stakes applications\n- Lottery systems with moderate value\n- Scenarios requiring better security than single-block randomness\n\n<Aside>\n  While block skipping improves security over single-block randomness, it only delays the threat. A validator representing 1/250 of the network can still choose optimal timing to influence outcomes in blocks they generate.\n</Aside>\n\n## Approach 3: Commit-reveal scheme\n\n### Mechanism\n\nParticipants commit to secret values by publishing hashes, then reveal those values in a later phase. The final randomness is derived from combining all revealed values, ensuring no single party can determine the outcome alone. When properly implemented, this approach provides cryptographically secure randomness suitable for high-value applications.\n\n### How it works\n\n1. Commit phase: Each participant generates a random number off-chain and submits its hash to the contract.\n1. Reveal phase: After all commitments are received, participants disclose their original numbers.\n1. Combination: The contract combines the revealed numbers (e.g., by XOR or sum) to produce the final random value.\n\n### Security model\n\n- ✅ Cryptographically secure when properly implemented\n- ✅ Resistant to both user and validator manipulation; no single party can predict or influence the outcome\n- ⚠️ Requires incentives and penalties to prevent participants from refusing to reveal\n- ⚠️ Validators can influence timing or censor messages, but cannot determine the random value\n\n### Speed\n\nVery slow (multi-phase, multi-block process)\n\n### Implementation requirements\n\n- On-chain verification of commitments\n- Penalty mechanisms for non-reveals or invalid reveals\n- Timeout handling for missing participants\n\n### Use cases\n\n- High-value applications (significant lotteries, auctions)\n- Decentralized gaming with financial stakes\n- Systems requiring Byzantine fault tolerance\n\n<Aside\n  type=\"caution\"\n>\n  Commit-reveal schemes require careful incentive design. Participants may refuse to reveal if the outcome is unfavorable. Use penalties or collateral to enforce honest behavior.\n</Aside>\n\n## Comparison of approaches\n\n| Factor                               | `randomize_lt()` | Block skipping      | Commit-reveal                         |\n| ------------------------------------ | ---------------- | ------------------- | ------------------------------------- |\n| Speed                                | Fast             | Slow                | Very slow                             |\n| Implementation complexity            | Low              | Medium              | High                                  |\n| Resistance to user manipulation      | High             | High                | Cryptographically secure              |\n| Resistance to validator manipulation | Low              | Medium              | High (validators cannot predict)      |\n| Cost (gas + storage)                 | Low              | Medium              | High                                  |\n| Suitable for high-value applications | ❌ No            | ⚠️ Use with caution | ✅ Yes (recommended for critical use) |\n\n<Aside type=\"tip\">\n  When choosing an approach, consider the value at risk and required time-to-finality. For high-stakes applications such as lotteries with significant funds, use commit-reveal. Audit implementations through formal verification when possible.\n</Aside>\n\n## Best practices\n\n- Avoid standalone [`random()`](/languages/func/stdlib#random) calls. Validators controlling the block seed can predict the output.\n- Keep randomness out of external message receivers. External messages remain vulnerable even with [`randomize_lt()`](/languages/func/stdlib#randomize-lt).\n- Use hybrid or off-chain entropy for critical applications. Combine on-chain randomness with off-chain entropy or external randomness oracles when significant value is at risk.\n- Test randomness behavior across different blocks. Verify that the contract behaves correctly when randomness is manipulated within validator capabilities.\n\n## How block random seeds work\n\nUnderstanding the underlying mechanism helps evaluate security trade-offs.\n\n### Seed generation by validators\n\nEach block's random seed is generated by the validator (or collator) creating that block. The [validator node code](https://github.com/ton-blockchain/ton/blob/f59c363ab942a5ddcacd670c97c6fbd023007799/validator/impl/collator.cpp#L1590) generates 32 random bytes using cryptographically secure primitives:\n\n```cpp\nprng::rand_gen().strong_rand_bytes(rand_seed->data(), 32);\n```\n\nA single validator generates this seed when creating a block, giving them control over the seed value. This is why single-block randomness is vulnerable to validator manipulation.\n\n### Per-contract randomization\n\nThe block seed is not used directly in contracts. Instead, it is [hashed with the contract address](https://github.com/ton-blockchain/ton/blob/f59c363ab942a5ddcacd670c97c6fbd023007799/crypto/block/transaction.cpp#L876) to produce a per-contract seed:\n\n```text\ncontract_seed = SHA256(block_seed || contract_address)\n```\n\nThis ensures different contracts in the same block receive different random seeds, preventing cross-contract randomness correlation.\n\n### Random number generation\n\nThe [`RANDU256`](/tvm/instructions#f810-randu256) TVM instruction implements the actual random number generation. When called:\n\n1. Take the current seed `r` (32 bytes)\n1. Compute `SHA512(r)`\n1. Use the first 32 bytes as the new seed\n1. Return the remaining 32 bytes as the random number\n\nSubsequent calls continue this chain, producing a deterministic sequence from the initial seed.\n\n<Aside>\n  Because the random sequence is deterministic once the initial seed is known, anyone who knows both the block seed and contract address can predict all random values generated during a transaction. Regular users cannot predict these values before block production, but validators generating the block can, since they control the block seed.\n</Aside>\n"
  },
  {
    "path": "contract-dev/security.mdx",
    "content": "---\ntitle: Security best practices\n---\n\nThere are several anti-patterns and potential attack vectors that smart contract developers should be aware of. These can affect the security, efficiency, and correctness of the contracts. Below are some common pitfalls and best practices to avoid them.\n\n## Signed/unsigned integer vulnerabilities\n\nImproper handling of signed integers can allow attackers to exploit overflow/underflow conditions.\n\n### Vulnerable code\n\n```func\n(cell,()) transfer_voting_power(cell votes, slice from, slice to, int amount) impure {\n    int from_votes = get_voting_power(votes, from);\n    int to_votes = get_voting_power(votes, to);\n    \n    from_votes -= amount;  // Can become negative!\n    to_votes += amount;\n    \n    votes~set_voting_power(from, from_votes);\n    votes~set_voting_power(to, to_votes);\n    return (votes,());\n}\n```\n\n### Secure implementation\n\n```func\n(cell,()) transfer_voting_power(cell votes, slice from, slice to, int amount) impure {\n    int from_votes = get_voting_power(votes, from);\n    int to_votes = get_voting_power(votes, to);\n    \n    throw_unless(998, from_votes >= amount);  // Validate sufficient balance\n    \n    from_votes -= amount;\n    to_votes += amount;\n    \n    votes~set_voting_power(from, from_votes);\n    votes~set_voting_power(to, to_votes);\n    return (votes,());\n}\n```\n\n## Sending sensitive data on-chain\n\nThe entire smart contract computation is transparent; confidential runtime values can be retrieved through emulation.\n\n### Vulnerable code\n\n```func\n;; DON'T: Storing password hash or private data\ncell private_data = begin_cell()\n    .store_slice(\"secret_password_hash\")\n    .store_uint(user_private_key, 256)\n    .end_cell();\n```\n\n## Account destruction race conditions\n\nDestroying accounts using [send mode](/foundations/messages/modes) `128 + 32` without proper checks can lead to fund loss in race conditions.\n\n### Vulnerable code\n\n```func\n() recv_internal(msg_value, in_msg_full, in_msg_body) {\n    if (in_msg_body.slice_empty?()) {\n        return ();  ;; Dangerous: empty message handling\n    }\n    \n    ;; Process and destroy account\n    send_raw_message(msg, 128 + 32);  ;; Destroys account\n}\n```\n\n### Secure approach\n\n```func\n() recv_internal(msg_value, in_msg_full, in_msg_body) {\n    ;; Proper validation before any destruction\n    throw_unless(error::unauthorized, authorized_sender?(sender));\n    \n    ;; Ensure no pending operations\n    throw_unless(error::pending_operations, safe_to_destroy?());\n    \n    ;; Then proceed with destruction if really needed\n}\n```\n\n## Missing replay protection\n\nReplay protection is a security mechanism that prevents an attacker from [reusing a previous message](https://en.wikipedia.org/wiki/Replay_attack). External messages without replay protection can be re-executed multiple times by an attacker which could lead to fund loss or other undesired behavior.\n\n### Secure implementation\n\n```func\n() recv_external(slice in_msg) impure {\n    slice ds = get_data().begin_parse();\n    int stored_seqno = ds~load_uint(32);\n    int msg_seqno = in_msg~load_uint(32);\n    \n    throw_unless(33, msg_seqno == stored_seqno);  ;; Prevent replay\n    \n    accept_message();\n    \n    ;; Update sequence number\n    set_data(begin_cell().store_uint(stored_seqno + 1, 32).end_cell());\n}\n```\n\n## Unconditional accepting of external messages\n\nIncoming [external messages](/foundations/messages/external-in) do not transfer funds. Receiving smart contract must pay for their processing from its balance. Upon receiving an external message, a smart contract can spend some free gas ([`gas_credit`](/foundations/config#param-20-and-21%3A-gas-prices)) in order to decide whether it is ready to accept it, and then pay for its further processing.\n\nExternal messages are usually accepted through the [`ACCEPT`](/tvm/instructions#f800-accept) TVM instruction, which sets `gas_limit` to its maximum possible value specified in the network configuration, and sets `gas_credit` to zero. From this point on, the contract will have to pay for the entire processing of the incoming message.\n\nTherefore, if `ACCEPT` is not guarded by a condition, an attacker might repeatedly send messages, and spend the entire balance of the contract.\n\nThe [`SETGASLIMIT`](/tvm/instructions#f801-setgaslimit) instruction can lead to the same issue.\n\n### Vulnerable code\n\n```func\n() recv_external(slice in_msg) {\n    accept_message();\n    ;; ...\n}\n```\n\n### Secure implementation\n\nChecks before accepting an external message vary by use case. The following example is a part of [wallet v3 code](https://github.com/ton-blockchain/ton/blob/53ec9684bd213983e1fe0f7610d3e3453a4ec628/crypto/smartcont/wallet3-code.fc), that doesn't accept a message if it isn't signed by the wallet's owner.\n\n```func\n() recv_external(slice in_msg) impure {\n    ;; parse message and contract storage (omitted)\n    throw_unless(33, msg_seqno == stored_seqno);\n    throw_unless(34, subwallet_id == stored_subwallet);\n    throw_unless(35, check_signature(slice_hash(in_msg), signature, public_key));\n    accept_message();\n    ;; handle the message (omitted)\n}\n```\n\n## Invalid throw values\n\nExit codes `0` and `1` indicate normal execution of the compute phase of the transaction. Execution can be unexpectedly aborted by calling a `throw` directly with exit codes `0` and `1`. This can make debugging very difficult since such aborted execution would be indistinguishable from a normal one.\n\n## Gas limitation\n\nBe careful with the [Out of gas error](/tvm/exit-codes#13%3A-out-of-gas-error). It cannot be handled, so try to pre-calculate the gas consumption whenever possible. This will help avoid wasting extra gas, as the transaction will fail anyway.\n\n### Secure implementation\n\n```tact\nmessage Vote { votes: Int as int32 }\n\ncontract VoteCounter() {\n    const voteGasUsage = 10000; // precompute with tests\n\n    receive(msg: Vote) {\n        require(context().value > getComputeFee(self.voteGasUsage, false), \"Not enough gas!\");\n        // ...subsequent logic...\n    }\n\n    // Empty receiver for the deployment,\n    // which forwards the remaining value back to the sender\n    receive() { cashback(sender()) }\n}\n```\n\n## Insecure random numbers\n\nGenerating truly secure random numbers in TON is challenging. The built-in random functions are pseudo-random and depend on logical time. An attacker can predict the randomized number by [brute-forcing](https://en.wikipedia.org/wiki/Brute-force_attack) the logical time in the current block.\n\n### Secure approach\n\n- For critical applications, avoid relying solely on on-chain solutions.\n\n- Use built-in random functions with randomized logical time to enhance security by making predictions harder for attackers without access to a validator node. Note, however, that it is still not entirely foolproof.\n\n- Consider using the _commit-and-disclose scheme_:\n\n1. Participants generate random numbers off-chain and send their hashes to the contract.\n1. Once all hashes are received, participants disclose their original numbers.\n1. Combine the disclosed numbers (e.g., summing them) to produce a secure random value.\n\n- Don't use randomization in external message receivers, as it remains vulnerable even with randomized logical time.\n\n## Executing third-party code\n\nExecuting untrusted code can compromise contract security.\n\n### Prevention\n\n```func\n;; Validate all external code before execution\nthrow_unless(error::untrusted_code, verify_code_signature(code));\nthrow_unless(error::invalid_code, validate_code_safety(code));\n```\n\n## Race condition of messages\n\nA message cascade can be processed over many blocks. Assume that while one message flow is running, an attacker can initiate a second message flow in parallel. That is, if a property was checked at the beginning, such as whether the user has enough tokens, do not assume that it will still be satisfied at the third stage in the same contract.\n\n## Preventing front-running with signature verification\n\nIn TON blockchain, all pending messages are publicly visible in the mempool. Front-running can occur when an attacker observes a pending transaction containing a valid signature and quickly submits their own transaction using the same signature before the original transaction is processed.\n\n### Secure approach\n\nInclude critical parameters like the recipient address (`to`) within the data that is signed. This ensures that the signature is valid only for the intended operation and recipient, preventing attackers from reusing the signature for their benefit. Also, implement replay protection to prevent the same signed message from being used multiple times.\n\n```tact\nstruct RequestBody {\n    to: Address;\n    seqno: Int as uint64;\n}\n\nmessage(0x988d4037) Request {\n    signature: Slice as bytes64;\n    requestBody: RequestBody;\n}\n\ncontract SecureChecker(\n    publicKey: Int as uint256,\n    seqno: Int as uint64, // Add seqno for replay protection\n) {\n    receive(request: Request) {\n        // Verify the signature against the reconstructed data hash\n        require(checkSignature(request.requestBody.toCell().hash(), request.signature, self.publicKey), \"Invalid signature!\");\n\n        // Check replay protection\n        require(request.requestBody.seqno == self.seqno, \"Invalid seqno\"); // Assuming external message with seqno\n        self.seqno += 1; // Increment seqno after successful processing\n\n        // Ensure the message is sent to the address specified in the signed data\n        message(MessageParameters {\n            to: request.requestBody.to, // Use the 'to' from the signed request\n            value: 0,\n            mode: SendRemainingBalance, // Caution: sending the whole balance!\n            bounce: false,\n            body: \"Your action payload here\".asComment(), // Example body\n        });\n    }\n\n    // Empty receiver for the deployment,\n    // which forwards the remaining value back to the sender\n    receive() { cashback(sender()) }\n\n    get fun seqno(): Int {\n        return self.seqno;\n    }\n}\n\n```\n\nRemember to also implement replay protection to prevent reusing the same signature even if it's correctly targeted.\n\n### Vulnerable approach\n\nDo not sign data without including essential context like the recipient address. An attacker could intercept the message, copy the signature, and replace the recipient address in their own transaction, effectively redirecting the intended action or funds.\n\n```tact\nmessage(0x988d4037) Request {\n    signature: Slice as bytes64;\n    data: Slice as remaining; // 'to' address is not part of the signed data\n}\n\ncontract InsecureChecker(\n    publicKey: Int as uint256,\n) {\n    receive(request: Request) {\n        // The signature only verifies 'request.data', not the intended recipient.\n        if (checkDataSignature(request.data.hash(), request.signature, self.publicKey)) {\n            // Attacker can see this message, copy the signature, and send their own\n            // message to a different 'to' address before this one confirms.\n            // The 'sender()' here is the original sender, but the attacker can initiate\n            // a similar transaction targeting themselves or another address.\n            message(MessageParameters {\n                to: sender(), // Vulnerable: recipient isn't verified by the signature\n                value: 0,\n                mode: SendRemainingBalance, // Caution: sending the whole balance!\n                bounce: false,\n            });\n        }\n    }\n\n    // Empty receiver for the deployment,\n    // which forwards the remaining value back to the sender\n    receive() { cashback(sender()) }\n}\n```\n\nFurthermore, once a signature is used in a transaction, it becomes publicly visible on the blockchain. Without proper replay protection, anyone can potentially reuse this signature and the associated data in a new transaction if the contract logic doesn't prevent it.\n\n## Return gas excesses carefully\n\nIf excess gas is not returned to the sender, funds accumulate in contracts over time. This is suboptimal. Add a function to rake out excess, but popular contracts like [Jetton wallet](/standard/tokens/jettons/how-it-works) return it to the sender with a message using the `0xd53276db` opcode.\n\n### Secure gas handling\n\n```func\nmessage(0xd53276db) Excesses {}\nmessage Vote { votes: Int as int32 }\n\ncontract Sample(\n    votes: Int as uint32,\n) {\n    receive(msg: Vote) {\n        self.votes += msg.votes;\n\n        message(MessageParameters {\n            to: sender(),\n            value: 0,\n            mode: SendRemainingValue | SendIgnoreErrors,\n            body: Excesses {}.toCell(),\n        });\n    }\n\n    // Empty receiver for the deployment,\n    // which forwards the remaining value back to the sender\n    receive() { cashback(sender()) }\n}\n```\n\n## Pulling data from another contract\n\nContracts in the blockchain can reside in separate shards processed by another set of validators. This means that one contract cannot pull data from another contract. Specifically, no contract can call a getter function from another contract.\n\nThus, any on-chain communication is asynchronous and done by sending and receiving messages.\n\n### Secure approach\n\nExchange messages to pull data from another contract.\n\n```tact\nmessage GetMoney {}\nmessage ProvideMoney {}\nmessage TakeMoney { money: Int as coins }\n\ncontract OneContract(\n    money: Int as coins,\n) {\n    receive(msg: ProvideMoney) {\n        message(MessageParameters {\n            to: sender(),\n            value: 0,\n            mode: SendRemainingValue | SendIgnoreErrors,\n            body: TakeMoney { money: self.money }.toCell(),\n        });\n    }\n\n    // Empty receiver for the deployment,\n    // which forwards the remaining value back to the sender\n    receive() { cashback(sender()) }\n}\n\ncontract AnotherContract(\n    oneContractAddress: Address,\n) {\n    receive(_: GetMoney) {\n        message(MessageParameters {\n            to: self.oneContractAddress,\n            value: 0,\n            mode: SendRemainingValue | SendIgnoreErrors,\n            bounce: false,\n            body: ProvideMoney {}.toCell(),\n        });\n    }\n\n    receive(msg: TakeMoney) {\n        require(sender() == self.oneContractAddress, \"Invalid money provider!\");\n        // ...further processing...\n    }\n\n    // Empty receiver for the deployment,\n    // which forwards the remaining value back to the sender\n    receive() { cashback(sender()) }\n}\n```\n\n## TON address representation issues\n\n[TON addresses](/foundations/addresses/formats) have multiple formats that must be handled correctly.\n\n### Address formats\n\n```func\n;; Raw: 0:b4c1b2ede12aa76f4a44353944258bcc8f99e9c7c474711a152c78b43218e296\n;; Bounceable: EQC0wbLt4Sqnb0pENTlEJYvMj5npx8R0cRoVLHi0MhjilkPX\n;; Non-bounceable: UQC0wbLt4Sqnb0pENTlEJYvMj5npx8R0cRoVLHi0Mhjilh4S\n\n;; Always validate workchain\nforce_chain(to_address);\n```\n\n## Name collision vulnerabilities\n\nFunction or variable names can collide with built-in functions or reserved keywords.\n\n### Best practice\n\n```func\n;; Use descriptive, unique names\nint user_balance = 0;  ;; Instead of just 'balance'\n() validate_user_signature()  ;; Instead of just 'validate()'\n```\n\n## Incorrect data type handling\n\nReading or writing incorrect data types can corrupt contract state.\n\n### Vulnerable code\n\n```func\n;; Writing uint but reading int\nstorage~store_uint(value, 32);\nint read_value = storage~load_int(32);  ;; Type mismatch\n```\n\n### Secure implementation\n\n```func\n;; Consistent type usage\nstorage~store_uint(value, 32);\nint read_value = storage~load_uint(32);\n```\n\n## Missing function return value checks\n\nIgnoring function return values can lead to logic errors and unexpected behavior.\n\n### Vulnerable code:\n\n```func\ndictinfos~udict_delete?(32, index);  ;; Ignoring success flag\n```\n\n### Secure implementation:\n\n```func\nint success = dictinfos~udict_delete?(32, index);\nthrow_unless(error::fail_to_delete_dict, success);\n```\n\n## Contract code updates\n\nContracts can be updated if not properly protected, changing their behavior unexpectedly.\n\n### Secure implementation\n\n```func\n() update_code(cell new_code) impure {\n    throw_unless(error::unauthorized, authorized_admin?(sender()));\n    throw_unless(error::invalid_code, validate_code?(new_code));\n    \n    set_code(new_code);\n}\n```\n"
  },
  {
    "path": "contract-dev/signing.mdx",
    "content": "---\ntitle: \"Signing messages\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nCryptographic signatures are the foundation of access control. Contracts verify signatures on-chain and implement their own authorization policies for [wallet operations](/standard/wallets/how-it-works#how-ownership-verification-works), server-authorized actions, [gasless transactions](/standard/wallets/v5#gasless-transactions), multisig wallets, and delegation.\n\n## Ed25519 in TON\n\nTON uses [Ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519) as the [standard](/foundations/whitepapers/tblkch#a-3-10-cryptographic-ed25519-signatures) signature scheme. All [wallets](/standard/wallets/history) (v1–v5) and [highload wallets](/standard/wallets/highload/overview) rely on Ed25519.\n\nSpecification:\n\n- Public key size: 256 bits\n- Signature size: 512 bits\n- Curve: Ed25519\n\n<Aside\n  type=\"caution\"\n>\n  The public key is _not_ the wallet address. The address is derived from the contract's initial code and data that are included in [`StateInit`](/foundations/messages/deploy) structure. Multiple contracts can use the same public key but have [different addresses](/foundations/addresses/overview).\n</Aside>\n\n## Other primitives\n\nTVM exposes additional cryptographic primitives beyond Ed25519. These are useful for cross-chain compatibility and advanced protocols:\n\n| Primitive                                                                                     | Purpose                                                                      |\n| --------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |\n| [secp256k1](https://en.wikipedia.org/wiki/Secp256k1)                                          | Ethereum-style ECDSA via `ECRECOVER`; x-only pubkey operations (TVM v9+)     |\n| [secp256r1 (P-256)](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm) | ECDSA verification via `P256_CHKSIGNS` and `P256_CHKSIGNU`                   |\n| [BLS12-381](https://en.wikipedia.org/wiki/BLS_digital_signature)                              | Pairing-based operations for signature aggregation and zero-knowledge proofs |\n| [Ristretto255](https://en.wikipedia.org/wiki/Curve25519#Ristretto)                            | Prime-order group over Curve25519 for advanced cryptographic constructions   |\n\nFor details, see crypto instructions in [TVM instructions](/tvm/instructions).\n\nThis guide focuses on Ed25519, usually used for TON.\n\n## Signing pipeline\n\nEd25519 signatures in TON typically work with hashes rather than raw data, because signing the hash takes a smaller and constant amount of time.\n\n- Off-chain (TypeScript)\n  - Serialize message data into a cell\n  - Compute its hash (256 bits)\n  - Sign the hash with private key\n  - Signature (512 bits)\n- On-chain (Tolk)\n  - Contract receives signature and data\n  - Recomputes the hash\n  - Verifies signature matches the hash and public key\n\nTVM provides two signature verification methods:\n\n- [`CHKSIGNS`](/tvm/instructions#f911-chksigns) checks signature of data;\n- [`CHKSIGNU`](/tvm/instructions#f910-chksignu) checks signature of hash.\n\nHash-based verification (`CHKSIGNU`) is preferred because `CHKSIGNS` only processes data from a single cell (up to $127 * 8 = 1016$ bits) and ignores cell references. For messages containing multiple cells or references, hashing the entire structure first is required.\n\n## Signature interaction patterns\n\nSignatures are used in different ways depending on who signs the message, who sends it, and who pays for execution. Here are three real-world examples.\n\n### Example 1: Standard wallets (v1–v5)\n\nStandard wallet contracts are [described in more detail](/standard/wallets/history) in the wallets section.\n\nHow it works:\n\n1. User signs a message off-chain (includes replay protection data and transfer details)\n1. User sends external message to blockchain\n1. Wallet contract verifies the signature\n1. Wallet contract checks seqno for replay protection\n1. Wallet contract accepts message (pays gas from wallet balance)\n1. Wallet contract increments seqno\n1. Wallet contract executes the transfer\n\nKey characteristics:\n\n- Who signs: User\n- Who sends: User (external message)\n- Who pays gas: Wallet contract\n\nThis is the most common pattern.\n\n### Example 2: Gasless transactions (Wallet v5)\n\nHow it works:\n\n1. User signs a message off-chain that includes two transfers: one to recipient, one to service as payment\n1. User sends signed message to service via API\n1. Service verifies the signature\n1. Service wraps signed message in internal message\n1. Service sends internal message to user's wallet (pays gas in TON)\n1. Wallet contract verifies user's signature\n1. Wallet contract checks seqno for replay protection\n1. Wallet contract increments seqno\n1. Wallet contract executes both transfers (to recipient and to service)\n\nKey characteristics:\n\n- Who signs: User\n- Who sends: Service (internal message)\n- Who pays gas: Service (in TON), gets compensated in Jettons\n\nThis pattern enables users to pay gas in Jettons instead of TON.\n\n### Example 3: Server-controlled operations\n\nHow it works:\n\n1. User requests authorization from server\n1. Server validates request and signs authorization message (includes validity period and operation parameters)\n1. User sends server-signed message to contract (with payment)\n1. Contract verifies server's signature\n1. Contract checks validity period\n1. Contract performs authorized action (deploy, mint, claim)\n1. If user tries to send same message again, contract ignores it (state already changed)\n\nKey characteristics:\n\n- Who signs: Server\n- Who sends: User (internal message with payment)\n- Who pays gas: User\n\nThis pattern is useful when backend needs to authorize specific operations (auctions, mints, claims) without managing private keys for each user.\n\nReal-world example: [telemint contract](https://github.com/TelegramMessenger/telemint) uses server-signed messages to authorize NFT deployments.\n\n## Message structure for signing\n\nWhen designing a signed message, the choice is how to organize the signed data — the message fields that will be hashed and verified. The key question: is the signed data a **slice** (part of a cell) or a **cell** (separate cell)? This affects gas consumption during signature verification.\n\n### Approach 1: Signed data as slice\n\nAfter loading the signature from the message body, the signed data remains as a **slice** — a part of the cell that may contain additional data and references.\n\nUsed in: Wallet v1-v5\n\nSchema — Wallet v3r2:\n\n```tlb\nmsg_body$_ signature:bits512 subwallet_id:uint32\n           seqno:uint32 valid_until:uint32\n           mode:uint8 message_to_send:^Cell\n           = ExternalInMessage;\n```\n\n```mermaid\ngraph\n    subgraph Cell[\"Message body\"]\n        direction LR\n        A[**signature**]\n        subgraph Signed[\"Signed data\"]\n        direction LR\n            B[subwallet_id]\n            C[seqno]\n            D[valid_until]\n            E[mode]\n            F((message<br>to send))\n        end\n    end\n\n    A ~~~ B\n    B ~~~ C\n    C ~~~ D\n    D ~~~ E\n    E ~~~ F\n\n```\n\nVerification in FunC:\n\n```func\nslice signature = in_msg_body~load_bits(512);\nslice signed_data = in_msg_body;  // Remaining data\n\nint hash = slice_hash(signed_data);  // 526 gas\nthrow_unless(35, check_signature(hash, signature, public_key));\n```\n\nGas analysis:\n\nAfter loading the signature, the remaining data is a **slice**. To verify the signature, the contract needs to hash this slice. In TVM, the method for hashing a slice is `slice_hash()`, which costs `526` gas.\n\nWhy expensive?\\\n`slice_hash()` internally rebuilds a cell from the slice, copying all data and references.\n\n<Aside\n  type=\"tip\"\n  title=\"Optimization available\"\n>\n  Recent TVM versions support `builder_hash()` for efficient hashing. Convert the slice to a builder and hash it — this costs less than 100 gas total. See [Optimization: Builder hashing](#optimization-builder-hashing) below for details.\n</Aside>\n\n### Approach 2: Signed data as cell\n\nThe signed data is stored in a **separate cell**, placed as a reference in the message body.\n\nUsed in: Preprocessed Wallet v2, Highload Wallet v3\n\nSchema — Preprocessed Wallet v2:\n\n```tlb\n_ valid_until:uint64 seqno:uint16 actions:^Cell = MsgInner;\n\nmsg_body$_ signature:bits512 msg_inner:^MsgInner = ExternalInMessage;\n```\n\n```mermaid\ngraph LR\n    subgraph Root[\"Message body\"]\n        direction LR\n        A[**signature**]\n        B((msg_inner))\n    end\n\n    subgraph Ref[\"Signed data (next cell)\"]\n        direction LR\n        C[valid_until]\n        D[seqno]\n        E((actions))\n    end\n\n    A ~~~ B\n    B -.-> Ref\n    C ~~~ D\n    D ~~~ E\n\n```\n\nVerification in FunC:\n\n```func\nslice signature = in_msg_body~load_bits(512);\ncell signed_data = in_msg_body~load_ref();  // Signed data as cell\n\nint hash = cell_hash(signed_data);  // 26 gas\nthrow_unless(35, check_signature(hash, signature, public_key));\n```\n\nGas analysis:\n\nThe signed data is loaded as a **cell** from the reference. To get its hash, the contract uses `cell_hash()`, which costs only 26 gas.\n\nWhy efficient?\\\nEvery cell in TON stores its hash as metadata. `cell_hash()` reads this precomputed value directly — no rebuilding, no copying.\n\nTrade-off:\\\nThis approach adds one extra cell to the message, slightly increasing the forward fee. However, the gas savings (\\~500 gas) outweigh the forward fee increase.\n\n### Optimization: Builder hashing\n\nRecent TVM versions introduced efficient builder hashing (`HASHBU` instruction), which makes **signed data as slice** approach much more gas-efficient.\n\nVerification in FunC (optimized):\n\n```func\nslice signature = in_msg_body~load_bits(512);\nslice signed_data = in_msg_body;\n\nbuilder b = begin_cell().store_slice(signed_data);\nint hash = b.builder_hash();\nthrow_unless(35, check_signature(hash, signature, public_key));\n```\n\nGas comparison:\n\n| Method                  | Gas cost  | Notes                              |\n| ----------------------- | --------- | ---------------------------------- |\n| `slice_hash()`          | 526 gas   | Rebuilds cell from slice           |\n| Builder hashing (slice) | \\<100 gas | With HASHBU: cheap builder hashing |\n| `cell_hash()` (cell)    | 26 gas    | Uses precomputed cell hash         |\n\nConclusion:\\\nWith builder hashing optimization, both approaches are gas-efficient. New contracts can choose based on code simplicity and forward fee considerations.\n\nReference: [`GlobalVersions.md` — TVM improvements](https://github.com/ton-blockchain/ton/blob/5c0349110bb03dd3a241689f2ab334ae1a554ffb/doc/GlobalVersions.md#new-tvm-instructions-4)\n\n## How to sign messages in TypeScript\n\n### Prerequisites\n\n- Node.js 18+ or TypeScript environment\n- `@ton/core`, `@ton/crypto` packages installed\n\nInstall required packages:\n\n```bash\nnpm install @ton/core @ton/crypto\n```\n\n### Step 1: Generate or load a mnemonic\n\nA mnemonic is the wallet's master secret. It derives the private key used to sign messages.\n\nGenerate a new mnemonic:\n\n```typescript\nimport { mnemonicNew } from '@ton/crypto';\n\nconst mnemonic = await mnemonicNew(24); // Array of 24 words\n```\n\nLoad an existing mnemonic:\n\n```typescript\n// Read from environment; do not inline secrets\nconst mnemonic = (process.env.MNEMONIC ?? 'MNEMONIC_WORDS').split(' ');\n```\n\n<Aside\n  type=\"danger\"\n  title=\"Protect the mnemonic\"\n>\n  Anyone with access to the mnemonic can control the wallet and all funds. Store it securely (password manager, hardware wallet, encrypted storage). Never commit it to version control.\n</Aside>\n\n### Step 2: Derive the keypair\n\nConvert the mnemonic to an Ed25519 keypair:\n\n```typescript\nimport { mnemonicToPrivateKey } from '@ton/crypto';\n\nconst keyPair = await mnemonicToPrivateKey(mnemonic);\n// keyPair.publicKey  — stored in contract\n// keyPair.secretKey  — used to sign messages\n```\n\n### Step 3: Build the signed data\n\nBuild the message data that will be signed:\n\n```typescript\nimport { beginCell } from '@ton/core';\n\n// Build signed data (example: wallet message)\nconst seqno = 5;\nconst validUntil = Math.floor(Date.now() / 1000) + 60; // 60 seconds from now\n\nconst signedData = beginCell()\n    .storeUint(seqno, 32)\n    .storeUint(validUntil, 32)\n    // ... other fields (subwallet_id, actions, etc.)\n    .endCell();\n```\n\n### Step 4: Create the signature\n\nSign the hash of the signed data:\n\n```typescript\nimport { sign } from '@ton/crypto';\n\nconst signature = sign(signedData.hash(), keyPair.secretKey);\n// signature is a Buffer with 512 bits\n```\n\n### Step 5: Build the message body\n\nChoose the structure based on the contract design (see [Message structure for signing](#message-structure-for-signing) above):\n\n```typescript\n// Approach 1: Signed data as slice\nconst messageBodyInline = beginCell()\n    .storeBuffer(signature)             // 512 bits\n    .storeSlice(signedData.asSlice())   // Signed data as slice\n    .endCell();\n\n// Approach 2: Signed data as cell\nconst messageBodySeparate = beginCell()\n    .storeBuffer(signature)             // 512 bits\n    .storeRef(signedData)               // Signed data as cell\n    .endCell();\n```\n"
  },
  {
    "path": "contract-dev/testing/overview.mdx",
    "content": "---\ntitle: \"Overview\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\n\nTON Sandbox ([`@ton/sandbox`](https://github.com/ton-org/sandbox)) is a local blockchain emulator that allows you to test smart contracts from TypeScript, without deploying them to a real network, and without running a blockchain node. It provides a complete testing environment that closely mimics the behavior of the actual TON blockchain. [Blueprint](/contract-dev/blueprint/overview) project template already includes the `@ton/sandbox` dependency.\n\nThe companion `@ton/test-utils` helper library provides [matchers](https://jestjs.io/docs/using-matchers) for writing tests with Jest.\n\nThis guide covers everything you need to know about writing, running, and debugging tests for your smart contracts. For other programming languages consult documentation of corresponding [SDKs](/ecosystem/sdks).\n\n### Sandbox vs real network\n\n| Feature       | Sandbox            | Real Network                       |\n| ------------- | ------------------ | ---------------------------------- |\n| Speed         | Instant execution  | \\~5-15 second finality             |\n| Cost          | Free               | Requires real TON                  |\n| Deterministic | Yes                | No (depends on network conditions) |\n| Debugging     | Full introspection | Limited visibility                 |\n| State Control | Complete control   | Immutable history                  |\n\n### Sandbox limitations\n\nWhile Sandbox closely emulates the real network, there are some differences to be aware of:\n\n- **Time-dependent contracts**: Sandbox time is controlled, not real-time\n- **External dependencies**: Cannot interact with real external contracts, but can get their state and emulate them\n- **Blockchain imitation**: Because there is no concept of blocks in Sandbox, things like sharding do not work.\n\n## Writing tests\n\nBlueprint uses Jest as the default testing framework, providing powerful assertion capabilities and excellent TypeScript support.\n\n### Basic test setup\n\nEvery Blueprint project includes a test template. Here's the standard structure:\n\n```typescript title=\"tests/MyContract.spec.ts\" expandable\nimport { Blockchain, SandboxContract, TreasuryContract } from '@ton/sandbox';\nimport { Cell, toNano } from '@ton/core';\nimport { MyContract } from '../wrappers/MyContract';\nimport '@ton/test-utils';\nimport { compile } from '@ton/blueprint';\n\ndescribe('MyContract', () => {\n    let code: Cell;\n\n    beforeAll(async () => {\n        code = await compile('MyContract');\n    });\n\n    let blockchain: Blockchain;\n    let deployer: SandboxContract<TreasuryContract>;\n    let myContract: SandboxContract<MyContract>;\n\n    beforeEach(async () => {\n        blockchain = await Blockchain.create();\n        \n        myContract = blockchain.openContract(\n            MyContract.createFromConfig({}, code)\n        );\n        \n        deployer = await blockchain.treasury('deployer');\n        \n        const deployResult = await myContract.sendDeploy(\n            deployer.getSender(), \n            toNano('0.05')\n        );\n\n        expect(deployResult.transactions).toHaveTransaction({\n            from: deployer.address,\n            to: myContract.address,\n            deploy: true,\n            success: true,\n        });\n    });\n\n    it('should deploy', async () => {\n        // Contract is already deployed in beforeEach\n        // Add additional deployment checks here\n    });\n});\n```\n\n### Test isolation\n\nEach test should include a fresh `Blockchain` instance to ensure:\n\n**Test isolation**\n\n- No state leakage between tests\n- Predictable initial conditions\n- Independent contract deployments\n\n**Clean environment**\n\n- Fresh treasury wallets\n- Reset logical time and configuration\n- Clear transaction history\n\n```typescript\nbeforeEach(async () => {\n    // Fresh blockchain for each test\n    blockchain = await Blockchain.create();\n    \n    // Each test gets clean treasuries\n    deployer = await blockchain.treasury('deployer');\n    user = await blockchain.treasury('user');\n});\n```\n\n### Understanding transaction results\n\nWhen you send a message to a contract, you receive a `SendMessageResult` containing:\n\n```typescript\nconst result = await contract.sendIncrement(user.getSender(), toNano('0.1'));\n\n// result.transactions - Array of all transactions in the chain\n// result.events - Blockchain events emitted\n// result.externals - External messages generated\n```\n\n### Transaction matchers\n\nBlueprint provides powerful matchers for validating transactions:\n\n```typescript\nexpect(result.transactions).toHaveTransaction({\n    from: user.address,\n    to: contract.address,\n    value: toNano('1'),\n    op: 0x12345678, // Operation code\n    success: true,\n    outMessagesCount: 2, // Number of outbound messages\n    deploy: false,\n    body: beginCell()\n        .storeUint(0, 32) // Comment op\n        .storeStringTail(\"Hello, user!\")\n        .endCell()\n});\n```\n\n## Running tests\n\n```bash\n# Run all tests\nnpx blueprint test\n\n# Run specific test file\nnpx blueprint test MyContract\n\n# Run with coverage\nnpx blueprint test --coverage\n\n# Run with gas reporting  \nnpx blueprint test --gas-report\n```\n\n## Common pitfalls\n\n<Aside\n  type=\"caution\"\n>\n  **Avoid These Common Mistakes**\n\n  1. **Shared State**: Don't reuse blockchain instances between tests\n  1. **Async Issues**: Always await blockchain operations\n  1. **Time Dependencies**: Use `blockchain.now` for time-sensitive tests\n  1. **Gas Limits**: Be aware of the computation and action phase limits\n  1. **Message Ordering**: Remember that message processing is sequential\n  1. **Treasury Reuse**: Use unique seeds for different test scenarios\n</Aside>\n\n### Debugging checklist\n\nWhen tests fail, check these common issues:\n\n- ✅ Contract is properly deployed before testing\n- ✅ Treasury has sufficient balance for operations\n- ✅ Transaction matchers use correct field names\n- ✅ Exit codes match expected error conditions\n- ✅ Message bodies are correctly formatted\n- ✅ Time-sensitive operations account for blockchain time\n\n## Other resources\n\n- [Debug Guide](/contract-dev/debug) — Advanced debugging techniques\n- [TON Dev Wallet](https://github.com/TonDevWallet/TonDevWallet) — Visual debugging tool\n"
  },
  {
    "path": "contract-dev/testing/reference.mdx",
    "content": "---\ntitle: \"Reference\"\n---\n\nBlueprint provides comprehensive testing capabilities for TON smart contracts using the TON Sandbox emulator and test utilities. This reference covers all available testing APIs, methods, and utilities.\n\n## Quick Navigation\n\n**Main Sections:**\n\n- [Environment setup](#environment-setup) — installation and basic test structure\n- [Core Testing Classes](#core-testing-classes) — [`Blockchain`](#blockchain), [`Treasury`](#treasury), [`RemoteBlockchainStorage`](#remoteblockchainstorage)\n- [Type Definitions](#type-definitions) — [`SandboxContract`](#sandboxcontract), [`SendMessageResult`](#sendmessageresult), [`FlatTransaction`](#flattransaction), [`FlatTransactionComparable`](#flattransactioncomparable)\n- [Utility functions](#utility-functions) — helper functions for testing\n- [Test utilities and matchers](#test-utilities-and-matchers) — Jest/Chai assertion extensions and testing utilities\n- [Network configuration](#network-configuration) — custom blockchain configs\n\n## Environment setup\n\nBlueprint testing environment requires proper setup of the TON Sandbox and test utilities.\n\n### Installation\n\n```bash\nnpm install --save-dev @ton/sandbox @ton/test-utils\n```\n\n### Basic test structure\n\n```typescript title=\"./tests/Sample.spec.ts\" expandable\nimport { Blockchain, SandboxContract, TreasuryContract } from '@ton/sandbox';\nimport { Cell, toNano } from '@ton/core';\nimport { Sample } from '../wrappers/Sample';\nimport '@ton/test-utils';\nimport { compile } from '@ton/blueprint';\n\ndescribe('Sample', () => {\n    let code: Cell;\n\n    beforeAll(async () => {\n        code = await compile('Sample');\n    });\n\n    let blockchain: Blockchain;\n    let deployer: SandboxContract<TreasuryContract>;\n    let sample: SandboxContract<Sample>;\n\n    beforeEach(async () => {\n        blockchain = await Blockchain.create();\n\n        sample = blockchain.openContract(Sample.createFromConfig({}, code));\n\n        deployer = await blockchain.treasury('deployer');\n\n        const deployResult = await sample.sendDeploy(deployer.getSender(), toNano('0.05'));\n\n        expect(deployResult.transactions).toHaveTransaction({\n            from: deployer.address,\n            to: sample.address,\n            deploy: true,\n            success: true,\n        });\n    });\n\n    it('should deploy', async () => {\n        // the check is done inside beforeEach\n        // blockchain and sample are ready to use\n    });\n});\n```\n\n## Core Testing Classes\n\n### `Blockchain`\n\nThe main blockchain emulator class provides an isolated testing environment.\n\n```typescript\nclass Blockchain {\n    static create(opts?: {\n        executor?: IExecutor;\n        config?: BlockchainConfig;\n        storage?: BlockchainStorage;\n        meta?: ContractsMeta;\n        autoDeployLibs?: boolean;\n    }): Promise<Blockchain>\n\n    // Contract and states management\n    treasury(seed: string, params?: TreasuryParams): Promise<SandboxContract<TreasuryContract>>\n    createWallets(n: number, params?: TreasuryParams): Promise<SandboxContract<TreasuryContract>[]>\n    openContract<T extends Contract>(contract: T): SandboxContract<T>\n    provider(address: Address, init?: StateInit | null): ContractProvider\n    sender(address: Address): Sender\n    getContract(address: Address): Promise<SmartContract>\n    setShardAccount(address: Address, account: ShardAccount): Promise<void>\n    getTransactions(address: Address, opts?: { limit?: number; lt?: string | bigint; hash?: string | Buffer }): Promise<BlockchainTransaction[]>\n\n    // Core messaging methods\n    sendMessage(message: Message | Cell, params?: MessageParams): Promise<SendMessageResult>\n    sendMessageIter(message: Message | Cell, params?: SendMessageIterParams): Promise<AsyncIterator<BlockchainTransaction> & AsyncIterable<BlockchainTransaction>>\n    runGetMethod(address: Address, method: number | string, stack?: TupleItem[], params?: GetMethodParams): Promise<GetMethodResult>\n    runTickTock(on: Address | Address[], which: TickOrTock, params?: MessageParams): Promise<SendMessageResult>\n\n    // Snapshotting\n    snapshot(): BlockchainSnapshot\n    loadFrom(snapshot: BlockchainSnapshot): Promise<void>\n\n    // Coverage\n    enableCoverage(enable?: boolean): void\n    coverage(contract: Contract): Coverage | undefined\n    coverageForCell(code: Cell, address?: Address): Coverage | undefined\n\n    // Debugging\n    getDebuggerExecutor(): Promise<Executor>\n    get debug(): boolean\n    set debug(value: boolean)\n\n    // Configuration methods\n    setVerbosityForAddress(address: Address, verbosity: Partial<LogsVerbosity> | Verbosity | undefined): Promise<void>\n    setConfig(config: BlockchainConfig): void\n    randomize(): Promise<Buffer>\n\n    // Configuration properties\n    get now(): number | undefined\n    set now(now: number | undefined)\n    get lt(): bigint\n    get config(): Cell\n    get configBase64(): string\n    get verbosity(): LogsVerbosity\n    set verbosity(value: LogsVerbosity)\n    get libs(): Cell | undefined\n    set libs(value: Cell | undefined)\n    get random(): Buffer | undefined\n    set random(value: Buffer | undefined)\n    get recordStorage(): boolean\n    set recordStorage(v: boolean)\n    get autoDeployLibraries(): boolean\n    set autoDeployLibraries(value: boolean)\n    get prevBlocks(): PrevBlocksInfo | undefined\n    set prevBlocks(value: PrevBlocksInfo | undefined)\n}\n```\n\n#### `Blockchain.create()`\n\n```typescript\nstatic create(opts?: {\n    executor?: IExecutor;\n    config?: BlockchainConfig;\n    storage?: BlockchainStorage;\n    meta?: ContractsMeta;\n    autoDeployLibs?: boolean;\n}): Promise<Blockchain>\n```\n\nCreates a new blockchain instance for testing.\n\n**Parameters:**\n\n- `opts` — optional blockchain configuration\n  - `executor` — custom contract executor (default: `Executor`)\n  - `config` — blockchain configuration (`Cell`, `'default'`, or `'slim'`)\n  - `storage` — contracts storage (default: `LocalBlockchainStorage`)\n  - `meta` — optional contracts metadata provider\n  - `autoDeployLibs` — automatically collect and deploy libraries\n\n**Returns:** promise resolving to blockchain instance\n\n**Usage example:**\n\n```typescript\n// Basic blockchain\nconst blockchain = await Blockchain.create();\n\n// With slim config for faster execution\nconst blockchain = await Blockchain.create({ config: 'slim' });\n\n// With remote storage\nconst blockchain = await Blockchain.create({\n    storage: new RemoteBlockchainStorage(client)\n});\n\n// With auto-deploy libraries\nconst blockchain = await Blockchain.create({\n    autoDeployLibs: true\n});\n```\n\n#### `treasury()`\n\n```typescript\ntreasury(seed: string, params?: TreasuryParams): Promise<SandboxContract<TreasuryContract>>\n```\n\nCreates a treasury wallet contract. This wallet is used as an alternative to the wallet smart contract.\n\n**Parameters:**\n\n- `seed` — initial seed for the treasury. If the same seed is used to create a treasury, then these treasuries will be identical\n- `params` — optional treasury parameters\n  - `workchain` — the workchain ID of the treasury (default: 0)\n  - `predeploy` — if set, the treasury will be deployed at the moment of creation\n  - `balance` — initial balance of the treasury (default: 1\\_000\\_000 TON if omitted)\n  - `resetBalanceIfZero` — if set and the treasury balance is zero at the moment of calling the method, it resets the balance to `balance`\n\n**Returns:** promise resolving to treasury contract wrapper\n\n**Usage example:**\n\n```typescript\nconst deployer = await blockchain.treasury('deployer');\nconst user = await blockchain.treasury('user', { balance: toNano('100') });\n\n// Same seed creates identical treasury\nconst wallet1 = await blockchain.treasury('same-seed');\nconst wallet2 = await blockchain.treasury('same-seed');\n// wallet1.address equals wallet2.address\n```\n\n#### `createWallets()`\n\n```typescript\ncreateWallets(n: number, params?: TreasuryParams): Promise<SandboxContract<TreasuryContract>[]>\n```\n\nBulk variant of `treasury()` method.\n\n**Parameters:**\n\n- `n` — number of wallets to create\n- `params` — params for treasury creation\n\n**Returns:** array of opened treasury contracts\n\n**Usage example:**\n\n```typescript\nconst [wallet1, wallet2, wallet3] = await blockchain.createWallets(3);\n```\n\n#### `openContract()`\n\n```typescript\nopenContract<T extends Contract>(contract: T): SandboxContract<T>\n```\n\nWraps a contract for testing with additional methods and state tracking.\n\n**Parameters:**\n\n- `contract` — contract instance to wrap\n\n**Returns:** [`SandboxContract`](#sandboxcontract) wrapper with testing capabilities\n\n**Usage example:**\n\n```typescript\nconst myContract = blockchain.openContract(MyContract.createFromConfig(config, code));\n```\n\n#### `provider()`\n\n```typescript\nprovider(address: Address, init?: StateInit | null): ContractProvider\n```\n\nCreates a new `ContractProvider` for the contract address.\n\n**Parameters:**\n\n- `address` — address to create contract provider for\n- `init` — initial state of contract\n\n**Returns:** ContractProvider instance\n\n**Usage example:**\n\n```typescript\nconst contractProvider = blockchain.provider(address, init);\n```\n\n#### `sender()`\n\n```typescript\nsender(address: Address): Sender\n```\n\nCreates a Sender for the address. Note that this sender pushes internal messages to the Blockchain directly. No value is deducted from the sender address; all the values are set to defaults. Use for test purposes only.\n\n**Parameters:**\n\n- `address` — address to create sender for\n\n**Returns:** `Sender` instance\n\n**Usage example:**\n\n```typescript\nconst sender = blockchain.sender(address);\nawait contract.send(sender, ...);\n```\n\n#### `getContract()`\n\n```typescript\ngetContract(address: Address): Promise<SmartContract>\n```\n\nRetrieves `SmartContract` from `BlockchainStorage`.\n\n**Parameters:**\n\n- `address` — address of the contract to get\n\n**Returns:** a promise resolving to a `SmartContract` instance\n\n#### `setShardAccount()`\n\n```typescript\nsetShardAccount(address: Address, account: ShardAccount): Promise<void>\n```\n\nSets the account state directly for a contract address.\n\n**Parameters:**\n\n- `address` — contract `Address`\n- `account` — `ShardAccount` state to set\n\n#### `getTransactions()`\n\n```typescript\ngetTransactions(address: Address, opts?: {\n    limit?: number;\n    lt?: string | bigint;\n    hash?: string | Buffer;\n}): Promise<BlockchainTransaction[]>\n```\n\nRetrieves transactions for the specified address. Transactions are ordered from newest to oldest.\n\n**Parameters:**\n\n- `address` — the `Address` to retrieve transactions for\n- `opts` — options to fetch transactions\n  - `lt` — logical time of the transaction to start from (must be used with `hash`)\n  - `hash` — hash of the transaction to start from (must be used with `lt`)\n  - `limit` — maximum number of transactions to return\n\n**Returns:** promise resolving to an array of transactions involving the given address\n\n**Usage example:**\n\n```typescript\nconst transactions = await blockchain.getTransactions(Address.parse('...'), {\n    lt: '1234567890',\n    hash: 'abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890',\n    limit: 10\n});\n```\n\n#### `sendMessage()`\n\n```typescript\nsendMessage(message: Message | Cell, params?: MessageParams): Promise<SendMessageResult>\n```\n\nEmulates the result of sending a message to this `Blockchain`. Emulates the whole chain of transactions before returning the result. Each transaction increases lt by 1000000.\n\n**Parameters:**\n\n- `message` — message to send (`Message` object or `Cell` for external messages)\n- `params` — optional [`MessageParams`](#messageparams)\n  - `now` — override blockchain time for this message\n  - `randomSeed` — random seed for deterministic execution\n  - `ignoreChksig` — whether `CHKSIG` instructions are set to always succeed. Default: `false`\n\n**Returns:** promise resolving to [`SendMessageResult`](#sendmessageresult) containing transactions, events, and externals\n\n**Usage example:**\n\n```typescript\nconst result = await blockchain.sendMessage(internal({\n    from: sender.address,\n    to: contract.address,\n    value: toNano('1'),\n    body: beginCell().storeUint(0, 32).endCell(),\n}));\n\n// Check transactions\nexpect(result.transactions).toHaveTransaction({\n    from: sender.address,\n    to: contract.address,\n    success: true\n});\n```\n\n#### `sendMessageIter()`\n\n```typescript\nsendMessageIter(message: Message | Cell, params?: SendMessageIterParams): Promise<AsyncIterator<BlockchainTransaction> & AsyncIterable<BlockchainTransaction>>\n```\n\nStarts emulating the result of sending a message to this Blockchain. Each iterator call emulates one transaction, so the whole chain is not emulated immediately, unlike in `sendMessage`.\n\n**Parameters:**\n\n- `message` — message to send (`Message` or `Cell`)\n- `params` — optional parameters\n  - `allowParallel` — when `true`, allows many consequential executions of this method (default: `false`)\n  - other [`MessageParams`](#messageparams) (`now`, `randomSeed`, `ignoreChksig`)\n\n**Returns:** promise resolving to async iterator of [`BlockchainTransaction`](#blockchaintransaction)\n\n**Usage example:**\n\n```typescript\nconst message = internal({\n    from: sender.address,\n    to: address,\n    value: toNano('1'),\n    body: beginCell().storeUint(0, 32).endCell(),\n});\n\nfor await (const tx of await blockchain.sendMessageIter(message, { randomSeed: crypto.randomBytes(32) })) {\n    // process transaction\n    console.log(tx);\n}\n```\n\n#### `runGetMethod()`\n\n```typescript\nrunGetMethod(address: Address, method: number | string, stack?: TupleItem[], params?: GetMethodParams): Promise<GetMethodResult>\n```\n\nRuns a get method on the contract.\n\n**Parameters:**\n\n- `address` — contract `Address`\n- `method` — method ID (number) or method name (string) to run\n- `stack` — method parameters as `TupleItem` array\n- `params` — optional [`GetMethodParams`](#getmethodparams)\n  - `now` — override blockchain time for this call\n  - `randomSeed` — random seed for deterministic execution\n  - `gasLimit` — overrides TVM emulator `gas_limit`, defaults to 10\\_000\\_000\n\n**Returns:** promise resolving to [`GetMethodResult`](#getmethodresult) with stackReader and other execution details\n\n**Usage example:**\n\n```typescript\nconst { stackReader } = await blockchain.runGetMethod(address, 'get_now', [], {\n    now: 2,\n});\nconst now = stackReader.readNumber();\n\n// With method ID\nconst result = await blockchain.runGetMethod(address, 123, []);\n```\n\n#### `runTickTock()`\n\n```typescript\nrunTickTock(on: Address | Address[], which: TickOrTock, params?: MessageParams): Promise<SendMessageResult>\n```\n\nRuns tick or tock transaction.\n\n**Parameters:**\n\n- `on` — `Address` or `Address` array to run tick-tock\n- `which` — type of transaction (`'tick'` or `'tock'`)\n- `params` — [`MessageParams`](#messageparams) (`now`, `randomSeed`, `ignoreChksig`)\n\n**Returns:** promise resolving to [`SendMessageResult`](#sendmessageresult)\n\n**Usage example:**\n\n```typescript\nlet res = await blockchain.runTickTock(address, 'tock');\n```\n\n#### `snapshot()`\n\n```typescript\nsnapshot(): BlockchainSnapshot\n```\n\nSaves a snapshot of the current blockchain.\n\n**Returns:** [`BlockchainSnapshot`](#blockchainsnapshot) object\n\n**Usage example:**\n\n```typescript\nconst snapshot = blockchain.snapshot();\n// some operations\nawait blockchain.loadFrom(snapshot); // restores blockchain state\n```\n\n#### `loadFrom()`\n\n```typescript\nloadFrom(snapshot: BlockchainSnapshot): Promise<void>\n```\n\nRestores blockchain state from the snapshot.\n\n**Parameters:**\n\n- `snapshot` — [`BlockchainSnapshot`](#blockchainsnapshot) to restore from\n\n**Usage example:**\n\n```typescript\nconst snapshot = blockchain.snapshot();\n// ... perform operations\nawait blockchain.loadFrom(snapshot);\n```\n\n#### `enableCoverage()`\n\n```typescript\nenableCoverage(enable?: boolean): void\n```\n\nEnable coverage collection.\n\n**Parameters:**\n\n- `enable` — if `false`, disable coverage collection (default: `true`)\n\n**Usage example:**\n\n```typescript\nblockchain.enableCoverage();\n// ... execute contract methods\nconst coverage = blockchain.coverage(contract);\n```\n\n#### `coverage()`\n\n```typescript\ncoverage(contract: Contract): Coverage | undefined\n```\n\nReturns coverage analysis for the specified contract. Coverage is collected at the TVM assembly instruction level from all executed transactions and get method calls.\n\n**Parameters:**\n\n- `contract` — contract to analyze coverage for\n\n**Returns:** [`Coverage`](#coverage) object with detailed coverage data or undefined\n\n**Throws:** `Error` if the contract has no code or if verbose VM logs are not enabled\n\n**Usage example:**\n\n```typescript\nblockchain.enableCoverage();\nawait contract.send(sender, { value: toNano('1') }, 'increment');\n\nconst coverage = blockchain.coverage(contract);\nconst summary = coverage?.summary();\nconsole.log(`Coverage: ${summary?.coveragePercentage?.toFixed(2)}%`);\n\nconst htmlReport = coverage?.report(\"html\");\nawait fs.writeFile(\"coverage.html\", htmlReport);\n```\n\n#### `coverageForCell()`\n\n```typescript\ncoverageForCell(code: Cell, address?: Address): Coverage | undefined\n```\n\nReturns coverage analysis for the specified code cell. This method allows analyzing coverage for code cells directly, with optional address filtering.\n\n**Parameters:**\n\n- `code` — Cell containing contract code to analyze\n- `address` — optional contract address to filter transactions by\n\n**Returns:** [`Coverage`](#coverage) object with detailed coverage data\n\n**Usage example:**\n\n```typescript\nblockchain.enableCoverage();\nconst coverage = blockchain.coverageForCell(codeCell, contractAddress);\nconst allCoverage = blockchain.coverageForCell(codeCell); // Without address filtering\n```\n\n#### `getDebuggerExecutor()`\n\n```typescript\ngetDebuggerExecutor(): Promise<Executor>\n```\n\nGets the debugger executor instance for debugging purposes.\n\n**Returns:** promise resolving to Executor instance for debugging\n\n**Usage example:**\n\n```typescript\nconst debugExecutor = await blockchain.getDebuggerExecutor();\n// Use debugExecutor for debugging operations\n```\n\n#### `debug`\n\n```typescript\nget debug(): boolean\nset debug(value: boolean)\n```\n\nGets or sets debug mode for the blockchain.\n\n#### `setVerbosityForAddress()`\n\n```typescript\nsetVerbosityForAddress(address: Address, verbosity: Partial<LogsVerbosity> | Verbosity | undefined): Promise<void>\n```\n\nUpdate the logs' verbosity level for the address.\n\n**Parameters:**\n\n- `address` — contract `Address`\n- `verbosity` — [`LogsVerbosity`](#logsverbosity) configuration or undefined to reset\n\n**Usage example:**\n\n```typescript\nawait blockchain.setVerbosityForAddress(contract.address, {\n    blockchainLogs: true,\n    vmLogs: 'vm_logs_full'\n});\n```\n\n#### `setConfig()`\n\n```typescript\nsetConfig(config: BlockchainConfig): void\n```\n\nUpdates blockchain config.\n\n**Parameters:**\n\n- `config` — custom config in `Cell` format, or predefined `'default'` | `'slim'`\n\n**Usage example:**\n\n```typescript\nblockchain.setConfig('slim'); // Use slim config for faster execution\nblockchain.setConfig(customConfigCell); // Use custom config\n```\n\n#### `randomize()`\n\n```typescript\nrandomize(): Promise<Buffer>\n```\n\nGenerates and sets a new random seed using secure random bytes.\n\n**Returns:** promise resolving to the generated random seed `Buffer`\n\n**Usage example:**\n\n```typescript\nconst newSeed = await blockchain.randomize();\n```\n\n#### `now`\n\n```typescript\nget now(): number | undefined\nset now(now: number | undefined)\n```\n\nGets or sets the current time in the blockchain (UNIX timestamp).\n\n**Usage example:**\n\n```typescript\n// Get current time\nconst currentTime = blockchain.now;\n\n// Set blockchain time\nblockchain.now = Math.floor(Date.now() / 1000);\n\n// Clear time (use system time)\nblockchain.now = undefined;\n```\n\n#### `lt`\n\n```typescript\nget lt(): bigint\n```\n\nGets the current logical time in the blockchain.\n\n**Returns:** current logical time as `bigint`\n\n#### `config`\n\n```typescript\nget config(): Cell\n```\n\nGets the configuration used in the blockchain.\n\n**Returns:** configuration as `Cell`\n\n#### `configBase64`\n\n```typescript\nget configBase64(): string\n```\n\nGets the configuration used in the blockchain in base64 format.\n\n**Returns:** configuration as base64 string\n\n#### `verbosity`\n\n```typescript\nget verbosity(): LogsVerbosity\nset verbosity(value: LogsVerbosity)\n```\n\nGets or sets the logs verbosity level.\n\n**Usage example:**\n\n```typescript\n// Get current verbosity\nconst currentVerbosity = blockchain.verbosity;\n\n// Set verbosity\nblockchain.verbosity = {\n    print: true,\n    blockchainLogs: true,\n    vmLogs: 'vm_logs_full',\n    debugLogs: true\n};\n```\n\n#### `libs`\n\n```typescript\nget libs(): Cell | undefined\nset libs(value: Cell | undefined)\n```\n\nGets or sets the global blockchain libraries.\n\n**Usage example:**\n\n```typescript\n// Get current libs\nconst currentLibs = blockchain.libs;\n\n// Set libraries\nconst libsDict = Dictionary.empty(Dictionary.Keys.Buffer(32), Dictionary.Values.Cell());\nlibsDict.set(libCell.hash(), libCell);\nblockchain.libs = beginCell().storeDictDirect(libsDict).endCell();\n```\n\n#### `random`\n\n```typescript\nget random(): Buffer | undefined\nset random(value: Buffer | undefined)\n```\n\nGets or sets the random seed.\n\n**Usage example:**\n\n```typescript\n// Get current random seed\nconst currentSeed = blockchain.random;\n\n// Set random seed\nblockchain.random = crypto.randomBytes(32);\n```\n\n#### `recordStorage`\n\n```typescript\nget recordStorage(): boolean\nset recordStorage(v: boolean)\n```\n\nIf set to `true`, `BlockchainTransaction` will have `oldStorage` and `newStorage` fields. Note that enabling this flag will disable a certain optimization, which will slow down contract emulation.\n\n#### `autoDeployLibraries`\n\n```typescript\nget autoDeployLibraries(): boolean\nset autoDeployLibraries(value: boolean)\n```\n\nGets or sets whether libraries should be automatically deployed.\n\n#### `prevBlocks`\n\n```typescript\nget prevBlocks(): PrevBlocksInfo | undefined\nset prevBlocks(value: PrevBlocksInfo | undefined)\n```\n\nGets or sets the `PrevBlocksInfo` for the blockchain.\n\n### `Treasury`\n\nA test treasury wallet for sending transactions and managing test funds. Treasury is created by `blockchain.treasury()` and provides a convenient wallet interface for testing.\n\n```typescript\nclass TreasuryContract implements Contract {\n    static readonly code: Cell;\n    static create(workchain: number, subwalletId: bigint): TreasuryContract;\n    readonly address: Address;\n    readonly init: StateInit;\n    readonly subwalletId: bigint;\n    constructor(workchain: number, subwalletId: bigint);\n    sendMessages(provider: ContractProvider, messages: MessageRelaxed[], sendMode?: SendMode): Promise<void>;\n    send(provider: ContractProvider, args: SenderArguments): Promise<void>;\n    getSender(provider: ContractProvider): Treasury;\n    getBalance(provider: ContractProvider): Promise<bigint>;\n    createTransfer(args: {\n        messages: MessageRelaxed[];\n        sendMode?: SendMode;\n    }): Cell;\n}\n\ntype Treasury = SandboxContract<TreasuryContract>\n```\n\n#### `code`\n\n```typescript\nstatic readonly code: Cell\n```\n\nStatic property containing the compiled treasury contract code.\n\n**Returns:** Cell with treasury contract bytecode\n\n#### `create()`\n\n```typescript\nstatic create(workchain: number, subwalletId: bigint): TreasuryContract\n```\n\nCreates a new treasury contract instance.\n\n**Parameters:**\n\n- `workchain` — workchain ID (typically 0)\n- `subwalletId` — unique subwallet identifier\n\n**Returns:** new TreasuryContract instance\n\n#### `address`\n\n```typescript\nreadonly address: Address\n```\n\nThe address of the treasury contract.\n\n**Returns:** `Address` of the treasury\n\n#### `init`\n\n```typescript\nreadonly init: StateInit\n```\n\nThe initial state of the treasury contract.\n\n**Returns:** [`StateInit`](/foundations/messages/deploy) for contract deployment\n\n#### `subwalletId`\n\n```typescript\nreadonly subwalletId: bigint\n```\n\nUnique subwallet identifier generated from the treasury seed using SHA-256.\n\n**Returns:** `bigint` subwallet ID\n\n#### `sendMessages()`\n\n```typescript\nsendMessages(provider: ContractProvider, messages: MessageRelaxed[], sendMode?: SendMode): Promise<void>\n```\n\nSends multiple messages via the treasury contract.\n\n**Parameters:**\n\n- `provider` — `ContractProvider`\n- `messages` — array of `MessageRelaxed` to send\n- `sendMode` — optional `SendMode` (default: pay gas fees separately)\n\n#### `send()`\n\n```typescript\nsend(provider: ContractProvider, args: SenderArguments): Promise<void>\n```\n\nSends a single message via the treasury contract.\n\n**Parameters:**\n\n- `provider` — `ContractProvider`\n- `args` — `SenderArguments` including value, body, and [send mode](/foundations/messages/modes)\n\n#### `getSender()`\n\n```typescript\ngetSender(): Sender\n```\n\nReturns a sender interface for this treasury that automatically handles sending transactions.\n\n**Returns:** `Sender` object for transaction signing\n\n**Usage example:**\n\n```typescript\nconst deployer = await blockchain.treasury('deployer');\nconst sender = deployer.getSender();\n\n// Sender automatically handles seqno and signing\nawait contract.sendDeploy(sender, toNano('0.05'));\n```\n\n#### `getBalance()`\n\n```typescript\ngetBalance(provider: ContractProvider): Promise<bigint>\n```\n\nReturns the current TON balance of the treasury.\n\n**Parameters:**\n\n- `provider` — `ContractProvider`\n\n**Returns:** promise resolving to balance in nanoTON\n\n**Usage example:**\n\n```typescript\nconst treasury = await blockchain.treasury('user');\nconst balance = await treasury.getBalance();\nconsole.log(`Treasury balance: ${balance} nanoTON`);\n```\n\n#### `createTransfer()`\n\n```typescript\ncreateTransfer(args: {\n    messages: MessageRelaxed[];\n    sendMode?: SendMode;\n}): Cell\n```\n\nCreates a transfer message cell for sending multiple messages via the treasury.\n\n**Parameters:**\n\n- `args` — transfer arguments\n  - `messages` — array of `MessageRelaxed` to include in transfer\n  - `sendMode` — optional `SendMode` (default: pay gas fees separately)\n\n**Returns:** `Cell` containing the transfer message body\n\n#### Treasury usage\n\nTreasury contracts are pre-funded wallets that work like regular wallet contracts:\n\n**Usage example:**\n\n```typescript\n// Create treasury with default 1M TON balance\nconst treasury = await blockchain.treasury('user');\n\n// Create treasury with custom balance\nconst richTreasury = await blockchain.treasury('rich', {\n    balance: toNano(10_000_000n)\n});\n\n// Use treasury sender for transactions\nawait contract.sendMessage(treasury.getSender(), toNano('1'), messageBody);\n\n// Treasury handles all operations automatically\n```\n\n### `RemoteBlockchainStorage`\n\nStorage implementation that fetches contract states from a real TON network.\n\n```typescript\nclass RemoteBlockchainStorage implements BlockchainStorage {\n    constructor(client: TonClient4Wrapper, blockSeqno?: number)\n}\n```\n\n**Parameters:**\n\n- `client` — wrapped TON client for network access\n- `blockSeqno` — optional block number to fetch state from\n\n**Usage example:**\n\n```typescript\nimport { TonClient4 } from '@ton/ton';\nimport { RemoteBlockchainStorage, wrapTonClient4ForRemote } from '@ton/sandbox';\n\nconst blockchain = await Blockchain.create({\n    storage: new RemoteBlockchainStorage(\n        wrapTonClient4ForRemote(\n            new TonClient4({\n                endpoint: 'https://mainnet-v4.tonhubapi.com'\n            })\n        )\n    )\n});\n```\n\n## Type Definitions\n\n### `SandboxContract`\n\nEnhanced contract wrapper that transforms contract methods for sandbox testing. SandboxContract automatically wraps `get` methods and `send` methods to work with the sandbox environment.\n\n```typescript\nexport type SandboxContract<F> = {\n    [P in keyof F]: P extends `${'get' | 'is'}${string}`\n        ? F[P] extends (x: infer CP, ...args: infer P) => infer R\n            ? ExtendsContractProvider<CP> extends true\n                ? (...args: P) => R\n                : never\n            : never\n        : P extends `send${string}`\n            ? F[P] extends (x: infer CP, ...args: infer P) => infer R\n                ? ExtendsContractProvider<CP> extends true\n                    ? (...args: P) => Promise<SendMessageResult & {\n                        result: R extends Promise<infer PR> ? PR : R;\n                    }>\n                    : never\n                : never\n            : F[P];\n};\n```\n\n**Key transformations:**\n\n- **Get methods** (`get*`) — Remove the ContractProvider parameter, return the same result\n- **Send methods** (`send*`) — Remove ContractProvider parameter, return `Promise<SendMessageResult & { result: R }>`\n- **Other properties** — Remain unchanged\n\n**Usage example:**\n\n```typescript\n// Open a contract in sandbox\nconst myContract = blockchain.openContract(MyContract.createFromConfig(config, code));\n\n// Deploy the contract - returns SendMessageResult\nconst deployResult = await myContract.sendDeploy(deployer.getSender(), toNano('0.05'));\nexpect(deployResult.transactions).toHaveTransaction({\n    from: deployer.address,\n    to: myContract.address,\n    success: true\n});\n\n// Send methods return SendMessageResult with transaction info\nconst incrementResult = await myContract.sendIncrement(user.getSender(), toNano('0.1'));\nexpect(incrementResult.transactions).toHaveTransaction({\n    from: user.address,\n    to: myContract.address,\n    success: true\n});\n\n// Get methods work the same as production\nconst counter = await myContract.getCounter();\nexpect(counter).toBe(1n);\n```\n\n### `SendMessageResult`\n\nResult of sending a message to the blockchain emulator.\n\n```typescript\nexport type SendMessageResult = {\n    transactions: BlockchainTransaction[];\n    events: Event[];\n    externals: ExternalOut[];\n};\n```\n\n**Properties:**\n\n- `transactions` — array of [`BlockchainTransaction`](#blockchaintransaction) objects that resulted from the message\n- `events` — array of [`Event`](#event-types) objects emitted during execution\n- `externals` — array of `ExternalOut` messages generated during execution\n\n### `BlockchainTransaction`\n\nEnhanced transaction type with additional sandbox-specific properties.\n\n```typescript\nexport type BlockchainTransaction = SmartContractTransaction & {\n    events: Event[];\n    parent?: BlockchainTransaction;\n    children: BlockchainTransaction[];\n    externals: ExternalOut[];\n    mode?: number;\n};\n```\n\n**Properties:**\n\n- `events` — [`Event`](#event-types) objects emitted during transaction execution\n- `parent` — parent [`BlockchainTransaction`](#blockchaintransaction) that triggered this one\n- `children` — child [`BlockchainTransaction`](#blockchaintransaction) objects triggered by this transaction\n- `externals` — `ExternalOut` messages generated during execution\n- `mode` — transaction execution mode\n\n### `MessageParams`\n\nOptional parameters for message sending operations.\n\n```typescript\nexport type MessageParams = Partial<{\n    now: number;\n    randomSeed: Buffer;\n    ignoreChksig: boolean;\n}>;\n```\n\n**Properties:**\n\n- `now` — override blockchain time for this message (UNIX timestamp)\n- `randomSeed` — random seed for deterministic execution\n- `ignoreChksig` — whether `CHKSIG` instructions are set to always succeed\n\n### `GetMethodParams`\n\nOptional parameters for a get method execution.\n\n```typescript\nexport type GetMethodParams = Partial<{\n    now: number;\n    randomSeed: Buffer;\n    gasLimit: bigint;\n}>;\n```\n\n**Properties:**\n\n- `now` — override blockchain time for this call (UNIX timestamp)\n- `randomSeed` — random seed for deterministic execution\n- `gasLimit` — override TVM emulator gas limit (default: 10,000,000)\n\n### `GetMethodResult`\n\nResult of executing a get method on a contract.\n\n```typescript\nexport type GetMethodResult = {\n    stack: TupleItem[];\n    stackReader: TupleReader;\n    exitCode: number;\n    gasUsed: bigint;\n    blockchainLogs: string;\n    vmLogs: string;\n    debugLogs: string;\n};\n```\n\n**Properties:**\n\n- `stack` — raw `TupleItem` array returned by the method\n- `stackReader` — convenient `TupleReader` for parsing stack items\n- `exitCode` — TVM exit code (0 for success, see [ExitCodes](#exitcodes))\n- `gasUsed` — amount of gas consumed during execution\n- `blockchainLogs` — blockchain-level execution logs\n- `vmLogs` — TVM execution logs\n- `debugLogs` — debug-level execution logs\n\n### `Verbosity`\n\nVerbosity levels for TVM execution logging.\n\n```typescript\nexport type Verbosity = 'none' | 'vm_logs' | 'vm_logs_location' | 'vm_logs_gas' | 'vm_logs_full' | 'vm_logs_verbose';\n```\n\n**Values:**\n\n- `'none'` — no VM logs\n- `'vm_logs'` — basic VM execution logs\n- `'vm_logs_location'` — VM logs with code location information\n- `'vm_logs_gas'` — VM logs with gas consumption details\n- `'vm_logs_full'` — comprehensive VM logs\n- `'vm_logs_verbose'` — maximum verbosity VM logs\n\n### `LogsVerbosity`\n\nConfiguration for different types of logging output.\n\n```typescript\nexport type LogsVerbosity = {\n    print: boolean;\n    blockchainLogs: boolean;\n    vmLogs: Verbosity;\n    debugLogs: boolean;\n};\n```\n\n**Properties:**\n\n- `print` — enable console output\n- `blockchainLogs` — enable blockchain-level logs\n- `vmLogs` — TVM execution [`Verbosity`](#verbosity) level\n- `debugLogs` — enable debug-level logs\n\n### `SmartContractTransaction`\n\nEnhanced transaction type with execution logs and storage information.\n\n```typescript\nexport type SmartContractTransaction = Transaction & {\n    blockchainLogs: string;\n    vmLogs: string;\n    debugLogs: string;\n    oldStorage?: Cell;\n    newStorage?: Cell;\n    outActions?: OutAction[];\n};\n```\n\n**Properties:**\n\n- `blockchainLogs` — blockchain execution logs\n- `vmLogs` — TVM execution logs\n- `debugLogs` — debug execution logs\n- `oldStorage` — contract storage before transaction (if `recordStorage` enabled)\n- `newStorage` — contract storage after transaction (if `recordStorage` enabled)\n- `outActions` — output actions generated during execution\n\n### `BlockchainSnapshot`\n\nSnapshot of blockchain state for persistence and restoration.\n\n```typescript\nexport type BlockchainSnapshot = {\n    contracts: SmartContractSnapshot[];\n    networkConfig: string;\n    lt: bigint;\n    time?: number;\n    verbosity: LogsVerbosity;\n    libs?: Cell;\n    nextCreateWalletIndex: number;\n    prevBlocksInfo?: PrevBlocksInfo;\n    randomSeed?: Buffer;\n    autoDeployLibs: boolean;\n    transactions: BlockchainTransaction[];\n};\n```\n\n**Properties:**\n\n- `contracts` — snapshots of all contract states\n- `networkConfig` — blockchain configuration\n- `lt` — current logical time\n- `time` — current blockchain time\n- `verbosity` — logging configuration\n- `libs` — shared libraries\n- `nextCreateWalletIndex` — next treasury wallet index\n- `prevBlocksInfo` — previous blocks information\n- `randomSeed` — random seed for execution\n- `autoDeployLibs` — auto-deploy libraries flag\n- `transactions` — transaction history\n\n### `GetMethodResultSuccess`\n\nSuccessful get method execution result from the remote API.\n\n```typescript\nexport type GetMethodResultSuccess = {\n    success: true;\n    stack: string;\n    gas_used: string;\n    vm_exit_code: number;\n    vm_log: string;\n    missing_library: string | null;\n};\n```\n\n**Properties:**\n\n- `success` — always true for successful results\n- `stack` — serialized result stack\n- `gas_used` — gas consumption as string\n- `vm_exit_code` — TVM exit code\n- `vm_log` — TVM execution log\n- `missing_library` — missing library hash if any\n\n### `GetMethodResultError`\n\nA failed get method execution result from the remote API.\n\n```typescript\nexport type GetMethodResultError = {\n    success: false;\n    error: string;\n};\n```\n\n**Properties:**\n\n- `success` — always false for error results\n- `error` — error description\n\n### `Event` Types\n\nBlockchain events that were emitted during transaction execution.\n\n```typescript\nexport type EventAccountCreated = {\n    type: 'account_created';\n    account: Address;\n};\n\nexport type EventAccountDestroyed = {\n    type: 'account_destroyed';\n    account: Address;\n};\n\nexport type EventMessageSent = {\n    type: 'message_sent';\n    from: Address;\n    to: Address;\n    value: bigint;\n    body: Cell;\n    bounced: boolean;\n};\n\nexport type Event = EventAccountCreated | EventAccountDestroyed | EventMessageSent;\n```\n\n**Event Types:**\n\n- `EventAccountCreated` — account was created during execution\n- `EventAccountDestroyed` — account was destroyed during execution\n- `EventMessageSent` — message was sent during execution\n\n### `BlockId`\n\nAn identifier for a blockchain block.\n\n```typescript\nexport type BlockId = {\n    workchain: number;\n    shard: bigint;\n    seqno: number;\n    rootHash: Buffer;\n    fileHash: Buffer;\n};\n```\n\n**Properties:**\n\n- `workchain` — workchain number\n- `shard` — shard identifier\n- `seqno` — sequence number\n- `rootHash` — block root hash\n- `fileHash` — block file hash\n\n### `PrevBlocksInfo`\n\nInformation about previous blocks in the blockchain.\n\n```typescript\nexport type PrevBlocksInfo = {\n    lastMcBlocks: BlockId[];\n    prevKeyBlock: BlockId;\n    lastMcBlocks100?: BlockId[];\n};\n```\n\n**Properties:**\n\n- `lastMcBlocks` — last masterchain blocks\n- `prevKeyBlock` — previous key block\n- `lastMcBlocks100` — last 100 masterchain blocks (optional)\n\n### `SerializableSnapshot`\n\nJSON-serializable format for blockchain snapshots.\n\n```typescript\nexport type SerializableSnapshot = {\n    contracts: {\n        address: string;\n        account: string;\n        lastTxTime: number;\n        verbosity?: Partial<LogsVerbosity>;\n    }[];\n    networkConfig: string;\n    lt: string;\n    time?: number;\n    verbosity: LogsVerbosity;\n    libs?: string;\n    nextCreateWalletIndex: number;\n    prevBlocksInfo?: {\n        lastMcBlocks: SerializableBlockId[];\n        prevKeyBlock: SerializableBlockId;\n        lastMcBlocks100?: SerializableBlockId[];\n    };\n    randomSeed?: string;\n    autoDeployLibs: boolean;\n    transactions: {\n        transaction: string;\n        blockchainLogs: string;\n        vmLogs: string;\n        debugLogs: string;\n        oldStorage?: string;\n        newStorage?: string;\n        outActions?: string;\n        externals: string[];\n        mode?: number;\n        parentHash?: string;\n        childrenHashes: string[];\n    }[];\n};\n```\n\n### `ExtraCurrency`\n\nType for extra currencies in transactions.\n\n```typescript\nexport type ExtraCurrency = {\n    [key: number]: bigint;\n};\n```\n\n**Properties:**\n\n- `[key: number]` — currency ID mapped to amount in basic units\n\n## Utility functions\n\n### `loadConfig()`\n\nLoads and parses blockchain configuration from Cell or base64 string.\n\n```typescript\nexport function loadConfig(configCellOrBase64: string | Cell): BlockchainConfig;\n```\n\n**Parameters:**\n\n- `configCellOrBase64` — configuration as `Cell` or base64 string\n\n**Returns:** parsed `BlockchainConfig` object\n\n### `updateConfig()`\n\nUpdates blockchain configuration with new parameters.\n\n```typescript\nexport function updateConfig(config: Cell, ...params: ConfigParam[]): Cell;\n```\n\n**Parameters:**\n\n- `config` — existing configuration `Cell`\n- `...params` — `ConfigParam` array to update\n\n**Returns:** updated configuration `Cell`\n\n### `prettyLogTransaction()`\n\nCreates a formatted log string for a transaction.\n\n```typescript\nexport function prettyLogTransaction(tx: Transaction, mapFunc?: AddressMapFunc): string;\n```\n\n**Parameters:**\n\n- `tx` — `Transaction` to create a log string for\n- `mapFunc` — optional `AddressMapFunc` to map addresses to human-readable strings\n\n**Returns:** formatted transaction log string\n\n### `prettyLogTransactions()`\n\nLogs multiple transactions to the console using formatted output.\n\n```typescript\nexport function prettyLogTransactions(txs: Transaction[], mapFunc?: AddressMapFunc): void;\n```\n\n**Parameters:**\n\n- `txs` — `Transaction` array to log\n- `mapFunc` — optional `AddressMapFunc` to map addresses to a human-readable format\n\n**Example Output:**\n\n```\nnull  ➡️  EQBGhqLAZseEqRXz4ByFPTGV7SVMlI4hrbs-Sps_Xzx01x8G\n      ➡️  0.05 💎 EQC2VluVfpj2FoHNMAiDMpcMzwvjLZxxTG8ecq477RE3NvVt\n```\n\n### `internal()` (Utility Function)\n\nCreates an internal message from parameters. This is a utility function used internally and in message builders.\n\n```typescript\nexport function internal(params: {\n    from: Address;\n    to: Address;\n    value: bigint;\n    body?: Cell;\n    stateInit?: StateInit;\n    bounce?: boolean;\n    bounced?: boolean;\n    ihrDisabled?: boolean;\n    ihrFee?: bigint;\n    forwardFee?: bigint;\n    createdAt?: number;\n    createdLt?: bigint;\n    ec?: Dictionary<number, bigint> | [number, bigint][] | ExtraCurrency;\n}): Message;\n```\n\n**Parameters:**\n\n- `from` — sender `Address`\n- `to` — recipient `Address`\n- `value` — message value in nanoTON\n- `body` — optional message body `Cell`\n- `stateInit` — optional [`StateInit`](/foundations/messages/deploy) for contract deployment\n- `bounce` — bounce flag (default: true for bounceable messages)\n- `bounced` — indicates if this is a bounced message (default: false)\n- `ihrDisabled` — disable Instant Hypercube Routing (default: true)\n- `ihrFee` — IHR fee amount\n- `forwardFee` — forward fee amount\n- `createdAt` — message creation timestamp\n- `createdLt` — logical time when message was created\n- `ec` — extra currencies `Dictionary` or [`ExtraCurrency`](#extracurrency)\n\n**Returns:** `Message` object for blockchain processing\n\n**Usage examples:**\n\n```typescript\n// Simple internal message\nconst message = internal({\n    from: sender.address,\n    to: contract.address,\n    value: toNano('1'),\n    body: beginCell().storeUint(1, 32).endCell()\n});\n\n// Message with stateInit for deployment\nconst deployMessage = internal({\n    from: deployer.address,\n    to: contract.address,\n    value: toNano('0.05'),\n    stateInit: { code, data },\n    body: beginCell().endCell()\n});\n\n// Non-bounceable message\nconst nonBounceMessage = internal({\n    from: sender.address,\n    to: wallet.address,\n    value: toNano('0.1'),\n    bounce: false\n});\n```\n\n### `printTransactionFees()`\n\nPrints transaction fees in a formatted table to the console.\n\n```typescript\nexport function printTransactionFees(transactions: Transaction[], mapFunc?: OpMapFunc): void;\n```\n\n**Parameters:**\n\n- `transactions` — list of `Transaction` to analyze and print fees for\n- `mapFunc` — optional `OpMapFunc` to map operation codes to a human-readable format\n\n**Returns:** `void` (outputs formatted table to console)\n\n### `snapshotToSerializable()`\n\n```typescript\nexport function snapshotToSerializable(snapshot: BlockchainSnapshot): SerializableSnapshot;\n```\n\n**Parameters:**\n\n- `snapshot` — [`BlockchainSnapshot`](#blockchainsnapshot) to serialize\n\n**Returns:** [`SerializableSnapshot`](#serializablesnapshot) — JSON-serializable snapshot object\n\n### `snapshotFromSerializable()`\n\n```typescript\nexport function snapshotFromSerializable(serialized: SerializableSnapshot): BlockchainSnapshot;\n```\n\n**Parameters:**\n\n- `serialized` — [`SerializableSnapshot`](#serializablesnapshot) object\n\n**Returns:** [`BlockchainSnapshot`](#blockchainsnapshot) — restored blockchain snapshot\n\n**Usage example:**\n\n```typescript\nimport { snapshotToSerializable, snapshotFromSerializable } from '@ton/sandbox';\nimport fs from 'fs';\n\n// Save snapshot to file\nconst snapshot = blockchain.snapshot();\nconst serializable = snapshotToSerializable(snapshot);\nfs.writeFileSync('snapshot.json', JSON.stringify(serializable));\n\n// Load snapshot from file\nconst loaded = JSON.parse(fs.readFileSync('snapshot.json', 'utf8'));\nconst restored = snapshotFromSerializable(loaded);\nawait blockchain.loadFrom(restored);\n```\n\n### `setGlobalVersion()`\n\nSets the global version in the blockchain configuration.\n\n```typescript\nexport function setGlobalVersion(config: Cell, version: number, capabilites?: bigint): Cell;\n```\n\n**Parameters:**\n\n- `config` — blockchain configuration `Cell`\n- `version` — global version number to set\n- `capabilites` — optional capabilities flags\n\n**Returns:** `Cell` — updated configuration Cell\n\n### `fetchConfig()`\n\nFetches blockchain configuration from TON network.\n\n```typescript\nexport async function fetchConfig(network: 'mainnet' | 'testnet', maxRetries?: number): Promise<Cell>;\n```\n\n**Parameters:**\n\n- `network` — network to fetch config from (`'mainnet'` or `'testnet'`)\n- `maxRetries` — maximum number of retry attempts (default: 5)\n\n**Returns:** `Promise<Cell>` — blockchain configuration Cell\n\n### `registerCompiledContract()`\n\nRegisters compiled contract for debugging support.\n\n```typescript\nexport function registerCompiledContract(code: Cell, debugInfo: FuncDebugInfo, marks: Cell): Cell;\n```\n\n**Parameters:**\n\n- `code` — compiled contract code `Cell`\n- `debugInfo` — `FuncDebugInfo` debug information\n- `marks` — debug marks `Cell`\n\n**Returns:** `Cell` — the same code Cell (for chaining)\n\n## Test utilities and matchers\n\nComprehensive testing utilities for TON blockchain transactions and state. Import from `@ton/test-utils` to use these utilities and matchers.\n\n```typescript\nimport '@ton/test-utils';\n```\n\n### `FlatTransaction`\n\nFlattened transaction structure for easier testing and comparison.\n\n```typescript\nexport type FlatTransaction = {\n    from?: Address;\n    to?: Address;\n    on?: Address;\n    value?: bigint;\n    ec?: [number, bigint][];\n    body?: Cell;\n    inMessageBounced?: boolean;\n    inMessageBounceable?: boolean;\n    op?: number;\n    initData?: Cell;\n    initCode?: Cell;\n    deploy: boolean;\n    lt: bigint;\n    now: number;\n    outMessagesCount: number;\n    oldStatus: AccountStatus;\n    endStatus: AccountStatus;\n    totalFees?: bigint;\n    aborted?: boolean;\n    destroyed?: boolean;\n    exitCode?: number;\n    actionResultCode?: number;\n    success?: boolean;\n    mode?: number;\n};\n```\n\n**Properties:**\n\n- `from` — sender address (if internal message)\n- `to` — recipient address\n- `on` — contract address being called\n- `value` — message value in nanoTON\n- `ec` — extra currencies as `[currencyId, amount]` pairs\n- `body` — message body cell\n- `inMessageBounced` — whether the incoming message was bounced\n- `inMessageBounceable` — whether the incoming message is bounceable\n- `op` — operation code extracted from message body\n- `initData` — contract initialization data\n- `initCode` — contract initialization code\n- `deploy` — whether this transaction deployed a contract\n- `lt` — logical time of transaction\n- `now` — timestamp of transaction\n- `outMessagesCount` — number of outbound messages\n- `oldStatus` — account status before transaction\n- `endStatus` — account status after transaction\n- `totalFees` — total fees paid for the transaction\n- `aborted` — whether the transaction was aborted\n- `destroyed` — whether the account was destroyed\n- `exitCode` — TVM exit code\n- `actionResultCode` — action phase result code\n- `success` — whether the transaction was successful\n- `mode` — transaction execution mode\n\n### `FlatTransactionComparable`\n\nPattern for matching transactions with optional fields and functions.\n\n```typescript\ntype WithFunctions<T> = {\n    [K in keyof T]: T[K] | ((x: T[K]) => boolean);\n};\n\nexport type FlatTransactionComparable = Partial<WithFunctions<FlatTransaction>>;\n```\n\nA partial [`FlatTransaction`](#flattransaction) where each field can be either:\n\n- The exact value to match\n- A function that returns `true` if the value matches the criteria\n\n**Usage examples:**\n\n```typescript\n// Exact value matching\nconst exactMatch: FlatTransactionComparable = {\n    from: deployer.address,\n    to: contract.address,\n    success: true,\n    deploy: true\n};\n\n// Function-based matching\nconst conditionalMatch: FlatTransactionComparable = {\n    value: (v) => v !== undefined && v >= toNano('0.1'), // At least 0.1 TON\n    exitCode: (code) => code === 0 || code === undefined, // Success or no code\n    totalFees: (fees) => fees !== undefined && fees < toNano('0.01') // Less than 0.01 TON fees\n};\n\n// Mixed matching\nconst mixedMatch: FlatTransactionComparable = {\n    from: user.address, // Exact match\n    success: true, // Exact match\n    value: (v) => v >= toNano('1'), // Function match\n    op: 0x12345678 // Exact match\n};\n```\n\n### `PrettyTransaction`\n\nHuman-readable transaction format for debugging and logging.\n\n```typescript\nexport type PrettyTransaction = Omit<FlatTransaction, 'from' | 'to' | 'on' | 'op' | 'failReason'> & {\n    failReason?: FailReason;\n    from?: string;\n    to?: string;\n    on?: string;\n    op?: string;\n};\n```\n\n**Properties:**\n\n- `failReason` — human-readable failure reason (if transaction failed)\n- `from` — readable sender address or name\n- `to` — readable recipient address or name\n- `on` — readable contract address or name\n- `op` — readable operation name or code\n\n### `FailReason`\n\nDescribes why a transaction failed with human-readable information.\n\n```typescript\nexport type FailReason = {\n    message: string;\n};\n```\n\n**Properties:**\n\n- `message` — human-readable failure description\n\n### `ContractsMeta`\n\nRegistry for contract metadata to enhance debugging and logging.\n\n```typescript\nexport class ContractsMeta {\n    get(key: Address): ContractMeta | undefined;\n    upsert(key: Address, value: Partial<ContractMeta>): void;\n    clear(): void;\n    delete(key: Address): void;\n}\n\nexport type ContractMeta = {\n    wrapperName?: string;\n    abi?: ContractABI | null;\n    treasurySeed?: string;\n};\n```\n\n**Methods:**\n\n- `get()` — retrieve metadata for contract address\n- `upsert()` — add or update metadata for contract address\n- `clear()` — remove all metadata\n- `delete()` — remove metadata for specific address\n\n**Usage example:**\n\n```typescript\nimport { contractsMeta } from '@ton/test-utils';\n\n// Add contract metadata for better debugging\ncontractsMeta.upsert(contract.address, {\n    wrapperName: 'MyContract',\n    abi: contractAbi,\n    treasurySeed: 'deployer'\n});\n\n// Pretty print transactions will now show readable names\nconst pretty = prettifyTransaction(transaction);\nconsole.log(pretty.to); // \"MyContract\" instead of address\n```\n\n### Jest/Chai matchers\n\nTest utils provides custom Jest/Chai matchers for testing TON blockchain transactions and data structures. These matchers are automatically available when you import `@ton/test-utils`.\n\n#### `toHaveTransaction()`\n\n```typescript\ntoHaveTransaction(cmp: FlatTransactionComparable): R\n```\n\nAsserts that a transaction array or result contains a transaction matching the specified pattern.\n\n**Parameters:**\n\n- `cmp` — [`FlatTransactionComparable`](#flattransactioncomparable) pattern with optional fields to match\n\n**Usage examples:**\n\n```typescript\n// Check deployment transaction\nexpect(result.transactions).toHaveTransaction({\n    from: deployer.address,\n    to: contract.address,\n    deploy: true,\n    success: true\n});\n\n// Check specific operation with value\nexpect(result.transactions).toHaveTransaction({\n    from: user.address,\n    to: contract.address,\n    value: toNano('1'),\n    op: 0x12345678,\n    success: true\n});\n\n// Use functions for complex matching\nexpect(result.transactions).toHaveTransaction({\n    value: (v) => v >= toNano('0.1'),\n    exitCode: (code) => code !== 0\n});\n```\n\n#### `toEqualCell()`\n\n```typescript\ntoEqualCell(cell: Cell): R\n```\n\nAsserts that a Cell equals another Cell by comparing their hash and content.\n\n**Parameters:**\n\n- `cell` — Cell to compare against\n\n**Usage example:**\n\n```typescript\nconst expectedCell = beginCell().storeUint(123, 32).endCell();\nexpect(actualCell).toEqualCell(expectedCell);\n```\n\n#### `toEqualAddress()`\n\n```typescript\ntoEqualAddress(address: Address): R\n```\n\nAsserts that an Address equals another Address.\n\n**Parameters:**\n\n- `address` — Address to compare against\n\n**Usage example:**\n\n```typescript\nexpect(contract.address).toEqualAddress(Address.parse('EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c'));\n```\n\n#### `toEqualSlice()`\n\n```typescript\ntoEqualSlice(slice: Slice): R\n```\n\nAsserts that a Slice equals another Slice by comparing their underlying Cell data.\n\n**Parameters:**\n\n- `slice` — Slice to compare against\n\n**Usage example:**\n\n```typescript\nconst expectedSlice = beginCell().storeUint(123, 32).endCell().beginParse();\nexpect(actualSlice).toEqualSlice(expectedSlice);\n```\n\n#### `toThrowExitCode()`\n\n```typescript\ntoThrowExitCode(exitCode: number): Promise<R>\n```\n\nAsserts that a function throws an error with a specific TVM exit code.\n\n**Parameters:**\n\n- `exitCode` — expected TVM exit code\n\n**Usage examples:**\n\n```typescript\n// Test that get method throws specific exit code\nawait expect(async () => {\n    await blockchain.runGetMethod(contract.address, 'fail_method');\n}).toThrowExitCode(11);\n\n// Test that send method throws exit code\nawait expect(async () => {\n    await contract.sendInvalidOperation(user.getSender(), toNano('0.1'));\n}).toThrowExitCode(134); // Invalid argument\n```\n\n### Transaction utilities\n\nUtilities for finding, filtering, and working with transactions in tests.\n\n#### `findTransaction()`\n\n```typescript\nexport function findTransaction<T extends Transaction>(txs: T | T[], match: FlatTransactionComparable): T | undefined;\n```\n\nFinds the first transaction matching the specified pattern.\n\n**Parameters:**\n\n- `txs` — single transaction or array of transactions to search\n- `match` — [`FlatTransactionComparable`](#flattransactioncomparable) pattern to match\n\n**Returns:** matching transaction or `undefined` if not found\n\n**Usage example:**\n\n```typescript\nimport { findTransaction } from '@ton/test-utils';\n\nconst deployTx = findTransaction(result.transactions, {\n    from: deployer.address,\n    to: contract.address,\n    deploy: true\n});\n\nif (deployTx) {\n    console.log('Deploy transaction found:', deployTx.lt);\n}\n```\n\n#### `findTransactionRequired()`\n\n```typescript\nexport function findTransactionRequired<T extends Transaction>(txs: T | T[], match: FlatTransactionComparable): T;\n```\n\nFinds the first transaction matching the specified pattern, throwing an error if not found.\n\n**Parameters:**\n\n- `txs` — single transaction or array of transactions to search\n- `match` — [`FlatTransactionComparable`](#flattransactioncomparable) pattern to match\n\n**Returns:** matching transaction\n\n**Throws:** `Error` if no matching transaction is found\n\n**Usage example:**\n\n```typescript\nimport { findTransactionRequired } from '@ton/test-utils';\n\nconst deployTx = findTransactionRequired(result.transactions, {\n    from: deployer.address,\n    to: contract.address,\n    deploy: true\n});\n// Guaranteed to have a transaction or throw\nconsole.log('Deploy transaction LT:', deployTx.lt);\n```\n\n#### `filterTransactions()`\n\n```typescript\nexport function filterTransactions<T extends Transaction>(txs: T[], match: FlatTransactionComparable): T[];\n```\n\nFilters the transactions array to only include transactions matching the specified pattern.\n\n**Parameters:**\n\n- `txs` — array of transactions to filter\n- `match` — [`FlatTransactionComparable`](#flattransactioncomparable) pattern to match\n\n**Returns:** array of matching transactions\n\n**Usage example:**\n\n```typescript\nimport { filterTransactions } from '@ton/test-utils';\n\nconst successfulTxs = filterTransactions(result.transactions, {\n    success: true\n});\n\nconst userTxs = filterTransactions(result.transactions, {\n    from: user.address\n});\n```\n\n### Async execution utilities\n\nUtilities for working with transaction iterators and step-by-step execution.\n\n#### `executeTill()`\n\n```typescript\nexport async function executeTill<T extends Transaction>(txs: AsyncIterator<T>, match: FlatTransactionComparable): Promise<T[]>;\n```\n\nExecutes transactions from an async iterator until finding a transaction matching the pattern.\n\n**Parameters:**\n\n- `txs` — async iterator of transactions from [`sendMessageIter()`](#sendmessageiter)\n- `match` — [`FlatTransactionComparable`](#flattransactioncomparable) pattern to match\n\n**Returns:** a `Promise` resolving to an array of executed transactions up to and including the match\n\n**Throws:** `Error` if no matching transaction is found\n\n**Usage example:**\n\n```typescript\nimport { executeTill } from '@ton/test-utils';\n\nconst message = internal({\n    from: sender.address,\n    to: contract.address,\n    value: toNano('1')\n});\n\nconst txIter = await blockchain.sendMessageIter(message);\nconst executedTxs = await executeTill(txIter, {\n    to: contract.address,\n    success: true\n});\n\nconsole.log(`Executed ${executedTxs.length} transactions until success`);\n```\n\n#### `executeFrom()`\n\n```typescript\nexport async function executeFrom<T extends Transaction>(txs: AsyncIterator<T>): Promise<T[]>;\n```\n\nExecutes all remaining transactions from an async iterator.\n\n**Parameters:**\n\n- `txs` — async iterator of transactions\n\n**Returns:** promise resolving to array of all executed transactions\n\n**Usage example:**\n\n```typescript\nimport { executeFrom } from '@ton/test-utils';\n\nconst message = internal({\n    from: sender.address,\n    to: contract.address,\n    value: toNano('1')\n});\n\nconst txIter = await blockchain.sendMessageIter(message);\nconst allTxs = await executeFrom(txIter);\n\nconsole.log(`Total executed transactions: ${allTxs.length}`);\n```\n\n### Formatting and debugging utilities\n\nUtilities for making transactions and debugging information more readable.\n\n#### `prettifyTransaction()`\n\n```typescript\nexport function prettifyTransaction(transaction: Transaction): PrettyTransaction;\n```\n\nConverts a transaction to a human-readable format for debugging and logging.\n\n**Parameters:**\n\n- `transaction` — transaction to prettify\n\n**Returns:** [`PrettyTransaction`](#prettytransaction) object with readable formatting\n\n**Usage example:**\n\n```typescript\nimport { prettifyTransaction } from '@ton/test-utils';\n\nconst pretty = prettifyTransaction(transaction);\nconsole.log('Transaction details:', pretty);\n```\n\n#### `contractsMeta`\n\nGlobal registry for contract metadata to enhance debugging and logging.\n\n```typescript\nexport const contractsMeta: ContractsMeta;\n```\n\n**Usage example:**\n\n```typescript\nimport { contractsMeta } from '@ton/test-utils';\n\n// Add contract metadata for better debugging\ncontractsMeta.upsert(contract.address, {\n    wrapperName: 'MyContract',\n    abi: contractAbi,\n    treasurySeed: 'deployer'\n});\n\n// Pretty print transactions will now show readable names\nconst pretty = prettifyTransaction(transaction);\nconsole.log(pretty.to); // \"MyContract\" instead of address\n```\n\n### Testing constants and utilities\n\n#### `ExitCodes`\n\nComprehensive collection of TVM exit codes for error testing and analysis.\n\n```typescript\nexport const ExitCodes: {\n    // Numeric codes\n    Success: 0;\n    ReservedSuccess: 1;\n    StackUnderflow: 2;\n    StackOverflow: 3;\n    IntegerOverflow: 4;\n    RangeCheckError: 5;\n    InvalidOpcode: 6;\n    TypeCheckError: 7;\n    CellOverflow: 8;\n    CellUnderflow: 9;\n    DictionaryError: 10;\n    UnknownError: 11;\n    FatalError: 12;\n    OutOfGas: 13;\n    OutOfGasNegative: -14;\n    VirtualizationError: 14;\n    InvalidActionList: 32;\n    ActionListTooLong: 33;\n    InvalidOrUnsupportedAction: 34;\n    InvalidOutboundSrcAddress: 35;\n    InvalidOutboundDestAddress: 36;\n    NotEnoughToncoin: 37;\n    NotEnoughExtraCurrencies: 38;\n    OutboundMessageTooLarge: 39;\n    CannotProcessMessage: 40;\n    NullLibraryReference: 41;\n    LibraryChangeError: 42;\n    LibraryLimitsExceeded: 43;\n    AccountStateTooLarge: 50;\n    NullReference: 128;\n    InvalidSerializationPrefix: 129;\n    InvalidIncomingMessage: 130;\n    ConstraintsError: 131;\n    AccessDenied: 132;\n    ContractStopped: 133;\n    InvalidArgument: 134;\n    ContractCodeNotFound: 135;\n    InvalidStandardAddress: 136;\n    NotBasechainAddress: 138;\n    UnrecognizedMessageOpcode: 65535;\n\n    // String mappings (reverse lookup)\n    \"0\": \"Success\";\n    \"1\": \"ReservedSuccess\";\n    // ... etc\n};\n```\n\n#### `randomAddress()`\n\n```typescript\nexport function randomAddress(workchain?: number): Address;\n```\n\nGenerates a random TON address for testing purposes.\n\n**Parameters:**\n\n- `workchain` — workchain ID (default: 0)\n\n**Returns:** randomly generated `Address`\n\n**Usage example:**\n\n```typescript\nimport { randomAddress } from '@ton/test-utils';\n\nconst testAddress = randomAddress();\nconst masterchainAddress = randomAddress(-1);\n\n// Use in tests\nexpect(contract.getOwner()).toEqualAddress(testAddress);\n```\n\n## Network configuration\n\n### Custom network configuration\n\n```typescript\nimport { loadConfig, updateConfig } from '@ton/sandbox';\n\nconst oldConfig = loadConfig(blockchain.config);\nconst updatedConfig = updateConfig(oldConfig, {\n    ...oldConfig[8],\n    anon0: {\n        ...oldConfig[8].anon0,\n        version: 99,\n    },\n});\nblockchain.setConfig(updatedConfig);\n```\n"
  },
  {
    "path": "contract-dev/upgrades.mdx",
    "content": "---\ntitle: \"Upgrading contracts\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nThe address of a contract is determined by its [initial code and state](/foundations/status). A contract can upgrade its code while preserving its address. This is useful for fixing bugs, adding features, or adapting to protocol changes without migrating to a new address.\n\nUpgrades are critical when other contracts reference the contract being upgraded. For example, [NFT items](/standard/tokens/nft/how-it-works) reference their collection contract. The collection admin cannot modify these references stored in existing NFT items. Without upgrades, fixing bugs or adding features would require deploying a new collection and migrating all items—an expensive and complex process. Upgrades solve this by allowing the collection contract to evolve in place while preserving all existing references.\n\nThe pattern is also essential for [vanity](/contract-dev/vanity) contracts and protocols such as distributed exchange (DEX) where preserving the contract address is critical.\n\n## How upgrades work\n\nTolk provides two functions for upgrades.\n\n- `contract.setCodePostponed(code: cell)` — schedules the code to be replaced during the [action phase](/foundations/phases#action-phase). The new code takes effect after the current transaction completes.\n- `contract.setData(data: cell)` — immediately replaces the contract's persistent storage. This happens during the [compute phase](/foundations/phases#compute-phase), before the transaction ends.\n\nKey difference: `setCodePostponed()` applies changes _after_ the current transaction, while `setData()` applies changes _immediately_. This means the new code won't run until the next message arrives, but the new data is already active.\n\n<Aside\n  type=\"caution\"\n  title=\"Funds at risk\"\n>\n  Contract upgrades change code behavior and can affect funds or contract state. Unauthorized upgrades can cause loss of control or funds. Restrict upgrade messages to trusted admin addresses only.\n</Aside>\n\n<Aside\n  type=\"caution\"\n  title=\"Ethics\"\n>\n  Use delayed upgrades to allow users to [react to compromised admin keys](https://blog.trailofbits.com/2025/06/25/maturing-your-smart-contracts-beyond-private-key-risk/) or [unwanted updates](https://en.wikipedia.org/wiki/Exit_scam).\n</Aside>\n\n## Basic upgrade pattern\n\nThe contract accepts upgrade messages containing new code and data. Only the admin can trigger upgrades.\n\n### How it works\n\n1. Admin sends upgrade message. The message contains new code, data, or both.\n1. Contract verifies sender. Checks that the sender is the admin address.\n1. Code is scheduled. If new code is provided, `setCodePostponed()` schedules it for replacement.\n1. Data is upgraded. If new data is provided, `setData()` immediately replaces the storage.\n1. Transaction completes. The action phase executes, applying the new code.\n1. Next message uses new code. Subsequent messages execute with the upgraded logic.\n\nThe upgrade happens immediately in a single transaction. The new code becomes active after the transaction completes. Any data replacement happens during the compute phase, so the new data is immediately available when the transaction ends.\n\nIf there's not enough Toncoin to execute action phase with the code update, but enough to execute compute phase with data update, the contract state changes will be reverted. Make sure to thoroughly test the upgrade script for possible gas issues, and provide enough Toncoin to execute the upgrade transaction completely.\n\n### Example\n\n```tolk title=\"Tolk\" expandable\nstruct (0x1111) UpgradeContract {\n    data: cell?\n    code: cell?\n}\n\ntype AllowedMessages = UpgradeContract\n\nfun onInternalMessage(in: InMessage) {\n\n    val msg = lazy AllowedMessages.fromSlice(in.body);\n\n    match (msg) {\n\n        UpgradeContract => {\n            var storage = lazy Storage.load();\n            assert (in.senderAddress == storage.adminAddress) throw 1111;\n            if (msg.code != null) {\n                contract.setCodePostponed(msg.code!);\n            }\n            if (msg.data != null) {\n                contract.setData(msg.data!);\n            }\n        }\n\n        else => {\n            // just accept TON\n        }\n    }\n}\n\nstruct Storage {\n    adminAddress: address\n}\n\nfun Storage.load() {\n    return Storage.fromCell(contract.getData());\n}\n\nfun Storage.save(self) {\n    contract.setData(self.toCell());\n}\n```\n\n## Delayed upgrades for production safety\n\nWhen upgrading protocols that are already running and have users, delayed upgrades are a best practice. This provides additional security layers: if an admin is compromised, there is time to react. Users can also see the upgrade and withdraw funds from the protocol if it has been compromised.\n\nThe pattern adds a time delay between requesting and approving an upgrade. The admin must first request an upgrade, wait for a timeout period, then approve it.\n\n### How it works\n\n1. Admin requests upgrade. Sends `RequestUpgrade` message with new code and data\n1. Contract verifies and stores. Validates admin, ensures no pending request, stores upgrade details with timestamp\n1. Timeout period. The contract enforces a waiting period before approval\n1. Admin approves upgrade. Sends `ApproveUpgrade` message after timeout expires\n1. Contract verifies timeout. Checks that enough time has passed since the request\n1. Upgrade applies. Schedules new code with `setCodePostponed()` and upgrades data with `setData()`\n1. Request cleared. Removes the pending request from storage\n\nThe admin can also send `RejectUpgrade` at any time to cancel a pending upgrade. This three-message flow (request → wait → approve or reject) gives users time to review changes and react if the admin account is compromised.\n\n### Example\n\n```tolk title=\"Tolk\" expandable\nstruct UpgradeContract {\n    data: cell?\n    code: cell?\n}\n\nstruct CurrentRequest {\n    newUpgrade: UpgradeContract\n    timestamp: uint32\n}\n\nstruct (0x00000001) RequestUpgrade {\n    newUpgrade: UpgradeContract\n}\n\nstruct (0x00000002) RejectUpgrade { }\n\nstruct (0x00000003) ApproveUpgrade { }\n\ntype AllowedMessages =\n    | RequestUpgrade\n    | RejectUpgrade\n    | ApproveUpgrade\n\nfun onInternalMessage(in: InMessage) {\n    val msg = lazy AllowedMessages.fromSlice(in.body);\n\n    match (msg) {\n\n        RequestUpgrade => {\n            var storage = lazy Storage.load();\n\n            assert (in.senderAddress == storage.adminAddress) throw 100;\n            assert (storage.CurrentRequest == null) throw 101;\n\n            storage.CurrentRequest = {\n                newUpgrade: msg.newUpgrade,\n                timestamp: blockchain.now()\n            };\n\n            storage.save();\n        }\n\n        RejectUpgrade => {\n            var storage = lazy Storage.load();\n\n            assert (in.senderAddress == storage.adminAddress) throw 100;\n            assert (storage.CurrentRequest != null) throw 201;\n\n            storage.CurrentRequest = null;\n            storage.save();\n        }\n\n        ApproveUpgrade => {\n            var storage = lazy Storage.load();\n\n            assert (in.senderAddress == storage.adminAddress) throw 100;\n            assert (storage.CurrentRequest != null) throw 301;\n            assert (storage.CurrentRequest!.timestamp + storage.timeout < blockchain.now()) throw 302;\n\n            if (storage.CurrentRequest!.newUpgrade.code != null) {\n                contract.setCodePostponed(storage.CurrentRequest!.newUpgrade.code!);\n            }\n\n            if (storage.CurrentRequest!.newUpgrade.data != null) {\n                contract.setData(storage.CurrentRequest!.newUpgrade.data!);\n            }\n            else {\n                storage.CurrentRequest = null;\n                storage.save();\n            }\n        }\n\n        else => {\n            // just accepted tons\n        }\n    }\n}\n\nget fun currentRequest() {\n    var storage = lazy Storage.load();\n    return storage.CurrentRequest;\n}\n\nstruct Storage {\n    adminAddress: address,\n    timeout: uint32,\n    CurrentRequest: CurrentRequest?\n}\n\nfun Storage.load() {\n    return Storage.fromCell(contract.getData());\n}\n\nfun Storage.save(self) {\n    contract.setData(self.toCell());\n}\n```\n\n## Hot upgrades for frequently upgraded contracts\n\nStandard upgrade methods fail when a contract receives frequent updates. For example, DEX pools that update prices every second or lending protocols that continuously adjust interest rates. The problem: it is not possible to predict what data will be in storage when the upgrade transaction executes.\n\nWhen an upgrade message with new code and data is sent, other transactions may execute before the upgrade arrives. By the time the upgrade applies, the prepared data may be stale. For a DEX pool, this can overwrite current price data with outdated values, breaking the protocol.\n\nHot upgrades solve this by scheduling a code change and immediately calling a migration function with the new code. The migration function runs in the same transaction that applies the upgrade. It reads the old storage structure, transforms it to match the new schema, and writes the upgraded storage. This preserves all state changes that happened between preparing the upgrade and executing it.\n\n### How it works\n\n1. Admin sends upgrade message. The message contains new code cell and optional additional data\n1. Contract verifies sender. Checks that the sender is the admin address\n1. Schedule code change. `setCodePostponed()` schedules the code replacement\n1. Switch to new code. `setTvmRegisterC3()` immediately activates the new code in register [C3](/tvm/registers#c3-—-function-selector)\n1. Call migration. Invoke `hotUpgradeData()` which now runs with the new code\n1. Migration executes. The function reads old storage, transforms it, and writes new storage\n\nThe key mechanism: `setTvmRegisterC3()` switches the code register so the migration function executes with the new code in the same transaction. The migration reads the current storage state (preserving all updates), transforms it to the new schema, and saves it. When the transaction completes, the new code becomes permanent through `setCodePostponed()`.\n\n<Aside\n  type=\"caution\"\n>\n  Hot upgrades require careful migration logic. Test migrations thoroughly on testnet. If the migration function fails, the contract becomes unusable. The `hotUpgradeData()` function runs only during upgrade messages, not on regular messages, preventing accidental repeated migrations.\n</Aside>\n\n### Example\n\nThe example shows a counter contract that adds a metadata field through a hot upgrade. The storage structure changes: the original version stores only `adminAddress` and `counter`. The new version adds `metadata` and reorders fields.\n\nOriginal contract:\n\n```tolk title=\"main.tolk\" expandable\nimport \"@stdlib/tvm-lowlevel\"\n\nstruct (0x00001111) HotUpgrade {\n    additionalData: cell?\n    code: cell\n}\n\nstruct (0x00002222) IncreaseCounter {}\n\ntype AllowedMessages =\n    | HotUpgrade\n    | IncreaseCounter\n\n// migration function must have method_id\n@method_id(2121)\nfun hotUpgradeData(additionalData: cell?) { return null; }\n\nfun onInternalMessage(in: InMessage) {\n\n    val msg = lazy AllowedMessages.fromSlice(in.body);\n\n    match (msg) {\n\n        HotUpgrade => {\n            var storage = lazy Storage.load();\n            assert (in.senderAddress == storage.adminAddress) throw 1111;\n\n            contract.setCodePostponed(msg.code);\n\n            setTvmRegisterC3(transformSliceToContinuation(msg.code.beginParse()));\n            hotUpgradeData(msg.additionalData);\n        }\n\n        IncreaseCounter => {\n            var storage = lazy Storage.load();\n            storage.counter += 1;\n            storage.save();\n        }\n\n        else => {\n            // just accept TON\n        }\n    }\n}\n\nget fun counter() {\n    var storage = lazy Storage.load();\n    return storage.counter;\n}\n\nstruct Storage {\n    adminAddress: address\n    counter: uint32\n}\n\nfun Storage.load() {\n    return Storage.fromCell(contract.getData());\n}\n\nfun Storage.save(self) {\n    contract.setData(self.toCell());\n}\n```\n\nThe `hotUpgradeData()` function in the original code returns `null` because it does not perform any migration. When the upgrade message arrives:\n\n1. `contract.setCodePostponed(msg.code)` schedules the new code\n1. `setTvmRegisterC3()` switches register C3 to the new code immediately\n1. `hotUpgradeData(msg.additionalData)` is called and runs with the new code\n\nNew contract with migration:\n\n```tolk title=\"new.tolk\"\nimport \"@stdlib/tvm-lowlevel\"\n\nstruct (0x00001111) HotUpgrade {\n    additionalData: cell?\n    code: cell\n}\n\nstruct (0x00002222) IncreaseCounter {}\n\ntype AllowedMessages =\n    | HotUpgrade\n    | IncreaseCounter\n\n// migration function must have method_id\n@method_id(2121)\nfun hotUpgradeData(additionalData: cell?) {\n    var oldStorage = lazy oldStorage.load();\n\n    assert (additionalData != null) throw 1112;\n\n    var storage = Storage {\n        adminAddress: oldStorage.adminAddress,\n        counter: oldStorage.counter,\n        metadata: additionalData!\n    };\n\n    contract.setData(storage.toCell());\n}\n\nstruct oldStorage {\n    adminAddress: address\n    counter: uint32\n}\n\nfun oldStorage.load() {\n    return oldStorage.fromCell(contract.getData());\n}\n\n\nfun onInternalMessage(in: InMessage) {\n\n    val msg = lazy AllowedMessages.fromSlice(in.body);\n\n    match (msg) {\n\n        HotUpgrade => {\n            var storage = lazy Storage.load();\n            assert (in.senderAddress == storage.adminAddress) throw 1111;\n\n            contract.setCodePostponed(msg.code);\n\n            setTvmRegisterC3(transformSliceToContinuation(msg.code.beginParse()));\n            hotUpgradeData(msg.additionalData);\n        }\n\n        IncreaseCounter => {\n            var storage = lazy Storage.load();\n            storage.counter += 1;\n            storage.save();\n        }\n\n        else => {\n            // just accept TON\n        }\n    }\n}\n\nget fun metadata() {\n    var storage = lazy Storage.load();\n    return storage.metadata;\n}\n\nget fun counter() {\n    var storage = lazy Storage.load();\n    return storage.counter;\n}\nstruct Storage {\n    counter: uint32\n    adminAddress: address\n    metadata: cell\n}\n\nfun Storage.load() {\n    return Storage.fromCell(contract.getData());\n}\n\nfun Storage.save(self) {\n    contract.setData(self.toCell());\n}\n```\n\nIn the new version, `hotUpgradeData()` performs the migration:\n\n1. Loads storage using the old structure (`oldStorage` with `adminAddress` and `counter`)\n1. Creates new storage with the additional `metadata` field from `additionalData`\n1. Reorders fields (`counter` moves before `adminAddress`)\n1. Writes the migrated storage immediately with `contract.setData()`\n\nThe migration runs in the same transaction as the upgrade message. Any counter increments that happened between preparing the upgrade and executing it remain in storage because the migration reads the current state, not a pre-prepared snapshot. The migration function explicitly handles the structure change by reading fields from the old layout and writing them in the new layout.\n\n### When to use hot upgrades\n\nUse hot upgrades when:\n\n- The contract receives frequent state updates (DEX pools, oracles, lending protocols)\n- Storage changes between preparing and applying the upgrade would cause data loss\n- You need to preserve all intermediate state transitions\n\nUse standard upgrades when:\n\n- The contract upgrades infrequently\n- You can predict storage state at upgrade time\n- Simpler upgrade logic reduces risk\n\n## Combining delayed and hot upgrades\n\nYou can combine delayed upgrades with hot upgrades for production protocols that require both safety and structure migration. The delayed pattern provides time for users to review changes, while the hot upgrade mechanism handles storage migration without data loss.\n\n<Aside\n  title={\"📁 Complete Example Code\"}\n>\n  You can find full working examples demonstrating all upgrade patterns in our [GitHub repository](https://github.com/ton-org/docs-examples/tree/main/contract-dev/Upgrading). This includes implementations for basic, delayed, and hot upgrade patterns.\n</Aside>\n"
  },
  {
    "path": "contract-dev/using-on-chain-libraries.mdx",
    "content": "---\ntitle: \"Using on-chain libraries\"\n---\n\nimport { Image } from '/snippets/image.jsx';\nimport { Aside } from '/snippets/aside.jsx';\n\nIt is recommended to read [Library cells](/foundations/serialization/library) first.\n\n<Aside\n  type=\"danger\"\n>\n  You should always monitor the balance of the account that hosts the library. It should be sufficient for at least 10 years.\n</Aside>\n\n### Fee savings\n\nLibrary cells help reduce fees in two main ways.\n\n1. Forwarding fees. For example, in [jettons](/standard/tokens/jettons/overview), the [`StateInit`](/foundations/messages/deploy) must be forwarded with each transfer, resulting in high forwarding fees. Moving the code into a library cell significantly reduces these fees.\n\n1. Storage costs. Because a library must be hosted in the Masterchain, where storage is approximately 1,000 times more expensive than in the Basechain, hosting a copy of the code in the Basechain may be cheaper if there are fewer than 1,000 instances of the contract. The 1,000 factor is not constant and is subject to change. Consult [blockchain config parameter 18](https://tonviewer.com/config#18) for the latest value. However, due to the savings on forwarding fees, you should calculate whether this approach is cost-effective for your specific use case.\n\nEverything in TON is stored in cells, even the account code. One of the most common use cases for libraries is to store code shared by multiple contracts.\nWhen a library cell is part of an account’s `code`, it is automatically dereferenced on first access. This allows you to replace part of the contract code—or even the entire code—with a library cell.\n\nReplacing the entire code with a library cell is widely used in TON smart contracts.\nSome common examples:\n\n1. USDT (and other popular jettons) Jetton wallet contracts\n1. The Order contract in Multisig v2\n1. NFT item contracts in popular collections\n\nYou can check if a contract is using a library as its code by looking into its `code` cell in an explorer.\n\n```txt title=\"Fragment of USDT jetton-wallet account\"\n...\ncode:(just\n      value:(raw@^Cell\n        x{}\n         SPECIAL x{028F452D7A4DFD74066B682365177259ED05734435BE76B5FD4BD5D8AF2B7C3D68}\n        ))\n...\n```\n\nWhile it is not crucial to understand the exact representation shown on the [TON Explorer](https://explorer.toncoin.org/) ([more about explorers](/ecosystem/explorers/overview)), the key point is that there is only one cell in the contract code, tagged as `SPECIAL`, indicating it is an exotic cell. Following this is the hexadecimal representation of the library cell's internals. The first byte equals 2, indicating that it is a library cell, and the remaining bytes contain the hash of the referenced cell.\n\nHere you can see that the entire contract code consists of the 8-bit tag equal to 2 and a 256-bit representation hash of the referenced cell.\n\nIf you don’t want to put the entire code in a library cell, you can make only part of it a library cell. For example, if the same function is used in multiple different contracts, it makes sense to turn it into a library. However, you will likely need to set up the build process for such code yourself.\n\n### Using @ton/core\n\nYou can construct a library cell entirely in TypeScript using the `@ton/core` library. Here’s how to do it in a Blueprint project:\n\n```ts\nimport { Cell, beginCell } from '@ton/core';\n\nconst libPrep = beginCell().storeUint(2, 8).storeBuffer(jwalletCodeRaw.hash()).endCell();\nconst jwalletCode = new Cell({ exotic: true, bits: libPrep.bits, refs: libPrep.refs });\n```\n\n- [View source](https://github.com/ton-blockchain/stablecoin-contract/blob/de08b905214eb253d27009db6a124fd1feadbf72/sandbox_tests/JettonWallet.spec.ts#L104C1-L105C90)\n\n### Publishing an ordinary cell in the Masterchain library context\n\nThe following example was taken from [multisig v2 repository](https://github.com/ton-blockchain/multisig-contract-v2/blob/master/contracts/helper/librarian.func).\n\n```func\n;; Simple library keeper\n\n#include \"../imports/stdlib.fc\";\n#include \"../messages.func\";\n\nconst int DEFAULT_DURATION = 3600 * 24 * 365 * 10; ;; 10 years, can top-up in any time\nconst int ONE_TON = 1000000000;\n\n;; https://docs.ton.org/tvm.pdf, page 138, SETLIBCODE\n() set_lib_code(cell code, int mode) impure asm \"SETLIBCODE\";\n\ncell empty_cell() asm \"<b b> PUSHREF\";\n\n() recv_internal(int msg_value, cell in_msg_full, slice in_msg_body) impure {\n    slice in_msg_full_slice = in_msg_full.begin_parse();\n    int msg_flags = in_msg_full_slice~load_msg_flags();\n    slice sender_address = in_msg_full_slice~load_msg_addr();\n\n    cell lib_to_publish = get_data();\n\n    int initial_gas = gas_consumed();\n    (int order_cells, int order_bits, _) = compute_data_size(lib_to_publish, 1000); ;; according network config, max cells in library = 1000\n    int size_counting_gas = gas_consumed() - initial_gas;\n\n    int to_reserve = get_simple_compute_fee(MASTERCHAIN, size_counting_gas) +\n                     get_storage_fee(MASTERCHAIN, DEFAULT_DURATION, order_bits, order_cells);\n    raw_reserve(to_reserve, RESERVE_BOUNCE_ON_ACTION_FAIL);\n\n    send_message_with_only_body(sender_address, 0, begin_cell(), NON_BOUNCEABLE, SEND_MODE_CARRY_ALL_BALANCE);\n    ;; https://docs.ton.org/tvm.pdf, page 138, SETLIBCODE\n    set_lib_code(lib_to_publish, 2); ;; if x = 2, the library is added as a public library (and becomes available to all smart contracts if the current smart contract resides in the masterchain);\n    ;; brick contract\n    set_code(empty_cell());\n    set_data(empty_cell());\n}\n```\n\nThe main benefit of using this contract to publish library cells is that it requires you to provide sufficient TON for at least 10 years of storage. This prevents a common problem where, after a short time, the library freezes and becomes inaccessible, which can lead to unexpected scenarios.\n\nThe core of this contract is the line: `set_lib_code(lib_to_publish, 2);`. This function call publishes an ordinary cell with the flag set to `2`, which indicates that the library is public and can be used by anyone.\n\nNote that this contract becomes bricked after the cell is published, so no further operations on this contract can be performed.\n\n### Testing in Blueprint\n\nWhen testing smart contracts locally, there are **two ways to register libraries** in your blockchain environment.\n\n#### Option 1: **Automatic Library Deployment**\n\nEnable automatic library detection by passing the `autoDeployLibs` flag when creating the blockchain:\n\n```ts\nconst blockchain = await Blockchain.create({ autoDeployLibs: true });\n```\n\nIn your contract, deployed in **Masterchain**, deploy the library using the librarian example above.\n\nThis allows the contract to dynamically install and register the library at runtime, with the environment automatically tracking and using it as needed.\n\n#### Option 2: **Manual Library Deployment**\n\nIf `autoDeployLibs` is **not enabled**, you'll need to register libraries manually:\n\n```ts\nconst blockchain = await Blockchain.create();\nconst code = await compile('Contract');\n\n// Create a dictionary of library hash → library cell\nconst libsDict = Dictionary.empty(Dictionary.Keys.Buffer(32), Dictionary.Values.Cell());\nlibsDict.set(code.hash(), code);\n\n// Manually assign the libraries\nblockchain.libs = beginCell().storeDictDirect(libsDict).endCell();\n```\n\nThis gives you full control but requires explicitly managing which libraries are available during testing.\n\nAn example implementation can be found [here](https://github.com/ton-blockchain/stablecoin-contract/blob/de08b905214eb253d27009db6a124fd1feadbf72/sandbox_tests/JettonWallet.spec.ts#L100C9-L103C32).\n\n### Get methods for library-cell-based contracts\n\nWhen working with a Jetton wallet where the code is stored in a library cell, you may need to check its balance. To do so, you must execute a get method in the code.\n\nIf you call methods using one of [HTTP APIs](/ecosystem/api/overview) or [LiteServer](/ecosystem/nodes/overview), the library cell will be automatically resolved and the method will be executed.\n\nAlternatively, take the account state to your local system and execute methods there.\nIn that case, you will need to pull the account state and resolve all library reference cells (in most cases, if the contract is using libraries, the whole code of the contract is a library reference).\nTo resolve a library, the only thing you need is to call [getLibraries method](/ecosystem/api/toncenter/v2/blocks/get-smart-contract-libraries)\n\n#### Retrieving a library cell with LiteServer\n\nTo retrieve library cells from LiteServer, use the [liteServer.getLibraries](https://github.com/ton-blockchain/ton/blob/4cfe1d1a96acf956e28e2bbc696a143489e23631/tl/generate/scheme/lite_api.tl#L96) method.\n\n```ts\nimport { LiteClient, LiteRoundRobinEngine, LiteSingleEngine } from \"ton-lite-client\";\nimport { Cell } from \"@ton/core\";\nimport { z } from \"zod\";\n\nfunction intToIP(int: number): string {\n    const buf = Buffer.alloc(4);\n    buf.writeUInt32BE(int >>> 0, 0);\n    return Array.from(buf).join(\".\");\n}\n\nconst Server = z.object({\n    ip: z.number(),\n    port: z.number(),\n    id: z.object({ key: z.string() }),\n});\n\nconst Response = z.object({\n    liteservers: z.array(Server),\n});\n\n// testnet https://ton.org/testnet-global.config.json\n// mainnet https://ton.org/global.config.json\nconst configEndpoint = \"https://ton.org/global.config.json\";\n\nasync function getServers() {\n    const data = Response.parse(await (await fetch(configEndpoint)).json());\n    return data.liteservers.map((server) => {\n        return new LiteSingleEngine({\n            host: `tcp://${intToIP(server.ip)}:${server.port}`,\n            publicKey: Buffer.from(server.id.key, 'base64'),\n        });\n    });\n}\n\nasync function getLibraryByHash(hash: Buffer) {\n    const engine = new LiteRoundRobinEngine(await getServers());\n    const client = new LiteClient({ engine });\n    const libs = await client.getLibraries([hash]);\n    const lib = libs.result[0];\n    if (!lib || libs.result.length !== 1) {\n        throw new Error(\"Library not found\");\n    }\n    const roots = Cell.fromBoc(lib.data);\n    const root = roots[0];\n    if (!root || roots.length !== 1) {\n        throw new Error(\"Malformed BoC for a library\");\n    }\n    return root.toBoc().toString(\"hex\");\n}\n\nasync function main() {\n    const hash = Buffer.from(\"8F452D7A4DFD74066B682365177259ED05734435BE76B5FD4BD5D8AF2B7C3D68\", \"hex\");\n    const code = await getLibraryByHash(hash);\n    console.log(code);\n}\n\nvoid main();\n```\n"
  },
  {
    "path": "contract-dev/vanity.mdx",
    "content": "---\ntitle: \"How to use a vanity contract\"\nsidebarTitle: \"Use a vanity contract\"\n---\n\nA [vanity contract](https://github.com/ton-community/vanity-contract) allows customization of the address of a smart contract being deployed. It does this by making its own [`StateInit`](/foundations/messages/deploy) depend on constant data that is randomly generated many times until a desired address is found. It is often used to deploy contracts with a specific prefix or suffix so the address is visible in block explorers.\n\nThe contract code and data are included in the vanity deploy message. The vanity contract is first deployed with a `StateInit` that produces the desired address (see [Addresses overview](/foundations/addresses/overview#account-id)), and then immediately sets its actual state from the payload. This is a special case of [upgrading](/contract-dev/upgrades) contract's code.\n\n## Prerequisites\n\n- OpenCL-capable GPU\n- [Python 3](https://www.python.org/downloads/)\n- [`pyopencl`](https://pypi.org/project/pyopencl/)\n- [Blueprint](/contract-dev/blueprint/overview)\n\n## How it works\n\nThe vanity contract code:\n\n```func expandable\n(int) slice_equal(slice s1, slice s2) asm \"SDEQ\";\n\n() recv_internal(cell in_msg_cell, slice in_msg) impure {\n    ;; Parse data\n    var ds = get_data().begin_parse();\n    ds~skip_bits(5); ;; Padding\n    var owner = ds~load_msg_addr();\n    ds~skip_bits(256);\n    ds.end_parse();\n\n    ;; Parse message\n    var cs = in_msg_cell.begin_parse();\n    var flags = cs~load_uint(4);  ;; int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool\n    slice sender = cs~load_msg_addr();\n\n    ;; Allow deployment only to the owner\n    throw_unless(8, slice_equal(sender, owner));\n\n    ;; Set code and data\n    var code = in_msg~load_ref();\n    var data = in_msg~load_ref();\n    in_msg.end_parse();\n    set_code(code);\n    set_data(data);\n}\n```\n\nIt checks whether the message comes from the owner specified in the data, then replaces its code and data with the ones provided in the incoming message. The `owner` field is required, because someone might intercept an external message, find `salt` in it, and concurrently deploy their own contract with this salt. Because a value of the `owner` field changes the address in an unpredictable way, an intercepted `salt` will be useless, unless attacker can send the message from the same `owner` address.\n\nThe 256-bit salt is stored in this contract's `StateInit` in addition to five padding bits and the owner address. The salt is not used by the contract's logic (it is skipped with `ds~skip_bits(256);`); it only influences the resulting address via the `StateInit` hash.\n\nBecause a contract address is derived from the `StateInit` hash, changing the salt changes the address deterministically. The search for a suitable salt happens entirely off-chain: a Python script (with an OpenCL kernel for speed) generates many random salt values, computes the resulting address, and reports matches. The on-chain vanity contract does not brute-force salts; it only verifies the owner and then sets the provided code and data when deployed.\n\n## Generate salt\n\nTo generate the salt, copy the code from [`src/generator`](https://github.com/ton-community/vanity-contract/tree/6baeb39500de0fee79bd241047699ca65ee71f55/src/generator) in the same [repository](https://github.com/ton-community/vanity-contract). It includes the `run.py` script and the `vanity.cl` OpenCL kernel.\n\nRun the command with the desired search parameters, including `-w` for the [workchain](/foundations/addresses/overview#workchain-id) and the owner address allowed to perform the deployment. The example below searches on the basechain for the specified suffix.\n\n```bash\npython3 run.py -w 0 --end '<SUFFIX>' --case-sensitive <OWNER_ADDR>\n```\n\nWhere:\n\n- `<SUFFIX>` — desired address suffix; case sensitive when `--case-sensitive` is set.\n- `<OWNER_ADDR>` — address allowed to deploy via the vanity contract.\n\nAfter running, the script prints logs and starts the search, printing every found salt. It also writes found salts to the `found.txt` file. The search continues until it is stopped or exits after the first match when `--only-one` is set. Example output:\n\n```text\nSearching wallets case-sensitive, with \"TEST\" in the end\nOwner:  UQCSQnz9h3iilIHMueOPs8RaryGqzb-bJpReZuZAUsm6TDRo\nFlags:  1100\nKernel conditions: result[44] == 'T' && result[45] == 'E' && result[46] == 'S' && result[47] == 'T'\n\nUsing device:  Apple M2 Max\nSpeed: 198 Mh/s, miss: 4, found: 0\nSpeed: 204 Mh/s, miss: 2, found: 0\nFound:  EQBas7IlwGKmd6CT7_l0PLynkUv2fmrANn2FFgcMntBATEST salt:  1045adb4ffb9af72021354a07a6f3e64ebc9822775f80b7d98beb195f57093df\nSpeed: 207 Mh/s, miss: 1, found: 1\nSpeed: 206 Mh/s, miss: 4, found: 1\nFound:  EQB1p467NtIyNpwVAF0qZYDCaXzA56mk8P6nqt6QJFeQTEST salt:  fa683a39082696af7bafecaa63f6172b615f5b7d89fea24c941d52aa3310bbc3\nSpeed: 208 Mh/s, miss: 0, found: 2\nSpeed: 205 Mh/s, miss: 2, found: 2\nSpeed: 208 Mh/s, miss: 2, found: 2\nFound:  EQBXaec9-r5Ge65hXTQopw7akH6LQr4rms9DdzkhxcUiTEST salt:  e7336b387099b3f8a31fa114ff801b799f14f3fe7f6c27c6cf0ccbb542ab743d\nSpeed: 206 Mh/s, miss: 2, found: 3\nSpeed: 203 Mh/s, miss: 2, found: 3\nSpeed: 203 Mh/s, miss: 3, found: 3\n```\n\nThe more specific the search, the rarer the matches, and the more compute is required to find one. A 4-character match typically appears in a few seconds on a laptop. TON user-friendly addresses are Base64, so each character encodes 6 bits; four characters correspond to 24 bits, i.e., about 1 in 2<sup>24</sup> trials on average. Once a salt is found, it can be used to deploy an arbitrary smart contract at that address.\n\n## Deploy the contract\n\nDeploy of the vanity contract and the message that replaces its code and data usually come in a single [message](https://github.com/ton-blockchain/ton/blob/5c0349110bb03dd3a241689f2ab334ae1a554ffb/crypto/block/block.tlb#L155):\n\n```\ninit:\n    code: vanity contract code\n    data:\n        owner: owner's address\n        salt: generated salt\nbody:\n    code: new contract's code\n    data: new contract's data\n```\n\nThis example uses [Blueprint](/contract-dev/blueprint/overview) to create and send this message. Define a vanity contract wrapper at `wrappers/VanityContract.ts`:\n\n```ts expandable\nimport { Address, beginCell, Cell, Contract, contractAddress, ContractProvider, Sender, SendMode } from '@ton/core';\n\nexport type VanityContractConfig = {\n    owner: Address;\n    salt: Buffer;\n};\n\nexport function vanityContractConfigToCell(\n    config: VanityContractConfig\n): Cell {\n    return beginCell()\n        .storeUint(0, 5)\n        .storeAddress(config.owner)\n        .storeBuffer(config.salt, 32)\n        .endCell();\n}\n\n// from https://github.com/ton-community/vanity-contract/blob/6baeb39500de0fee79bd241047699ca65ee71f55/src/contract/vanity-address.cell\nconst vanityCode = Cell.fromBoc(\n    Buffer.from(\n        'b5ee9c72010102010032000114ff00f4a413f4bcf2c80b010046d3ed44d075d721fa408307d721d102d0d30331fa403058c705f288d4d4d101fb04ed54',\n        'hex',\n    ),\n)[0];\n\nexport class VanityContract implements Contract {\n    constructor(\n        readonly address: Address,\n        readonly init?: { code: Cell; data: Cell },\n    ) {}\n\n    static createFromAddress(address: Address) {\n        return new VanityContract(address);\n    }\n\n    static createFromConfig(\n        config: VanityContractConfig, \n        workchain = 0\n    ) {\n        const data = vanityContractConfigToCell(config);\n        const init = {\n            code: vanityCode,\n            data,\n        };\n        return new VanityContract(\n            contractAddress(workchain, init),\n            init,\n        );\n    }\n\n    async sendDeploy(\n        provider: ContractProvider,\n        via: Sender,\n        value: bigint,\n        newCode: Cell,\n        newData: Cell,\n    ) {\n        const body = beginCell()\n            .storeRef(newCode)\n            .storeRef(newData)\n            .endCell();\n        await provider.internal(via, {\n            value,\n            sendMode: SendMode.PAY_GAS_SEPARATELY,\n            body,\n        });\n    }\n}\n```\n\nCreate `scripts/deployExampleContract.ts`:\n\n```ts expandable\nimport { toNano, Address } from '@ton/core';\nimport { ExampleContract } from '../wrappers/ExampleContract';\nimport { VanityContract } from '../wrappers/VanityContract';\nimport { compile, NetworkProvider } from '@ton/blueprint';\n\nexport async function run(provider: NetworkProvider) {\n    const vanityContract = provider.open(\n        VanityContract.createFromConfig({\n            owner: Address.parse('<OWNER_ADDR>'),\n            salt: Buffer.from('<SALT_HEX>', 'hex'),\n        }),\n    );\n\n    const exampleContract = provider.open(\n        ExampleContract.createFromConfig(\n            {},\n            await compile('ExampleContract'),\n        ),\n    );\n\n    const init = exampleContract.init!;\n\n    await vanityContract.sendDeploy(\n        provider.sender(),\n        toNano('0.01'), // attach value for deployment fees\n        init.code,\n        init.data,\n    );\n\n    await provider.waitForDeploy(vanityContract.address);\n}\n```\n\nWhere:\n\n- `<OWNER_ADDR>` — address allowed to deploy via the vanity contract.\n- `<SALT_HEX>` — 32-byte salt in hex found by the generator.\n\nRun the script via `npx blueprint run`. The deployment succeeds when `<OWNER_ADDR>` matches the address of the wallet used for actual deployment. `ExampleContract` can be replaced with any contract; the vanity contract does not depend on the specifics of the code or data.\n"
  },
  {
    "path": "contract-dev/zero-knowledge.mdx",
    "content": "---\ntitle: \"Zero-knowledge proofs on TON\"\nsidebarTitle: \"Zero-knowledge proofs\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nThis guide shows how to create, compile, and test a simple [Circom](https://docs.circom.io/) scheme and verify a [ZK-proof](https://en.wikipedia.org/wiki/Zero-knowledge_proof) using the [`zk-SNARK`](https://en.wikipedia.org/wiki/Non-interactive_zero-knowledge_proof) [`Groth16`](https://eprint.iacr.org/2016/260.pdf) protocol.\n\n<Aside>\n  This guide is also applicable to circuits written in the [Noname](https://github.com/zksecurity/noname) language, since the [`export-ton-verifier`](https://github.com/mysteryon88/export-ton-verifier) library integrates with `snarkjs`, which in turn integrates with the Noname language.\n\n  Other examples can be found [here](https://github.com/zk-examples/zk-ton-examples/).\n</Aside>\n\n## Prerequisites\n\n- [Node.js](https://nodejs.org) 18 or a later LTS.\n- [`circom`](https://docs.circom.io/getting-started/installation/#installing-circom)\n- [`snarkjs`](https://docs.circom.io/getting-started/installation/#installing-snarkjs)\n- [Blueprint](/contract-dev/blueprint/overview)\n\n## Project setup\n\n1. Create a new project using Blueprint:\n\n   ```bash\n   npm create ton@latest ZkSimple\n   cd ZkSimple\n   ```\n1. Install libraries for working with ZK-proofs:\n\n   ```bash\n   npm install snarkjs @types/snarkjs\n   ```\n1. Install the verifier export utility for TON:\n\n   ```bash\n   npm install export-ton-verifier@latest\n   ```\n\nThis utility exports verifier contracts for FunC, Tolk, and Tact.\n\n## Create the Circom circuit\n\nCreate the directory `circuits/Multiplier` and the file `Multiplier.circom`:\n\n```bash\nmkdir -p circuits/Multiplier\ncd circuits/Multiplier\n```\n\n```circom\npragma circom 2.2.2;\n\ntemplate Multiplier() {\n  signal input a;\n  signal input b;\n\n  signal output c;\n\n  c <== a*b;\n}\n\ncomponent main = Multiplier();\n```\n\nThis circuit proves knowledge of two numbers `a` and `b`, whose product is equal to the public output `c`, without revealing `a` and `b` themselves.\n\n### Compile\n\nRun in `circuits/Multiplier`:\n\n```bash\ncircom Multiplier.circom --r1cs --wasm --sym --prime bls12381\n```\n\nAfter compilation, the following files will appear:\n\n- `Multiplier.r1cs` — circuit constraints (R1CS)\n- `Multiplier.sym` — symbolic signal map\n- `Multiplier.wasm` — artifact for generating proof\n\nCheck constraints:\n\n```bash\nsnarkjs r1cs info Multiplier.r1cs\n```\n\nOutput example:\n\n```\n[INFO]  snarkJS: Curve: bls12-381\n[INFO]  snarkJS: # of Wires: 4\n[INFO]  snarkJS: # of Constraints: 1\n[INFO]  snarkJS: # of Private Inputs: 2\n[INFO]  snarkJS: # of Public Inputs: 0\n[INFO]  snarkJS: # of Outputs: 1\n```\n\n<Aside>\n  `snarkjs` supports the [`alt_bn128`](https://eips.ethereum.org/EIPS/eip-196) and [`bls12-381`](https://electriccoin.co/blog/new-snark-curve/) curves. Ethereum uses `alt_bn128`, but `bls12-381` is used for TON, so it is the one chosen in this guide.\n</Aside>\n\n## Trusted setup (`Groth16`)\n\nThe **trusted setup** is a one-time ceremony that generates the proving and verification keys for a circuit. It's called \"trusted\" because if the setup parameters are compromised, proofs could be forged. For production use, participate in a multi-party trusted setup ceremony. For local development and testing, a simplified single-party setup is sufficient. For local tests, perform a simplified trusted setup ceremony.\n\nThe \"power of tau\" parameter (`10`) has to be chosen\n\n- as low as possible, because it affects execution time;\n- high enough, because the more constraints in the scheme, the higher the parameter required.\n\n```bash\n# first phase\nsnarkjs powersoftau new bls12-381 10 pot10_0000.ptau -v\nsnarkjs powersoftau contribute pot10_0000.ptau pot10_0001.ptau --name=\"First contribution\" -v -e=\"some random text\"\n\n# second phase (depends on the compiled scheme)\nsnarkjs powersoftau prepare phase2 pot10_0001.ptau pot10_final.ptau -v\nsnarkjs groth16 setup Multiplier.r1cs pot10_final.ptau Multiplier_0000.zkey\nsnarkjs zkey contribute Multiplier_0000.zkey Multiplier_final.zkey --name=\"1st Contributor\" -v -e=\"some random text\"\n\n# export verification key\nsnarkjs zkey export verificationkey Multiplier_final.zkey verification_key.json\n```\n\nClear up unnecessary artifacts:\n\n```sh\nrm pot10_0000.ptau pot10_0001.ptau pot10_final.ptau Multiplier_0000.zkey\n```\n\n## Export the verifier contract\n\n```bash\n# export FunC contract (default)\nnpx export-ton-verifier ./circuits/Multiplier/Multiplier_final.zkey ./contracts/verifier_multiplier.fc\n\n# export Tolk contract\nnpx export-ton-verifier ./circuits/Multiplier/Multiplier_final.zkey ./contracts/verifier_multiplier.tolk --tolk\n\n# export Tact contract\nnpx export-ton-verifier ./circuits/Multiplier/Multiplier_final.zkey ./contracts/verifier_multiplier.tact --tact\n```\n\nFor FunC and Tolk, wrappers must be generated manually:\n\n```bash\nnpx export-ton-verifier import-wrapper ./wrappers/Verifier.ts --force\n```\n\nThis command generates a TypeScript wrapper file that provides type-safe methods to interact with the verifier contract.\n\n## Testing and verification\n\nIn `tests/ZkSimple.spec.ts`:\n\n```ts\nimport * as snarkjs from 'snarkjs';\nimport path from 'path';\nimport { dictFromInputList, groth16CompressProof } from 'export-ton-verifier';\n\n// for Tact (After running `npx blueprint build --all`)\nimport { Verifier } from '../build/Verifier_tact/tact_Verifier';\n\n// for FunC and Tolk\nimport { Verifier } from '../wrappers/Verifier';\n```\n\nLocal verification:\n\n```ts\nconst wasmPath = path.join(__dirname, '../circuits/Multiplier', 'Multiplier.wasm');\nconst zkeyPath = path.join(__dirname, '../circuits/Multiplier', 'Multiplier_final.zkey');\nconst verificationKey = require('../circuits/Multiplier/verification_key.json');\n\nconst input = { a: '342', b: '1245' };\n\nconst { proof, publicSignals } = await snarkjs.groth16.fullProve(input, wasmPath, zkeyPath);\nconst okLocal = await snarkjs.groth16.verify(verificationKey, publicSignals, proof);\n```\n\nOn-chain verification:\n\n```ts\nconst { pi_a, pi_b, pi_c, pubInputs } = await groth16CompressProof(proof, publicSignals);\n\n// Quick check via get-method: verifies the proof locally without changing blockchain state.\nexpect(await verifier.getVerify({ pi_a, pi_b, pi_c, pubInputs })).toBe(true);\n\n// Send the proof to the contract in a message\n// The contract will run verification; handling the result/flow is up to the developer using this template.\nawait verifier.sendVerify(deployer.getSender(), { pi_a, pi_b, pi_c, pubInputs, value: toNano('0.15') });\n```\n\n<Aside type=\"tip\">\n  Build the contracts before running tests. For Tact contracts, run `npx blueprint build --all` first. For FunC/Tolk, ensure the wrappers are generated.\n</Aside>\n\n## Other Languages\n\nThis tutorial follows the path **Circom → `snarkjs` → `export-ton-verifier` → TON**.\nThe same workflow applies to other stacks — the key requirement is to obtain a `proof` and a `verification key` in `snarkjs` format.\n\nIn the example repository — [`zk-ton-examples`](https://github.com/zk-examples/zk-ton-examples/) — there are already templates for `noname`, `gnark`, and `arkworks`: proofs can be generated in any of these stacks, then converted into `snarkjs` format and verified both locally and on-chain in the same way.\n\n<Aside>\n  Two utilities are available that help convert proofs and verification keys into a format compatible with `snarkjs`:\n\n  - [`ark-snarkjs`](https://github.com/mysteryon88/ark-snarkjs): use for exporting from `arkworks`\n  - [`gnark-to-snarkjs`](https://github.com/mysteryon88/gnark-to-snarkjs): use for exporting from `gnark`\n</Aside>\n\nThe idea is always the same: generate `proof.json` and `verification_key.json` in `snarkjs` format, then use `export-ton-verifier` and perform verification in TON.\n\n### Arkworks (Rust)\n\nUse the `arkworks` library to generate the proof and verification key, then convert them into `snarkjs` format with `ark-snarkjs`.\n\n1. Set up an Arkworks project:\n\n```sh\ncargo init\ncargo add ark-bls12-381 ark-ff ark-groth16 ark-r1cs-std ark-relations ark-snark ark-snarkjs ark-std rand@0.8.5\n```\n\n<Aside>\n  The packages listed above are the core dependencies needed for most `arkworks` circuits. Depending on the specific circuit implementation, additional packages may be required.\n</Aside>\n\n2. Write the circuit in Rust. Implement the circuit logic using `arkworks` primitives, similar to how a Circom circuit would be written. Learn how to write constraints in `arkworks` by following the [Arkworks R1CS tutorial](https://github.com/arkworks-rs/r1cs-tutorial). A working example of a simple multiplication circuit can be found in the [`zk-ton-examples` repository](https://github.com/zk-examples/zk-ton-examples/tree/main/circuits/Arkworks/MulCircuit).\n\n2. Compile, generate proof, and perform trusted setup following the same workflow as in the Circom section above.\n\n2. Export the proof and verification key to JSON using `ark-snarkjs`:\n\n```rust\nuse ark_snarkjs::{export_proof, export_vk};\nuse ark_bls12_381::{Bls12_381, Fr};\n\nlet _ = export_proof::<Bls12_381, _>(&proof, &public_inputs, \"json/proof.json\");\nlet _ = export_vk::<Bls12_381, _>(\n    &params.vk,\n    public_inputs.len(),\n    \"json/verification_key.json\",\n);\n```\n\nThe directory and files will be created automatically.\n\n5. Export the verifier contract:\n\n```sh\n# FunC contract\nnpx export-ton-verifier ./circuits/Arkworks/MulCircuit/json/verification_key.json ./contracts/verifier_ark.fc\n\n# Tact contract\nnpx export-ton-verifier ./circuits/Arkworks/MulCircuit/json/verification_key.json ./contracts/verifier_ark.tact --tact\n\n# Tolk contract\nnpx export-ton-verifier ./circuits/Arkworks/MulCircuit/json/verification_key.json ./contracts/verifier_ark.tolk --tolk\n```\n\n### `gnark` (Go)\n\nUse the `gnark` library to generate the proof and verification key, then convert them into `snarkjs` format with `gnark-to-snarkjs`.\n\n1. Set up a `gnark` project. You can find an example circuit in the [`gnark` repository](https://github.com/Consensys/gnark?tab=readme-ov-file#example). A working example of a cubic circuit can be found in the [`zk-ton-examples` repository](https://github.com/zk-examples/zk-ton-examples/tree/main/circuits/Cubic%20%28gnark%29).\n\n1. Add `gnark-to-snarkjs` as a dependency:\n\n```sh\ngo get github.com/mysteryon88/gnark-to-snarkjs@latest\n```\n\n3. Export the proof and verification key:\n\n```go\n{\n  proof_out, _ := os.Create(\"proof.json\")\n  defer proof_out.Close()\n  _ = gnarktosnarkjs.ExportProof(proof, []string{\"35\"}, proof_out)\n}\n{\n  out, _ := os.Create(\"verification_key.json\")\n  defer out.Close()\n  _ = gnarktosnarkjs.ExportVerifyingKey(vk, out)\n}\n```\n\n4. Export the verifier contract:\n\n```sh\n# Tact contract\nnpx export-ton-verifier ./circuits/cubic-gnark/verification_key.json ./contracts/verifier_cubic.tact --tact\n\n# FunC contract\nnpx export-ton-verifier ./circuits/cubic-gnark/verification_key.json ./contracts/verifier_cubic.fc\n\n# Tolk contract\nnpx export-ton-verifier ./circuits/cubic-gnark/verification_key.json ./contracts/verifier_cubic.tolk --tolk\n```\n\n## Conclusion\n\nThis guide demonstrates a minimal example: **circuit → trusted setup → verifier export → verification in TON**. This workflow can be extended to support more complex circuits and real-world applications.\n\n## Useful Links\n\n- Example repository: [`zk-ton-examples`](https://github.com/zk-examples/zk-ton-examples/)\n- Verifier export library: [`export-ton-verifier`](https://github.com/mysteryon88/export-ton-verifier)\n- Additional utilities:\n  - [`ark-snarkjs`](https://github.com/mysteryon88/ark-snarkjs)\n  - [`gnark-to-snarkjs`](https://github.com/mysteryon88/gnark-to-snarkjs)\n- Using ZK-proofs in Tact: [docs.tact](https://docs.tact-lang.org/cookbook/zk-proofs/)\n- Circom: [docs.circom.io](https://docs.circom.io/)\n- Noname: [`zksecurity/noname`](https://github.com/zksecurity/noname)\n- `gnark`: [`consensys/gnark`](https://github.com/Consensys/gnark)\n- Arkworks: [`arkworks`](https://arkworks.rs/)\n- SnarkJS: [`iden3/snarkjs`](https://github.com/iden3/snarkjs)\n"
  },
  {
    "path": "contribute/snippets/aside.mdx",
    "content": "---\ntitle: \"Aside component\"\nsidebarTitle: \"Aside\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nTo display secondary information alongside a page’s main content, use the `<Aside>` component.\n\n<Aside>\n  Include nonessential, supplementary information in a regular `<Aside>`. If some information is important or might lead to bad cases when not taken into consideration, specify a different [`type`](#type), such as `\"caution\"` or `\"danger\"`.\n</Aside>\n\nIt is a wrapper over built-in [Callout components](https://www.mintlify.com/docs/components/callouts) provided by Mintlify, but with a unified interface and a way to specify a title.\n\n## Import\n\n```tsx\nimport { Aside } from '/snippets/aside.jsx';\n```\n\n## Usage\n\nDisplay an aside (also known as \"admonitions\" or \"callouts\") using the `<Aside>` component.\n\nAn `<Aside>` can have an optional [`type`](#type) attribute, which controls the aside’s color, icon, and default title.\n\n````mdx\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside>Some content in an aside.</Aside>\n\n<Aside type=\"caution\">Some cautionary content.</Aside>\n\n<Aside type=\"tip\">\n\n  Other content is also supported in asides.\n\n  ```js\n  // A code snippet, for example.\n  ```\n\n</Aside>\n\n<Aside type=\"danger\">Do not give your password to anyone.</Aside>\n````\n\n### Use custom titles\n\nOverride the default aside titles by using the [`title`](#title) attribute.\n\n```mdx title=\"Watch out!\"\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside type=\"caution\" title=\"Watch out!\">\n  A warning aside _with_ a custom title.\n</Aside>\n```\n\n## `<Aside>` props\n\n**Implementation:** [`aside.jsx`](https://github.com/ton-org/docs/blob/main/snippets/aside.jsx)\n\nThe `<Aside>` component accepts the following props:\n\n### `type`\n\n**type:** `\"note\" | \"tip\" | \"caution\" | \"danger\"` <br />\n**default:** `\"note\"`\n\nThe type of aside to display:\n\n- `note` asides (the default) are blue and display an information icon.\n- `tip` asides are purple and display a rocket icon.\n- `caution` asides are yellow and display a triangular warning icon.\n- `danger` asides are red and display an octagonal warning icon.\n\nPassing a different, unrecognized type resets the type to `danger` and replaces text content with the corresponding error message.\n\n### `title`\n\n**type:** `string` <br />\n**default:** `\"\"` (no title)\n\nThe title of the aside to display. If `title` is not set, no title is displayed.\n\n### `icon`\n\n**type:** `string` <br />\n**default:** `\"\"` (corresponds to the [`type`](#type))\n\nThe custom icon to display instead of the default one set by the [`type`](#type). Can be one of the following:\n\n- [Font Awesome icon] name\n- [Lucide icon](https://lucide.dev/icons) name\n\n### `iconType`\n\n**type:** `\"regular\" | \"solid\" | \"light\" | \"thin\" | \"sharp-solid\" | \"duotone\" | \"brands\"` <br />\n**default:** `\"regular\"`\n\nThe [Font Awesome icon] style — only used with Font Awesome icons.\n\n[Font Awesome icon]: https://fontawesome.com/icons\n"
  },
  {
    "path": "contribute/snippets/filetree.mdx",
    "content": "---\ntitle: \"FileTree component\"\nsidebarTitle: \"FileTree\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\nimport { FileTree } from '/snippets/filetree.jsx';\n\nTo display the structure of a directory with files and collapsible subdirectories, use the `<FileTree>` component. Click on a subdirectory to open or close it.\n\n<Aside type=\"note\">\n  Additionally, notes can be added to files and directories, which are displayed after their names.\n</Aside>\n\nThe `<FileTree>` is a wrapper over the built-in [`<Tree>` component](https://www.mintlify.com/docs/components/tree) provided by Mintlify, but with a data-driven interface: pass a list of objects and strings instead of [composing JSX children manually](#using-\\<tree>-directly).\n\n## Import\n\n```tsx\nimport { FileTree } from '/snippets/filetree.jsx';\n```\n\n## Usage\n\nSpecify the structure of files and directories inside the [`items` property](#items) as a JavaScript list of strings, objects, and nested lists.\n\n```mdx\nimport { FileTree } from '/snippets/filetree.jsx';\n\n<FileTree items={[ /* ...entries, see below... */ ]} />\n```\n\n### Specify files and placeholders\n\n```mdx\nimport { FileTree } from '/snippets/filetree.jsx';\n\n{/* Files and a placeholder by the end */}\n<FileTree\n  items={[\n    \"file-name-1.ml\",\n    \"file-name-2.hs\",\n    \"file-name-3.mp3\",\n    \"...\", // will be rendered as …\n  ]}\n/>\n```\n\n<FileTree\n  items={[\"file-name-1.ml\", \"file-name-2.hs\", \"file-name-3.mp3\", \"...\"]}\n/>\n\n### Add notes and comments\n\n```mdx\nimport { FileTree } from '/snippets/filetree.jsx';\n\n{/* Using objects to add notes or nested folders */}\n<FileTree\n  items={[\n    \"file-name-1\",\n    { kind: \"file\", name: \"file-name-2\", note: \"very important file\" },\n    {\n      kind: \"folder\",\n      name: \"best-folder\",\n      note: \"not really\",\n      open: false, // otherwise defaults to true\n      items: [\"file-name-3-within-subfolder\"],\n    },\n  ]}\n/>\n```\n\n<FileTree\n  items={[\"file-name-1\", {\n    kind: \"file\",\n    name: \"file-name-2\",\n    note: \"very important file\"\n  }, {\n    kind: \"folder\",\n    name: \"best-folder\",\n    note: \"not really\",\n    open: false,\n    items: [\"file-name-3-within-subfolder\"]\n  }]}\n/>\n\n### Specify folders and their state\n\n```mdx\nimport { FileTree } from '/snippets/filetree.jsx';\n\n{/* Make all sub-folders be closed by default */}\n<FileTree\n  items={[\n    { kind: \"folder\", name: \"folder-1\", open: true, items: [\"something1\"] },\n    { kind: \"folder\", name: \"folder-2\", items: [\"something2\"] },\n  ]}\n  defaultOpen={false} {/* otherwise defaults to true */}\n/>\n```\n\n<FileTree\n  items={[{\n    kind: \"folder\",\n    name: \"folder-1\",\n    open: true,\n    items: [\"something1\"]\n  }, {\n    kind: \"folder\",\n    name: \"folder-2\",\n    items: [\"something2\"]\n  }]}\n  defaultOpen={false}\n/>\n\n## `<FileTree>` props\n\n**Implementation:** [`filetree.jsx`](https://github.com/ton-org/docs/blob/main/snippets/filetree.jsx)\n\nThe `<FileTree>` component accepts the following props:\n\n### `items` (required)\n\n**type:** `FileTreeItem[]`\n\nHierarchy of files and folders to display.\n\nThe `FileTreeItem` can be one of the following kinds:\n\n- `...` or `…` — both display a placeholder entry `…` indicating additional items in a directory that are intentionally omitted\n- any `string` — name of the file inside the currently described directory\n- `{ kind: \"file\", ...fields... }` — an extended syntax for files, with the following fields:\n  - `name: string` — the filename;\n  - `note?: string` — optional comment, displayed next to the filename;\n- `{ kind: \"folder\", ...fields... }` — syntax for folders and directories, with the following fields:\n  - `name: string` — the directory name;\n  - `note?: string` — optional comment, displayed next to the directory name;\n  - `open?: boolean` — whether to open the directory, defaults to `true`;\n  - `items: FileTreeItem[]` — nested files and folders;\n\n<Aside type=\"note\">\n  Folders are open by default. That is, their `open` property is `true` unless specified otherwise.\n</Aside>\n\n### `defaultOpen`\n\n**type:** `boolean` <br />\n**default:** `true`\n\nWhether to open all folders on page load. Can be overridden by the `open` property of individual [`FileTreeItem` entries](#items-required).\n\n## Using `<Tree>` directly\n\nFor cases where a data-driven approach is unnecessary, use the built-in `<Tree>` component directly. It requires no import and accepts `<Tree.File>` and `<Tree.Folder>` sub-components as children.\n\n```mdx\n<Tree>\n  <Tree.Folder name=\"app\" defaultOpen>\n    <Tree.File name=\"layout.tsx\" />\n    <Tree.File name=\"page.tsx\" />\n    <Tree.Folder name=\"api\" defaultOpen>\n      <Tree.Folder name=\"auth\">\n        <Tree.File name=\"route.ts\" />\n      </Tree.Folder>\n      <Tree.File name=\"route.ts\" />\n    </Tree.Folder>\n    <Tree.Folder name=\"components\">\n      <Tree.File name=\"button.tsx\" />\n      <Tree.File name=\"dialog.tsx\" />\n      <Tree.File name=\"tabs.tsx\" />\n    </Tree.Folder>\n  </Tree.Folder>\n  <Tree.File name=\"package.json\" />\n</Tree>\n```\n\n<Tree>\n  <Tree.Folder\n    name=\"app\"\n    defaultOpen\n  >\n    <Tree.File\n      name=\"layout.tsx\"\n    />\n\n    <Tree.File\n      name=\"page.tsx\"\n    />\n\n    <Tree.Folder\n      name=\"api\"\n      defaultOpen\n    >\n      <Tree.Folder\n        name=\"auth\"\n      >\n        <Tree.File\n          name=\"route.ts\"\n        />\n      </Tree.Folder>\n\n      <Tree.File\n        name=\"route.ts\"\n      />\n    </Tree.Folder>\n\n    <Tree.Folder\n      name=\"components\"\n    >\n      <Tree.File\n        name=\"button.tsx\"\n      />\n\n      <Tree.File\n        name=\"dialog.tsx\"\n      />\n\n      <Tree.File\n        name=\"tabs.tsx\"\n      />\n    </Tree.Folder>\n  </Tree.Folder>\n\n  <Tree.File\n    name=\"package.json\"\n  />\n</Tree>\n"
  },
  {
    "path": "contribute/snippets/image.mdx",
    "content": "---\ntitle: \"Image component\"\nsidebarTitle: \"Image\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\nimport { Image } from '/snippets/image.jsx';\n\nTo display an image, use the `<Image>` component. It allows displaying either a single image for all themes ([`src`](#src)) or one image per light theme (`src`) and one image for the dark theme ([`darkSrc`](#darksrc)).\n\n<Aside>\n  When an `src` path points to the SVG image and there is no [`darkSrc`](#darksrc) alternative, image colors will be inverted in the dark theme.\n</Aside>\n\nAdditionally, you can specify the [`href`](#href) property, making an image double as a clickable link. When doing so, the [`target`](#href) property allows to change the browsing context of the link.\n\n<Aside>\n  Making an image into a clickable link disables image zoom capabilities.\n</Aside>\n\nFinally, to adjust image dimensions in pixels, use [`height`](#height) or [`width`](#width) properties. By default, all images use 16:9 aspect ratio and set `height` to 342px and `width` to 608px.\n\n## Import\n\n```tsx\nimport { Image } from '/snippets/image.jsx';\n```\n\n## Usage\n\nShow images using the `<Image>` component.\n\n```mdx\nimport { Image } from '/snippets/image.jsx';\n\n{/* A single image */}\n<Image\n  src=\"/resources/images/<IMAGE>\"\n/>\n\n{/*\n  Image with height of 608px (max allowed).\n  Its width will be scaled proportionally to set height and vice versa.\n*/}\n<Image\n  src=\"/resources/images/<IMAGE>\"\n  height=\"608\"\n/>\n\n{/* Image variations for light or dark themes */}\n<Image\n  src=\"/resources/images/<IMAGE>\"\n  darkSrc=\"/resources/images/<IMAGE_DARK_THEME>\"\n  />\n\n{/* Image with all properties set */}\n<Image\n  src=\"/resources/images/<IMAGE>\"\n  alt=\"<ALT_TEXT>\"\n  darkSrc=\"/resources/images/<IMAGE_DARK_THEME>\"\n  darkAlt=\"<ALT_TEXT_DARK_THEME>\"\n  href=\"<CLICKABLE_LINK>\"\n  target=\"_blank\"\n  height=\"100\"\n  width={120 + 120}\n  />\n```\n\n## `<Image>` props\n\n**Implementation:** [`image.jsx`](https://github.com/ton-org/docs/blob/main/snippets/image.jsx)\n\nThe `<Image>` component accepts the following props:\n\n### `src` (required)\n\n**type:** `string`\n\nThe image file URL. The file path should be given either relative to the current `.mdx` file's location or absolute, assuming the root of the documentation repository is the `/` directory.\n\n<Aside\n  type=\"caution\"\n>\n  Relative links should **NOT** use `..` in their paths to avoid discovery or security issues.\n</Aside>\n\n<Aside>\n  Image files must be less than 20 MB uncompressed. For larger files, host them on a CDN service like Amazon S3.\n</Aside>\n\nExamples:\n\n- `<Image src=\"<IMAGE>\" />` — relative path to an image placed in the same folder as the current `.mdx` file.\n- `<Image src=\"/resources/images/<IMAGE>\" />` — absolute path to an image in the `resources/images/` sub-folder.\n\n### `alt`\n\n**type:** `string` <br />\n**default:** `\"\"`\n\nThe textual replacement for the image. It is mandatory and incredibly useful for accessibility — screen readers read the attribute value out to their users so they know what the image means. Alt text is also displayed on the page if the image can't be loaded for any reason, such as network errors, content blocking, or [link rot](https://en.wikipedia.org/wiki/Link_rot).\n\nSetting this attribute to an empty string (`alt=\"\"`) indicates that this image is not a key part of the content (it's decoration or a tracking pixel), and that non-visual browsers may omit it from rendering. Visual browsers will also hide the broken image icon if the alt attribute is empty and the image failed to display.\n\nThis attribute is also used when copying and pasting the image to text, or saving a linked image to a bookmark.\n\nSee more: [`alt` attribute on the `<img>` image embed element, MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/img#alt).\n\n### `darkSrc`\n\n<Aside>\n  The value of this property is ignored unless the [`src` property](#src) is set.\n</Aside>\n\n**type:** `string` <br />\n**default:** [`src`](#src) value\n\nSimilar to the [`src` property](#src), but specifies the image file URL for the dark theme only.\n\n### `darkAlt`\n\n<Aside>\n  The value of this property is ignored unless the [`darkSrc` property](#darksrc) is set.\n</Aside>\n\n**type:** `string` <br />\n**default:** [`alt`](#alt) value\n\nSimilar to the [`alt` property](#alt), but specifies the image file URL for the dark theme only.\n\n### `href`\n\n**type:** `string`\n\nThe `<a>` anchor element wraps the image, making it clickable. The `href` property is a URL that the clickable image hyperlink points to.\n\nSee more: [`href` attribute on the `<a>` anchor element, MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/a#href).\n\n### `target`\n\n<Aside>\n  The value of this property is ignored unless the [`href` property](#href) is set.\n</Aside>\n\n**type:** `\"_self\" | \"_blank\" | \"_parent\" | \"_top\" | \"_unfencedTop\"` <br />\n**default:** `\"_self\"`\n\nThe `<a>` anchor element wraps the image, making it clickable. The `target` property specifies where to display the linked URL, as the name for a browsing context (a tab, window, or [`<iframe>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/iframe)).\n\nThe following types have special meanings for where to load the URL:\n\n- `_self`: the current browsing context. (Default)\n- `_blank`: usually a new tab, but users can configure browsers to open a new window instead.\n- `_parent`: the parent browsing context of the current one. If there is no parent, behaves as `_self`.\n- `_top`: the topmost browsing context, i.e., the \"highest\" context that's an ancestor of the current one. If there are no ancestors, behaves as `_self`.\n- `_unfencedTop`: allows embedded [fenced frames](https://developer.mozilla.org/en-US/docs/Web/API/Fenced_frame_API) to navigate the top-level frame.\n\nSee more: [`target` attribute on the `<a>` anchor element, MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/a#target).\n\n### `height`\n\n**type:** `string | number` <br />\n**default:** `342` (pixels)\n\nThe intrinsic height of the image, in pixels. Must be specified without a unit and be within the inclusive range from 9 to 608.\n\nIf the [`width`](#width) property is not set, then the width of the image is adjusted according to the current aspect ratio in respect to the new set `height`.\n\nExamples:\n\n- `<Image src=\"<IMAGE>\" height=\"100\" />` — height of 100 pixels given in a string.\n- `<Image src=\"<IMAGE>\" height={50 + 50} />` — also the height of 100 pixels, but given as a number.\n\nSee more: [`height` attribute on the `<img>` image embed element, MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/img#height).\n\n### `width`\n\n**type:** `string | number` <br />\n**default:** `608` (pixels)\n\nThe intrinsic width of the image, in pixels. Must be specified without a unit and be within the inclusive range from 9 to 608.\n\nIf the [`height`](#height) property is not set, then the height of the image is adjusted according to the current aspect ratio in respect to the new set `width`.\n\nExamples:\n\n- `<Image src=\"<IMAGE>\" width=\"100\" />` — width of 100 pixels given in a string.\n- `<Image src=\"<IMAGE>\" width={50 + 50} />` — also the width of 100 pixels, but given as a number.\n\nSee more: [`width` attribute on the `<img>` image embed element, MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/img#width).\n\n### `center`\n\n**type:** `boolean` <br />\n**default:** `false`\n\nWhether to horizontally center the image.\n\nUsage: `<Image src=\"<IMAGE>\" center={true}/>`.\n\n### `noZoom`\n\n**type:** `boolean` <br />\n**default:** `false`\n\nWhether to disable the image zoom.\n\nUsage: `<Image src=\"<IMAGE>\" noZoom={true}/>`.\n"
  },
  {
    "path": "contribute/snippets/overview.mdx",
    "content": "---\ntitle: \"Using components and snippets\"\nsidebarTitle: \"Overview\"\n---\n\n_Snippets_ keep the same content in sync across pages, while _components_ provide reusable UI elements with consistent styling. Examples include a [link card](https://www.mintlify.com/docs/components/cards) or a [YouTube embed](https://www.mintlify.com/docs/create/image-embeds#youtube-embeds).\n\nMintlify supports MDX snippets and JSX (React) components in MDX files, and provides several [built-in components](#built-in-components). In addition, this documentation includes a number of [custom components](#custom-components) in the `snippets/` folder.\n\n## Using a snippet\n\nThe [DRY (Don't Repeat Yourself)](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) principle applies to documentation. When the same content appears in multiple places, create a custom snippet to keep it in sync.\n\nAll snippets are placed in the root `snippets/` folder. For creation and usage details, see the [Mintlify reusable snippets documentation](https://www.mintlify.com/docs/create/reusable-snippets).\n\n## Using a component\n\nTo use a custom component, import it into the MDX file and render it as a JSX tag. Tags start with an uppercase letter matching the name in the import statement:\n\n```mdx title=\"some/page.mdx\"\n---\ntitle: \"Frontmatter goes first, as usual\"\n---\n\n{/* Snippet imports go right after the frontmatter */}\nimport MyMdxSnippet from '/snippets/my-mdx-snippet.mdx';\n\n{/* Component imports follow suit */}\nimport { Aside } from '/snippets/aside.jsx';\n\nAnd now, some text and usage!\n\n<Aside>Here we go, some **nested content and formatting**!</Aside>\n```\n\nRelated Mintlify documentation:\n\n- [JSX snippets](https://www.mintlify.com/docs/create/reusable-snippets#jsx-snippets)\n- [React components](https://www.mintlify.com/docs/customize/react-components)\n\n## Built-in components\n\n[Mintlify provides built-in components](https://www.mintlify.com/docs/components/index) for common documentation use cases. These components are available globally without needing to import anything.\n\n### Use sparingly\n\nKeep formatting as simple as possible. Avoid components when a paragraph or series of paragraphs communicates the same intent and information without them.\n\n<Card\n  title=\"Steps\"\n  icon=\"list-ol\"\n  href=\"https://www.mintlify.com/docs/components/steps\"\n  horizontal=\"true\"\n>\n  Display sequential instructions in a numbered format.\n</Card>\n\n<Card\n  title=\"Code groups\"\n  icon=\"code\"\n  href=\"https://www.mintlify.com/docs/components/code-groups\"\n  horizontal=\"true\"\n>\n  Display multiple code examples with a toggle.\n</Card>\n\n<Card\n  title=\"Cards\"\n  icon=\"square\"\n  href=\"https://www.mintlify.com/docs/components/cards\"\n  horizontal=\"true\"\n>\n  Highlight content with customizable containers and icons. Prefer regular ordered or unordered Markdown lists and resort to cards only when the relevant links and content should stand out.\n</Card>\n\n<Card\n  title=\"Columns\"\n  icon=\"columns-3\"\n  href=\"https://www.mintlify.com/docs/components/columns\"\n  horizontal=\"true\"\n>\n  Arrange \\<Card> components in responsive layouts.\n</Card>\n\n<Card\n  title=\"Accordions\"\n  icon=\"chevron-down\"\n  href=\"https://www.mintlify.com/docs/components/accordions\"\n  horizontal=\"true\"\n>\n  Expandable sections for progressive disclosure of content.\n</Card>\n\n<Card\n  title=\"Expandables\"\n  icon=\"chevrons-down\"\n  href=\"https://www.mintlify.com/docs/components/expandables\"\n  horizontal=\"true\"\n>\n  Show and hide detailed content on demand. Append the expandable keyword to the opening part of a code block to collapse large examples.\n</Card>\n\n<Card\n  title=\"Badge\"\n  icon=\"award\"\n  href=\"https://www.mintlify.com/docs/components/badge\"\n  horizontal=\"true\"\n>\n  Add inline labels and status indicators for outdated or deprecated items. Otherwise, avoid this component.\n</Card>\n\n<Card\n  title=\"Tooltips\"\n  icon=\"message\"\n  href=\"https://www.mintlify.com/docs/components/tooltips\"\n  horizontal=\"true\"\n>\n  Display additional information on hover without going too deep. Link to the [glossary](/foundations/glossary), a detailed explanation page, or a reference page instead.\n</Card>\n\n<Card\n  title=\"Fields\"\n  icon=\"input-text\"\n  href=\"https://www.mintlify.com/docs/components/fields\"\n  horizontal=\"true\"\n>\n  Display parameter and property definitions, configuration options, or object fields.\n</Card>\n\nUse either of the following components only on pages that document HTTP APIs. Because they override the default auto-generated blocks, prefer regular code blocks whenever possible.\n\n<Card\n  title=\"Responses\"\n  icon=\"arrow-left-arrow-right\"\n  href=\"https://www.mintlify.com/docs/components/responses\"\n  horizontal=\"true\"\n>\n  Show \\<ResponseField> that describes API response structures and fields.\n</Card>\n\n<Card\n  title=\"Examples\"\n  icon=\"file-code\"\n  href=\"https://www.mintlify.com/docs/components/examples\"\n  horizontal=\"true\"\n>\n  Show \\<RequestExample> and \\<ResponseExample> side by side.\n</Card>\n\nWhen explaining a complex topic or writing a tutorial, use concise diagrams to clarify behavior that text and code cannot.\n\n<Card\n  title=\"Mermaid diagrams\"\n  icon=\"chart-diagram\"\n  href=\"https://www.mintlify.com/docs/components/mermaid-diagrams\"\n  horizontal=\"true\"\n>\n  Use code blocks with [Mermaid.js](https://mermaid.js.org/) syntax to create flowcharts, sequence diagrams, and more.\n</Card>\n\n### Do not use\n\nThese components have better alternatives:\n\n1. `<Callout>` - use the custom [`<Aside>`](/contribute/snippets/aside) component.\n1. `<Frame>` - use the custom [`<Image>`](/contribute/snippets/image) component.\n1. `<View>` - use `<CodeGroup>`, organize content in sub-headers, or create distinct pages per environment or language.\n1. `<Tile>` - use `<Card>`.\n1. `<Icon>` - do not use unless icons in other components or code blocks are insufficient in the given case.\n\nThese components are currently unused:\n\n1. `<Banner>` - reserved for special occasions and public releases.\n1. `<Update>` - the documentation does not contain changelogs.\n\n## Custom components\n\nTON documentation includes custom components built for various needs. See items on the left navigation panel within the \"Components and snippets\" group under the \"Contribute\" section, such as: [Aside](/contribute/snippets/aside), [Image](/contribute/snippets/image), etc.\n\n## Styling\n\nMintlify supports [Tailwind CSS v3][tailwind] for styling HTML elements and any components or snippets from the `snippets/` folder.\n\nRelated resources:\n\n- [Styling with Tailwind CSS in the Mintlify documentation](https://www.mintlify.com/docs/settings/custom-scripts#styling-with-tailwind-css)\n- [Tailwind CSS v3 documentation][tailwind]\n- [Unofficial Tailwind CSS v3 cheatsheet](https://tailwindcss.504b.cc/)\n\n## See also\n\n- [Text formatting, headers, and styling with Mintlify](https://www.mintlify.com/docs/create/text)\n\n[tailwind]: https://v3.tailwindcss.com/docs/utility-first\n"
  },
  {
    "path": "contribute/style-guide-extended.mdx",
    "content": "# TON documentation style guide\n\n## 0. Purpose, scope, and normative terms\n\nPurpose. This guide defines the required writing style for all public, developer-facing TON documentation. Its goal is to maximize reading experience and task success: a developer should be able to land on the right page, follow it once, and succeed. This document is intentionally explicit so both humans and automated tools (including LLM reviewers) can apply it consistently. (Why: a single, explicit house style reduces cognitive load, prevents voice drift, and enables reliable human and automated review.)\n\nScope. These rules **MUST** be followed on all pages in the docs site, including, for example: step-by-step/how‑tos, explanations, and references (CLI, TVM, standard contracts, network, config, serialization). Exceptions **MUST** be documented in Style exceptions with owner and expiry. (Why: consistent coverage avoids fragmented micro-styles; documented exceptions stay accountable and temporary.)\n\nNormative terms. The keywords **MUST**, **MUST NOT**, **SHOULD**, **SHOULD NOT**, **MAY**, **RECOMMENDED**, and **OPTIONAL** are to be interpreted as described in RFC 2119/8174. (Why: shared semantics eliminate ambiguity about what is mandatory vs. optional.)\n\nDefinitions (used throughout).\n\n- Page — a single documentation article.\n- Doc type — one of: Step by step, How‑to guide, Explanation, Reference (see [§3](#3-documentation-framework-content-types)).\n- Snippet — any code or command block.\n- Partial snippet — a focused excerpt that **MAY** be non‑runnable by itself and **MUST** be labeled as such (see [§10](#10-code-and-command-examples)).\n- Placeholder — a value the reader must replace; formatted as `<LIKE_THIS>`.\n- Admonition — a callout such as Note, Tip, Important, Caution, or Warning.\n- Reference anchor — a deep link to a specific item in a reference page (flag, field, error code, and similar items).\n\nOut of scope. Editorial process, CI wiring, analytics/metrics, and governance live outside this guide. (This guide is about writing.) (Why: focusing on writing rules keeps this document stable and avoids process churn.)\n\nLiving document. This guide evolves with the documentation. Editors **MAY** update rules as the information architecture and best practices change. When the guide changes, all existing documentation **MUST** be re-validated against the new rules and updated as needed to keep the docs consistent. (Why: styles must adapt as the product and the information architecture evolve; re-validation prevents long-term drift.)\n\n### Severity model (release‑blocking)\n\nLegend. \\[HIGH] blocks release; \\[MEDIUM] warns (non‑blocking); \\[LOW] suggestion.\n\nDefaults. Unless marked otherwise: MUST/MUST NOT → \\[MEDIUM]; SHOULD/SHOULD NOT → \\[LOW]; MAY/OPTIONAL/RECOMMENDED → \\[LOW].\n\nGlobal overrides (always \\[HIGH]). Safety callouts ([§11](#11-safety-critical-content-blockchain-specific)) when required; secrets in examples; copy/paste hazards (prompts in commands, mixed command+output, hard‑wrapped commands, undefined placeholders); destructive flags without warnings; broken/missing anchors or linking to superseded pages as normative; non‑HTTPS/tracked/unofficial links when official exists; use of `{}`/`[]` placeholders in commands; silent truncation of IDs/addresses.\n\nAnnotation scope. To keep the doc clean, inline badges are added only to \\[HIGH] items; all other items inherit the defaults above.\n\n## 1. Goals and principles (reader‑first, answer‑first)\n\n- Intent. Every page exists to help a developer finish a real task quickly and correctly.\n- Pages **MUST** optimize for clarity, scannability, accuracy, and trust;\n- Pages **MUST NOT** contain marketing language in technical sections. \\[HIGH]\n- Pages **SHOULD** be answer‑first (solution before theory) and example‑first (real code before exposition). (Why: task‑focused, plain, and scannable pages help readers complete work on the first try; marketing copy and theory up front slow readers and reduce trust.)\n\nPrinciples.\n\n1. Answer‑first. Open with purpose, outcome, and prerequisites. Then show the steps (or the API signature in reference). Background theory moves to its own Explanation page or a brief end section. (Why: leading with the solution shortens time‑to‑success; moving theory prevents detours for readers who just need to act.)\n   Example (good):\n   Goal: “Send a jetton from a web app.” Prerequisites: JS SDK, funded testnet wallet. Steps: 1–5. Verify: expected output. Troubleshoot: common errors.\n1. Example‑first and precise. Provide copy‑pasteable snippets with expected output. Use `<PLACEHOLDER>` values and define them at first use. Avoid unnecessary narrative around code. (Why: runnable, minimal examples remove guesswork; placeholders prevent users from pasting unsafe, hard‑coded values.)\n1. Minimal concepts in task pages. Do not front‑load long explanations in step-by-step/how‑tos. Link to a concept page instead. (Why: keeping theory separate avoids cognitive overload; readers can pull background only if they need it.)\n1. Single source of truth. Don’t duplicate reference tables in guides. Summarize only what's needed, then link to the reference anchor. (Why: duplication drifts and conflicts; deep links keep guides brief and ensure details stay correct in one place.)\n1. Scannability. Prefer short paragraphs (≤ \\~5 sentences) and short sentences (\\~15–20 words). Use headings, lists, and tables to chunk information. See [§8](#8-readability-and-scannability) for norms and flexibility. (Why: short, well‑chunked text is faster to scan and reduces rereads and errors.)\n\nAnti‑patterns (MUST NOT). Vague claims (“blazingly fast”), filler (“simply”, “just”, “obviously”, “please note”), and long theoretical detours in task pages. (Why: vague or padded text wastes time and hides the action; front‑loaded theory blocks progress for users who came to do a task.)\n\n## 2. Audience and assumptions\n\nDefault audience. The primary reader is new to blockchain but experienced in software development. (Why: sets a clear baseline so pages explain TON concepts without re-teaching general programming.) Pages **MUST NOT** re‑teach generic developer skills (e.g., basic shell, Git, Python/JS syntax) unless a step is unusual for TON. (Why: keeps pages focused and shorter; duplicating generic skills adds noise and goes stale quickly.)\n\nDeclaring prerequisites. Step by step and how‑to pages **SHOULD** include a Prerequisites block at the top. Reference pages **SHOULD** include a one‑line Summary to orient the reader. (Why: consistent placement improves scanning and lets readers self‑select quickly.)\n\n### 2.1 What belongs in Prerequisites\n\nPrerequisites are entry conditions: things the reader must have or have done before starting. Each item **MUST** be concrete and verifiable. (Why: readers should be able to check each prerequisite before starting to avoid wasted effort.)\n\nExamples of valid prerequisite categories:\n\n- **Software already installed** (not installed during the guide). Specify version and link to download page.\n- **Accounts or access already obtained**: API keys, RPC endpoints, wallet accounts.\n- **Artifacts from prior work**: `\"A deployed contract from [Deploy a counter](/path/to/guide)\"`, `\"A funded testnet wallet\"`.\n- **Funds or tokens**: \"Testnet TON from the [faucet](https://...)\".\n- **Unusual hardware** (only when relevant): \"A machine with at least 16 GiB RAM\".\n\n### 2.2 What does not belong in Prerequisites\n\n- **Obvious assumptions**. You **MUST NOT** list: internet connection, an operating system, a keyboard, a terminal/shell, a browser, a text editor, or similar universal tools. (Why: obvious items waste space and insult reader intelligence.) \\[HIGH]\n\n- **Things installed or created during the guide**. If step 1 is \"Install the SDK\", the SDK is **NOT** a prerequisite — the prerequisite is what is needed to install it (e.g., Node.js). You **MUST NOT** list items that the guide itself provides. (Why: listing in‑guide installations as prerequisites confuses readers about what they need beforehand.) \\[HIGH]\n\n- **Skills or knowledge**. \"Familiarity with TypeScript\" or \"Understanding of smart contracts\" are audience statements, not prerequisites. Use a separate \"Audience\" note for these (e.g., \"Audience: Intermediate. Assumes working knowledge of TypeScript and async/await.\"). You **MUST NOT** mix skills into the Prerequisites list. (Why: skills cannot be \"installed\" or verified the same way; separating them clarifies what readers need to do vs. know.) \\[HIGH]\n\n- **Background reading or concept links**. `\"Read the [Account model](/foundations/accounts) page first\"` belongs in prose or a \"Background\" section, not Prerequisites. If understanding a concept is truly required, state it as an audience assumption. You **SHOULD NOT** put learning links in Prerequisites. (Why: prerequisites are for artifacts and tools, not reading assignments.)\n\n### 2.3 Version specifications\n\n- Software prerequisites **MUST** specify at least the version tested in the guide. (Why: unversioned requirements cause \"works on my machine\" failures.) \\[HIGH]\n- Software prerequisites **SHOULD** specify a supported range when known (e.g., \"Node.js 20 or later LTS\", \"Python 3.10+\"). (Why: ranges tell readers whether their existing installation works.)\n- You **MUST NOT** use vague terms like \"latest\" or \"recent version\". (Why: \"latest\" changes over time and provides no actionable information.) \\[HIGH]\n\n### 2.4 Links in Prerequisites\n\n- Each software prerequisite **MUST** link to an official download or installation page, not to the project homepage or documentation root. (Why: readers need to act, not browse; download pages are actionable.) \\[HIGH]\n- For tools with OS‑specific installers, you **MAY** link to a general downloads page that offers all variants.\n- For TON‑ecosystem tools documented in these docs, link to the internal installation guide if one exists.\n\n### 2.5 Prerequisite examples\n\nGood:\n\n```text\nPrerequisites:\n- [Node.js](https://nodejs.org/en/download/) 20 or later LTS\n- A funded testnet wallet (get testnet TON from the [faucet](https://t.me/testgiver_ton_bot))\n- An RPC endpoint — use a public endpoint or get one from [TON Center](https://toncenter.com/)\n```\n\nBad:\n\n```text\nPrerequisites:\n- A computer with internet access  ← obvious\n- Node.js  ← no version, no link\n- Install the TON SDK  ← installed in the guide, not a prerequisite\n- Familiarity with JavaScript  ← skill, not a prerequisite\n- Read the [wallets overview](/wallets)  ← background reading, not a prerequisite\n```\n\n### 2.6 Audience and skill assumptions\n\nPages with advanced requirements **MUST** state them at the top in a separate Audience note, not in Prerequisites. (Why: separating \"what you need to have\" from \"what you need to know\" helps readers self‑select.)\n\nExample:\n\n```text\nAudience: Advanced. Assumes understanding of TVM exit codes and TL‑B schemas.\nSee: [TVM exit codes](/tvm/exit-codes), [TL‑B overview](/data-formats/tlb).\n```\n\nInclusive/global readers. Use plain, international English; avoid idioms and culture‑specific references. Prefer neutral, inclusive terms (e.g., allowlist/denylist). (Why: idioms and local metaphors confuse non‑native readers; inclusive terms are more precise and avoid unintended exclusion.)\n\n## 3. Documentation framework (content types)\n\nRule. Each page **MUST** be one of the following: Step by step, How‑to guide, Explanation, or Reference. Types **MUST NOT** be mixed on a single page. The chosen type **MUST** be clear from the title and content. (Why: single‑purpose pages are easier to find and follow; mixing types blurs intent and causes duplication.)\n\nSmall, clearly marked asides (e.g., a 1–2‑step “Verify” box in an Explanation) **MAY** appear when they aid comprehension; the page’s primary type remains unchanged. (Why: tiny, labeled asides help understanding without turning a concept page into a task page.)\n\n### 3.1 What each type means (and looks like)\n\n- Step by step (first success). Single happy path for newcomers. Hand‑holding is **RECOMMENDED**. (Why: one clear path gets novices to a working result quickly; branching early increases drop‑off.)\n  Title style: “Deploy a counter contract on testnet”. (Why: action‑oriented titles set expectations and help search/TOC scanning.)\n  Sections (suggested): Objective → Prerequisites → Steps → Verify → Troubleshoot → Next steps. Keep Next steps minimal (1–3 essential links) or omit when the path is linear. **SHOULD** avoid theory beyond two short bullets; link to an Explanation page. (Why: predictable structure reduces cognitive load; keeping theory brief prevents blocking progress.)\n\n- How‑to guide (goal‑oriented procedure). A recipe to achieve a specific outcome. **MUST** be procedural and concise. (Why: readers come for a recipe; extra narrative slows execution and invites errors.)\n  Title style: “How to mint a jetton with the CLI”. (Why: the “How to …” pattern matches search intent and signals page type while staying specific.)\n  Rule: **MUST NOT** embed long background; link to concepts as needed. (Why: avoids duplication and keeps the guide focused; background stays current in one canonical place.)\n\n- Explanation (concepts/why). Background, architecture, trade‑offs. **SHOULD** avoid step lists and commands. (Why: separating “why” from “how” improves comprehension and prevents pages from doing two jobs badly.)\n  Title style: “Account model and messages in TON”. (Why: noun‑based titles signal conceptual content and improve browseability.)\n\n- Reference (complete, factual). Exhaustive specs for APIs/CLI/SDK/types/errors. Non‑narrative tables and exact semantics. (Why: factual, uniform entries are scannable and machine‑linkable; narrative slows lookups.)\n  Title style: “`tvm.runvm` — interface and exit codes”. (Why: placing the exact identifier in the title improves search and deep linking.)\n  Rule: **MUST** be precise, consistent, and anchor‑linkable. (Why: deep anchors let guides link directly; precision prevents support churn and conflicting copies.)\n\n## 4. Voice and tone\n\nObjective. Sound like a helpful expert: professional, precise, and approachable. Use the same voice across all pages. (Why: a consistent, expert tone builds trust and reduces cognitive load; readers know what to expect across the site.)\n\nRules (binding).\n\n- Use present tense, active voice, and the imperative mood. Write steps as commands (e.g., “Run the validator.”), not future tense or passive voice. Avoid addressing the reader with “you”. (Why: imperative, active phrasing makes the action clear without personal address and reduces ambiguity in steps.)\n- Be neutral and inclusive. Avoid slang, idioms, culture‑specific jokes, or hype. (Why: neutral language is easier for non‑native readers and translators, and avoids alienating parts of the audience.)\n- **MUST NOT** use filler or patronizing words: simply, just, obviously, clearly, please note. Replace with exact instructions (Why: filler wastes time and can sound condescending; precise verbs tell the reader exactly what to do.)\n- Emojis in prose and headings **MUST NOT** appear. Use clear text or an `<Aside>` when emphasis is needed. (Why: emojis are ambiguous, distract from procedures, and do not localize reliably.)\n- Emojis in code/command blocks **MAY** appear only when they are part of runnable code or a literal command/output string. Do not add emojis for decoration; the snippet **MUST** remain copy‑pasteable and executable as shown. If quoting a UI/log message that contains an emoji, keep it verbatim inside quotes. (Why: runnable examples take precedence; avoiding decorative emojis preserves clarity and execution.)\n- Emojis in compact tables **MAY** be used sparingly as visual indicators only when they follow a widely understood convention (for example, `✅` / `❌` for supported/not supported, or `★` to mark a recommended option) and **MUST** be paired with a text label in the same cell or a descriptive header (e.g., “Supported — Yes/No”). Do not rely on an emoji alone to convey meaning, and **MUST NOT** use decorative or non‑standard pictograms (for example, a play triangle to indicate videos). (Why: paired, conventional icons preserve clarity for screen readers, localization, and cases where emojis don’t render.)\n- Even where emojis are technically allowed (code/output or compact tables), they **SHOULD** be rare and **MUST** have a clear purpose. If the same meaning is clear without the emoji, remove it. (Why: conventional text remains clearer for global readers and translators.)\n- Use plain terms over legalese/Latinisms. “Use” not “utilize”; “before” not “prior to.” (Why: common words improve comprehension and reduce rereads; they are also translated more consistently.)\n- Avoid first‑person pronouns (“we”, “I”, “our”). When an organization, product, or service is the actor, use its proper name (e.g., “Tonkeeper”, “TON”) or a neutral noun (“the node”, “the SDK”). Prefer imperative instructions without “you”. See [§5.8](#58-dont-get-personal) and [§5.10](#510-pronouns-and-person-references). (Why: neutral, explicit actors read cleanly and translate reliably.)\n\nMarketing and promotional language (ban).\n\n- You **MUST NOT** use marketing‑style language anywhere in technical content, including titles, headings, steps, tables, references, and callouts. This includes: \\[HIGH]\n\n  - Superlatives and hype: \"blazingly fast\", \"revolutionary\", \"world‑class\", \"seamless\", \"best‑in‑class\", \"powerful\", \"cutting‑edge\".\n  - Vague positive adjectives: \"reliable\", \"robust\", \"essential\", \"elegant\", \"intuitive\", \"flexible\", \"comprehensive\", \"scalable\" (when used without measurable criteria).\n  - Dramatic or emotional framing: \"elusive\", \"challenging\", \"painful\", \"frustrating\", \"nightmare\", \"perfectly\", \"beautifully\". Technical writing states facts, not feelings.\n  - Intensity words that exaggerate: \"instantly\", \"immediately\" (unless literally true), \"extremely\", \"incredibly\", \"massive\", \"huge\" (for non‑quantified values).\n  - Storytelling openers: \"Imagine…\", \"Picture this…\", \"Have you ever…\", \"What if…\". Start with the task or fact instead.\n\n  (Why: hype and drama erode trust, slow scanning, obscure required actions, and age poorly.)\n\n- Replace subjective claims with measurable facts (numbers, constraints, conditions) or remove them entirely. If a claim cannot be tested or measured, delete it. (Why: facts enable correct implementation and reproducible results.) \\[HIGH]\n\n- When describing benefits, state **what** happens and **under what conditions**, not how it feels. (Why: readers need actionable information, not emotional appeals.)\n\n  - Bad: \"This approach provides a robust and reliable solution.\"\n  - Good: \"This approach retries failed requests up to three times with exponential backoff.\"\n  - Bad: \"Tests catch issues instantly.\"\n  - Good: \"Tests run in under 2 seconds and fail on the first assertion violation.\"\n\nMicro‑examples.\n\n- Bad: “We’ll just quickly configure the node; it’s super easy!”\n  Good: “Configure the node.”\n- Bad: “Let’s go ahead and utilize the script.”\n  Good: “Run the script.”\n- Bad: “Obviously, the transaction fails if the fee is low.”\n  Good: “The transaction fails if the fee is too low.”\n\n## 5. Grammar and usage\n\nObjective. Make sentences easy to parse on first read. (Why: clear, low‑friction sentences reduce rereads and mistakes during implementation.)\n\n### 5.1 Voice, tense, and person\n\n- You **MUST** use active voice by default. Passive voice **MAY** be used only when the actor is unknown or irrelevant. (Why: active voice makes who does what explicit; passive hides responsibility and confuses steps.)\n\n  - Good: “The validator stops if the config is invalid.”\n  - Bad: “The validator is stopped if the config is invalid.”\n- You **MUST** use the present tense for general behavior and instructions; the future tense **SHOULD** be reserved for time‑dependent statements. (Why: present tense reads simpler and matches how‑to steps; future tense adds unnecessary words and ambiguity.)\n\n  - Good: “The API returns JSON.”\n  - Bad: “The API will return JSON.”\n- Prefer imperative instructions without addressing the reader (“you”). Avoid first‑person pronouns (“we”, “I”, “our”); when an organization, product, or service is the actor, use its proper name (e.g., “TON Center”, “TON”). See [§5.8](#58-dont-get-personal) and [§5.10](#510-pronouns-and-person-references). (Why: imperative, neutral phrasing keeps actors clear without personal address.)\n\n### 5.2 Plain, precise wording\n\n- You **SHOULD** prefer common words over legalese or Latinisms. (Why: familiar words are understood faster and translated more reliably.)\n\n  - Use “use,” not “utilize.” Use “before,” not “prior to.”\n- Hedging and filler **MUST NOT** appear: simply, just, obviously, clearly, please note. Replace with exact actions or facts. (Why: filler wastes time and can sound condescending; specifics tell readers exactly what to do.)\n\n### 5.3 Acronyms and terms\n\n- On first mention, you **MUST** spell out the term and follow with the acronym in parentheses. Use the acronym thereafter. (Why: defines terms once and keeps later text concise.)\n\n  - Example: “The Open Network (TON)…”\n- Project terminology **MUST** follow the term bank/glossary (see [§13](#13-terminology-and-naming)). Avoid introducing synonyms for the same concept. (Why: one canonical term prevents confusion and search/indexing issues.)\n\n### 5.4 Audience calibration\n\n- Assume developers are new to blockchain (but experienced in software). **MUST NOT** re‑teach generic developer skills unless a TON‑specific nuance requires it (see [§2](#2-audience-and-assumptions)). Provide concise prerequisites when needed. (Why: focusing on TON reduces noise and keeps pages shorter and more relevant.)\n\n### 5.5 Global and inclusive language\n\n- You **MUST** avoid idioms, cultural references, and biased terms. Prefer neutral alternatives (e.g., allowlist/denylist). Use people‑neutral wording and accessible examples. (Why: idioms and bias exclude readers and harm translation; neutral wording is clearer for everyone.)\n\n### 5.6 Spelling and contractions\n\n- Spelling **MUST** follow American English (e.g., color, analyze). (Why: a single spelling standard prevents mixed variants and review churn.)\n- Contractions (don’t, can’t) **MAY** be used when they improve flow and do not reduce clarity. (Why: natural phrasing is easier to read as long as the meaning stays clear.)\n\n### 5.7 Avoid unfinished work\n\nArticles **MUST NOT** have any TODO, mentions of the work on the article to be done in future, itemized or text plans on its continuation, unfinished sections (headers without any text afterwards). The only exception is use of the `<Stub>` component to tell the whole page is not finished yet. \\[HIGH]\n\n### 5.8 Don't get personal\n\nArticles **MUST NOT** use pronouns \"you\", \"your\" to refer to a reader, and **MUST NOT** use pronouns \"we\", \"I\", \"our\" to refer to an author. (Why: documentation must only describe facts; it knows no facts about readers; most facts about writers are off-topic). \\[HIGH]\n\n### 5.9 Avoid tautology, pleonasm, throat‑clearing, and circular references\n\nObjective. Remove wordy redundancies and self‑referential boilerplate so the reader gets the signal only. (Why: cutting redundancy speeds reading and reduces confusion.)\n\n#### Rules (normative)\n\n- You **MUST** remove tautologies/pleonasms (duplicate meaning in different words). (Why: redundant pairs add length without adding meaning.)\n\n  - Bad: “End result” → Good: “result”\n  - Bad: “Advance planning” → Good: “planning”\n  - Bad: “Free gift” → Good: “gift”\n\n- You **MUST NOT** use throat‑clearing/circular openers that describe the doc instead of delivering value. (Why: readers come to act; meta‑introductions delay the task.) \\[HIGH]\n\n  - Bad: “In this section, we will discuss how to…”, “This document aims to explain…”\n  - Good: “Deploy a validator on testnet.” (start with the action)\n\n- You **SHOULD** collapse wordy boilerplate into precise verbs. (Why: shorter, direct phrasing is faster to parse.)\n\n  - Bad: “In order to” → Good: “To”\n  - Bad: “For the purpose of” → Good: “To”\n  - Bad: “Due to the fact that” → Good: “Because”\n\n- You **MUST** avoid doublets/triplets (pairs that mean the same thing). (Why: repeating the same idea signals uncertainty and wastes space.)\n\n  - Bad: “each and every”, “basic fundamentals”, “final outcome”, “past history”, “future plans going forward”, “merge together”, “close proximity”, “completely eliminate”\n\n- You **MUST** avoid tautological logic and circular definitions. (Why: circular text doesn’t explain behavior and blocks understanding.)\n\n  - Bad: “A jetton is a jetton if it conforms to the jetton standard.”\n  - Good: “A jetton is a fungible token on TON defined by the Jetton standard, which specifies message formats for mint/transfer/burn.”\n\n- You **SHOULD** replace hedges and intensifiers with facts. (Why: intensity words add emotion, not information; facts reduce ambiguity.) \\[HIGH]\n\n  - Avoid: “basically”, “essentially”, “really”, “very”, “actually”, “literally” (unless literal).\n  - If precision matters, give a number, constraint, or example instead.\n\n- You **MUST NOT** use and/or. (Why: it is ambiguous; readers cannot tell if both are allowed or required.)\n\n  - Write: “A, B, or both” or “A or B” (choose one).\n\n- You **SHOULD NOT** use etc. in procedures or lists. (Why: open‑ended lists leave readers unsure what is required.)\n\n  - Either complete the list or write “for example” and stop.\n\n- You **MUST** avoid “as mentioned above/below”; link to the exact anchor instead (see [§12](#12-links-and-cross-references)). (Why: relative references break when pages change; links stay accurate.)\n\n- You **SHOULD** simplify “whether or not” → “whether”; “the reason is because” → “because”; “not uncommon” → “common/often.” (Why: simpler forms are clearer and shorter.)\n\nSee also: [Appendix B](#b-banned-and-preferred-terms) lists additional banned intensifiers and tone words.\n\n#### Before/after micro‑examples\n\n- Throat‑clearing\n\n  - Before: “In this guide, we will show you how to configure a validator.”\n  - After: “Configure a validator.”\n\n- Tautology\n\n  - Before: “The final outcome of the deployment process…”\n  - After: “The result of the deployment…”\n\n- Wordy boilerplate\n\n  - Before: “In order to reduce fees, you need to…”\n  - After: “To reduce fees, …”\n\n- Hedge + intensifier\n\n  - Before: “It’s basically very important to verify the address.”\n  - After: “Verify the address.”\n\n- Circular reference\n\n  - Before: “Sharding improves scalability because it shards the chain.”\n  - After: “Sharding splits the chain into parallel shards that process transactions concurrently, increasing throughput.”\n\n### 5.10 Pronouns and person references\n\n- You **MUST** use gender‑neutral singular “they/them/their” when referring to an unspecified or generic person. **MUST NOT** use gendered or split forms such as “he”, “she”, “he/she”, “s/he”, or “(s)he” for generic subjects. \\[HIGH] (Why: singular “they” is inclusive, concise, and avoids awkward constructions.)\n\n- Prefer imperative instructions or role nouns to avoid pronouns when possible (e.g., “Deploy the contract.” or “The operator updates the config.”). (Why: direct phrasing is clearer and reduces ambiguity.)\n\n- When referring to a named individual who has stated pronouns, use that person’s pronouns; if unknown or irrelevant, default to “they”. (Why: respect individuals while keeping language inclusive.)\n\n- Do **NOT** anthropomorphize software or networks with gendered pronouns. Use neutral nouns or “it” (e.g., “the node restarts”, “it fails to start”). (Why: avoids confusion and maintains technical tone.)\n\n- For organizations, products, and services, use the proper name (e.g., “TON”, “Tonkeeper”) or the neutral “it”; do not use “we/I/our” in documentation. (Why: consistent, neutral references read cleanly and translate reliably.)\n\n### 5.11 Parentheses\n\n- Parentheses **MAY** be used for short clarifications and abbreviation expansions (for example, “The Open Network (TON)”) but **SHOULD NOT** be used for extended side remarks. (Why: side remarks buried in parentheses are easy to miss and hard to translate.)\n\n- When a parenthetical includes an extra idea, condition, or step, split the sentence into two sentences or move the extra idea into its own sentence or list item instead of nesting it in parentheses. (Why: one idea per sentence is easier to parse and localize.)\n\n- Where a parenthetical is necessary for precision, keep it short and avoid chaining more than one set of parentheses in the same sentence. (Why: multiple nested asides make sentences hard to read.)\n\n## 6. Punctuation and mechanics\n\nObjective. Remove ambiguity and increase scan speed with consistent mechanics. (Why: predictable punctuation choices make sentences easier to parse and reduce misreads.)\n\n### 6.1 Commas, colons, semicolons\n\n- The Oxford (serial) comma **MUST** be used in lists of three or more items: “nodes, wallets, and explorers.” (Why: prevents ambiguity about whether the last two items are grouped.)\n- Comma splices **MUST NOT** occur. If two clauses can stand alone, use a period or a coordinating conjunction. (Why: run‑on sentences are hard to scan; separating clauses improves clarity.)\n\n  - Bad: “The node restarts, it begins syncing.”\n  - Good: “The node restarts. It then begins syncing.”\n- Colons **SHOULD** introduce lists or explanations after a complete clause. Semicolons **SHOULD** be rare. Prefer shorter sentences. (Why: correct colon use signals structure; semicolons slow scanning and can often be replaced by periods.)\n\n### 6.2 Quotation marks and emphasis\n\n- Quotation marks **MUST** be used only for actual quotations or literal UI text/messages, not for emphasis. (Why: quotes indicate exact strings; using them for emphasis misleads readers and translators.)\n\n  - Good: The error message “Account not found” appears.\n  - Bad: The “validator” node… (do not quote terms)\n\n- House rule — quoting style: Use the international style with American spelling. Quotation punctuation **MUST** remain outside closing quotes unless it is part of the quoted text. This differs from American book style; keep it consistent. (Why: keeps code‑adjacent strings accurate and avoids adding punctuation that isn’t part of the literal.) \\[HIGH]\n\n- Use double quotation marks for log/error strings and other literal UI text when quoting it as text; place punctuation outside unless it is part of the string. (Why: quotes remain the convention for messages/text and keep literals copyable.)\n\n- This rule applies to quoted UI/log/error strings only; it does not apply to code spans or headings. (Why: code spans and headings have their own styling rules.)\n\n- Log messages and error strings **MUST** appear verbatim in quotation marks; **MUST NOT** add emphasis or change casing/punctuation. (Why: exact copying/grepping depends on matching strings.) \\[HIGH]\n\n- When referencing interactive controls or keyboard keys that the reader should click or press, you **MUST** use `<kbd>Label</kbd>` for the control or key name. You **MUST NOT** use quotation marks, bold, or italics to style controls in instructions. (Why: `<kbd>` is designed for controls/keys and keeps actions easy to scan and copy.)\n\n  - Good: Click `<kbd>Settings</kbd>`, then select `<kbd>Network</kbd>`.\n  - Bad: Click “Settings” or **Settings**.\n\n- UI or menu labels that appear in screenshots or descriptive text but are not being presented as actions **MAY** be written in quotes. Avoid mixing `<kbd>` and quoted labels arbitrarily; prefer one style consistently within a page/section. For quoted UI strings, follow the house quoting style above. Punctuation follows normal sentence rules outside `<kbd>`. (Why: consistent styling keeps text readable and copyable.)\n\n- Error codes/identifiers **MUST** use code formatting: `ERR_FEE_TOO_LOW`, `EADDRINUSE`, `ENOENT`. (Why: code styling distinguishes tokens from prose and aids scanning and copy/paste.)\n\n- When paraphrasing behavior, you **MUST NOT** alter message semantics; label paraphrases clearly and avoid quotation marks. (Why: altered wording leads to mismatches during troubleshooting.)\n\n#### Emphasis (bold and italics)\n\n- Bold and italics **SHOULD** be used sparingly in body text. Prefer structure (headings, lists), precise wording, or an admonition over visual emphasis. (Why: heavy emphasis reduces scan speed and harms raw‑Markdown readability.)\n\n##### Bold\n\n- Bold **SHOULD** mark scan points: a skimming reader should be able to bounce between bolded words and still understand the key actions or constraints in a section. (Why: using bold as a scan path keeps pages easy to scan.)\n\n- Use bold for a few critical words in a heading or paragraph, not whole sentences. If the paragraph still communicates the same information when bold is removed, prefer plain text and drop the bold. (Why: unnecessary bold increases noise without adding meaning.)\n\n- You **MUST NOT** bold entire sentences, paragraphs, or whole list items. If a label is needed, use a heading or an appropriate callout instead. (Why: large bold blocks create visual noise and duplicate heading semantics.) \\[HIGH]\n\n- You **MUST NOT** use bold to style tokens, flags, filenames, or UI/log messages; use code font for tokens, quotation marks for log/error strings and UI text, and `<kbd>` for UI/menu labels and key names. (Why: consistent, literal styling keeps examples copy‑pasteable, searchable, and accessible.) \\[HIGH]\n\n- Within a paragraph, you **SHOULD NOT** use more than one short bold span (≤ 3 words). Reserve it for rare emphasis that clarifies meaning, not for decoration. (Why: limiting emphasis keeps true highlights noticeable.)\n\n##### Italics\n\n- Italics **MAY** be used for first‑mention term emphasis or titles of publications, books, papers, or standards. Avoid using italics for recurring emphasis in procedures. (Why: minimal, conventional italics aid comprehension.)\n\n- When introducing an important concept on a concept or explanation page and a glossary link is not attached, you **MAY** italicize the first meaningful mention to signal definition, then stop italicizing later mentions. (Why: one highlighted introduction is enough to draw attention without cluttering the scan path.)\n\n- Use italics for subtle emphasis that matters in sentence context but should not become a scan target. Use bold when the reader should find a word while scanning quickly. (Why: separating roles for bold and italics keeps both predictable.)\n\n- Link text **MUST NOT** be styled with bold or italics. Do not wrap links in emphasis (for example, `**[Foo](/foo)**`, `_ [Foo](/foo)_`) and do not put bold or italic markup inside the link label. When the link label is a code identifier, use inline code as the label (for example, ``[`foo_bar`](/ref/foo_bar)``). (Why: links are already visually distinct; extra emphasis adds noise and makes scanning harder.) \\[HIGH]\n\n### 6.3 Code styling\n\n- Code, filenames, paths, API endpoints, flags, and literals **MUST** use code formatting (inline backticks or fenced blocks). **MUST NOT** add punctuation inside code that isn’t part of the code. (Why: visual separation prevents misreading and keeps examples copy‑pasteable without edits.) \\[HIGH]\n\n### 6.4 Lists\n\n- Use numbered lists for procedures and bulleted lists for unordered sets. If list items are full sentences, **SHOULD** end with periods; otherwise, omit terminal punctuation consistently. (Why: matching list type to purpose improves comprehension; consistent punctuation keeps visual noise low.)\n\n- Unordered list markers **MUST** be `-` (hyphen). **MUST NOT** use `*` or `+`. (Why: a single marker keeps diffs cleaner and avoids mixed styles.)\n\n- Ordered lists **MUST** use `1.` for every item; let the MDX parser auto‑number in the rendered output. (Why: auto‑numbering prevents renumber churn when inserting/reordering steps.)\n\n### 6.5 Thematic breaks\n\n- Thematic breaks / horizontal rules (`---`, `***`, `___`, or HTML `<hr>`) **MUST NOT** be used. Use headings, whitespace, or an admonition to separate sections. (Why: horizontal rules fragment structure, reduce screen‑reader/navigation cues, and add noise in raw Markdown.)\n- You **MUST NOT** simulate separators with repeated characters or ASCII art (e.g., `=====`, `-----`). (Why: pseudo‑rules create the same problems and look like code noise.)\n- This rule does not apply to YAML frontmatter delimiters `---` at the top of a file. Frontmatter **MAY** use `---` as required by the site generator. (Why: frontmatter is metadata, not content.)\n\n### 6.6 Blockquotes\n\n- Blockquotes **MUST** be reserved for literal quotations from a source (another page in these docs or an external source). Include attribution inline or in the sentence introducing the quote; internal quotes **SHOULD** link to the exact anchor; external quotes **SHOULD** link to the canonical HTTPS source. (Why: clear attribution preserves trust and lets readers verify context.)\n- Blockquotes **MUST NOT** be used for callouts/admonitions, warnings, tips, examples, emphasis, or general instructions. Use the `<Aside>` component for callouts (see [§11.2](#112-how-to-write-the-callout), [Appendix A](#a-admonition-levels-and-usage)) and headings/lists for structure. (Why: misusing blockquotes harms structure, accessibility, and localization.)\n- Visual callouts (Note/Tip/Caution/Warning) **MUST** use only the `<Aside>` component. The only supported `type` values are `\"note\"`, `\"tip\"`, `\"caution\"`, and `\"danger\"`; do **NOT** use other components or type values. \\[HIGH] (Why: a single component and fixed types keep rendering, accessibility, and localization consistent.)\n- Short phrases or UI/log strings **SHOULD** use inline quotation marks instead of a blockquote. Tokens and identifiers **MUST** use code font, not blockquotes. (Why: inline quotes and code font are more precise and copy‑friendly.)\n- Keep quotations brief (prefer ≤ two sentences or one short paragraph). For longer material, summarize in your own words and link to the source. (Why: long quotes impede scanning and duplicate external content.)\n- Nested blockquotes **MUST NOT** be used. Quoted code or output **SHOULD** appear in fenced code blocks with attribution above the block, not inside a blockquote. (Why: fenced blocks remain copy‑pasteable and render consistently.)\n\n## 7. Headings and titles\n\nObjective. Make navigation obvious and sections self‑explanatory. (Why: clear, self‑describing headings reduce misclicks, speed scanning, and make deep links understandable out of context.)\n\n### 7.1 Case and form\n\n- Site‑managed H1. Pages **MUST NOT** include an in‑body H1. The page title is provided by the site generator/frontmatter. The first visible heading in the page content **MUST** be an H2. (Why: the template renders the title; omitting an in‑body H1 avoids duplicate titles and keeps a consistent heading hierarchy.)\n\n- In MDX content, you **MUST NOT** write `# ` (H1), `<h1>`, or use components that render an H1. Start headings at `##` (H2). (Why: syntax‑level bans prevent accidental H1s in raw Markdown/MDX and keep navigation consistent.)\n\n- Imported snippets/partials **MUST NOT** emit H1 headings; they **MUST** begin at H2 or lower within the host page’s hierarchy. (Why: embedded content inherits the page’s structure and must not reset the heading level.)\n\n- All headings **MUST** use sentence case (capitalize only the first word and proper nouns). (Why: sentence case is easier to read, avoids random capitalization, and localizes more reliably.) \\[HIGH]\n\n- Task (procedure) headings **MUST** start with an imperative verb; concept headings **SHOULD** be noun phrases. (Why: imperatives signal actions the reader takes; noun phrases signal explanatory content, improving navigation and search relevance.)\n\n  - Task: “Deploy a validator.”\n  - Concept: “Validator architecture.”\n\n- How‑to titles. For the How‑to doc type, the page title **MUST** follow “How to X”. Internal section headings (H2/H3) remain imperative. (Why: the pattern clarifies page type and improves discoverability without changing procedural heading style.)\n\n### 7.2 Gerunds and labels\n\n- For task/procedure headings (H2/H3), gerunds (e.g., “Creating…”, “Configuring…”) **SHOULD NOT** be used. Prefer imperative verbs. (Why: gerunds are vague about action vs. state; imperatives are clearer and translate better.)\n- Concept headings **MAY** use concise noun phrases (e.g., “Naming”, “Spelling”, “Versioning”). (Why: short labels act as clear section tags and improve scan speed.)\n- Fixed labels like Troubleshooting, Changelog, or FAQ are acceptable. Imperatives read cleaner and translate better in procedural sections. (Why: common labels match user expectations and TOC patterns; imperatives keep steps actionable.)\n- House default: use “Troubleshoot” by default; “Troubleshooting” is acceptable when aligning with established ecosystem conventions. (Why: one default reduces variance; allowing the alternate keeps external consistency where needed.)\n\n### 7.3 Uniqueness and linkability\n\n- Headings **MUST** be unique at the same nesting level within a page and **MUST** make sense out of context (as TOC/sidebar links). Avoid repeated “Introduction” sections; prefer specific names. (Why: unique, descriptive headings prevent anchor collisions and make links meaningful in search and sharing.)\n\n### 7.4 Formatting restrictions\n\n- Headings **MUST NOT** contain styling other than text: no bold, italics, `code`, quotes, or ALL CAPS (acronyms permitted). Keep headings clean; use formatting in body text only. (Why: extra styling harms scannability, clutters the TOC, and causes inconsistent rendering.)\n- Exceptions:\n\n  - Reference pages only: Headings **MAY** include code font for identifiers (API names, flags, error codes), e.g., `tvm.runvm` — interface and exit codes. (Why: monospaced identifiers preserve exact casing and aid search/copy.)\n  - When the heading contains a literal UI/log/error message, quotation marks **MAY** be included (e.g., Fix “Account not found”). (Why: quoting exact strings shows what to grep or match without altering punctuation.)\n\n### 7.5 Practical length norms\n\n- Headings **SHOULD** be concise. As a norm, Page title (site/frontmatter) ≤ \\~60 characters; H2/H3 ≤ \\~70 characters. Exceed only for clarity. (Why: concise titles fit sidebars and search results without truncation; brevity improves scanning.)\n\nExamples (good):\n\n- “Run a validator on testnet” (H2, imperative)\n- “Account model and messages in TON” (H2, concept)\n  Examples (bad):\n- “Running and configuring the validator” (gerunds)\n- “How the `validator` works” (code in heading)\n\n## 8. Readability and scannability\n\nObjective. Keep text fast to read and effortless to scan. (Why: quick comprehension reduces rereads and mistakes during implementation.)\n\n### 8.1 Paragraphs and sentences\n\n- One idea per paragraph. Paragraphs **SHOULD** be ≤ 5 sentences; single‑sentence paragraphs are acceptable for emphasis. These are recommended norms, not hard caps—exceed only when clarity requires it. (Why: tight, focused paragraphs are easier to scan; short norms keep pages consistent without blocking necessary detail.)\n- Each sentence **SHOULD** convey one main idea. If a sentence starts to describe two distinct actions or conditions, split it into two sentences or convert the extra actions into a list. (Why: one‑idea sentences are easier to scan and translate; lists make multi‑step actions obvious.)\n- Sentences **SHOULD** average 15–20 words. Long, multi‑clause sentences **SHOULD** be split. Front‑load key points. (Why: mid‑length sentences reduce cognitive load; splitting prevents misreads; leading with the main point speeds understanding.)\n\n### 8.2 Structure for scanning\n\n- Use subheadings, lists, and tables to break up dense text. Provide breathing room around code, tables, and images (blank lines before/after blocks). (Why: chunking and whitespace make structure visible and stop content from blending together.)\n- Highlight critical notes with admonitions (Note/Tip/Important/Caution/Warning) sparingly so they retain impact. (Why: overuse causes readers to ignore callouts; sparing use signals importance.)\n- This guidance does not limit required safety callouts in [§11](#11-safety-critical-content-blockchain-specific); when in doubt, include the safety callout. (Why: preventing harm overrides brevity and visual economy.)\n\n### 8.3 Micro‑examples\n\nBefore (hard to scan):\n“After deploying, if fees are misconfigured, the transaction might fail and the node logs a warning; you can retry after adjusting the config, but it’s better to verify the fee policy first because otherwise the wallet may reject the message.”\n\nAfter (scannable):\n\n- Verify fees before deploying.\n- If the transaction fails with `FEE_TOO_LOW`:\n\n  1. Update the fee policy.\n  1. Retry the deployment.\n- The node logs a warning on failure.\n\n## 9. Recommended page structures (by type)\n\nObjective. Make pages predictable without forbidding alternatives. (Why: predictable shapes reduce scanning time and help readers know what to expect.)\nRule. The patterns below are **RECOMMENDED**. You **MAY** deviate when another structure improves clarity, but pages in the same section **SHOULD** be consistent. (Why: consistency within a section helps navigation and comparison; flexibility allows better fit for edge cases.)\n\n### 9.1 Step by step (first success)\n\nRecommended sections:\nObjective → Prerequisites → Steps (3–7) → Verify (expected output or result) → Troubleshoot (common errors) → Next steps. Keep Next steps minimal (1–3 essential links) or omit when the path is linear. (Why: this flow gets newcomers to a working result, confirms success, handles common failures, and points to what to do next.)\nNotes: Keep a single happy path; theory **SHOULD** be limited to ≤ two bullets and linked to an Explanation page. (Why: branching and long theory cause drop‑offs; brief links keep momentum while offering depth when needed.)\n\nExample outline (good):\n\n- Objective: “Deploy a counter contract on testnet.”\n- Prerequisites: Node.js 20+, TON SDK JS, funded testnet wallet, `<RPC_URL>`.\n- Steps: 1) Initialize project … 2) Compile … 3) Deploy …\n- Verify: “Expected output” block showing successful deployment.\n- Troubleshoot: `INSUFFICIENT_FUNDS`, `INVALID_WORKCHAIN` fixes.\n- Next steps: Link to contract upgrades guide.\n\n### 9.2 How‑to guides (goal‑oriented procedures)\n\nRecommended sections:\nGoal → Prerequisites → Steps → Result → Links to Reference (anchor each flag/param). (Why: the reader sees what they’re trying to achieve, what they need, how to do it, what outcome to expect, and where to look up details.)\nNotes: Do not embed long background; link to concepts instead. Keep each step a single action with sub‑bullets for options. (Why: separating theory prevents duplication and keeps the guide tight; one action per step reduces ambiguity and errors.)\n\n### 9.3 Explanations (concepts/why)\n\nRecommended sections:\nWhat/Why → Core concepts → Trade‑offs → Related topics. (Why: this order frames purpose first, then explains mechanics, then consequences, and finally directs to adjacent ideas.)\nNotes: Avoid command sequences. Use diagrams and short examples to illustrate concepts. (Why: commands distract from understanding; visuals and minimal examples clarify ideas without turning the page into a procedure.)\n\n### 9.4 Reference (complete, factual)\n\nRecommended sections:\nSummary → Parameters/Fields (tables) → Returns/Responses → Errors (codes, meanings) → Examples (minimal usage) → Optional See also (1–3 essential anchors). (Why: a uniform, tabular layout makes lookups fast and supports deep linking and automation.)\nNotes: Be exhaustive and anchor‑linkable; minimize narrative. Keep formats consistent across entries. (Why: completeness and anchors enable precise links from guides; minimal prose speeds lookup; consistency lets readers scan different entries the same way.)\n\n## 10. Code and command examples\n\nObjective. Ensure examples are precise, copy‑pasteable, and unambiguous. (Why: readers should be able to run examples without editing or guessing.)\n\n### 10.1 General rules\n\n- Examples **MUST** be copy‑pasteable. **MUST NOT** include shell prompts (`$`, `>`) in command blocks. (Why: prompts get copied accidentally and break commands.) \\[HIGH]\n- Command and expected output **MUST** be presented as separate fenced blocks. (Why: mixing them causes copy errors and makes results hard to recognize.) \\[HIGH]\n- Placeholders **MUST** use `<ANGLE_CASE>` (e.g., `<RPC_URL>`, `<LEDGER_DIR>`), and each placeholder **MUST** be defined on first use. (Why: a consistent, visible pattern prevents pasting unsafe hard‑coded values.) \\[HIGH]\n- Fenced code blocks **MUST** specify a language (` ```bash `, ` ```rust `, ` ```json `, …). (Why: language tags enable correct highlighting and tooling.)\n- Filenames shown in examples **MUST** be realistic and kebab‑case (e.g., `wallet-config.json`, not `MyConfig.json`). (Why: examples should model the conventions we require elsewhere.)\n- Long commands **MUST NOT** be hard‑wrapped. Prefer UI soft wrap. If a tool supports safe line continuation (e.g., `\\` in POSIX shells), continuation **MAY** be used and must be copy‑pasteable as shown. (Why: hard wraps break execution; soft wrap or continuations keep commands runnable.)\n- You **SHOULD** favor examples that run end‑to‑end on testnet by default. (Why: safer defaults reduce risk and support quick validation.)\n- Inside language code, placeholders **SHOULD** be neutral (e.g., `UPPER_SNAKE` inside strings or comments) when angle brackets would clash with language syntax; in commands and prose, placeholders **MUST** use `<ANGLE_CASE>`. (Why: avoids syntax errors in code while keeping a single placeholder style in prose/CLI.)\n- In runnable examples, configuration values and other parameters that the reader is expected to change **MUST** be collected in one clearly visible block near the top of the snippet. When the language allows top‑level declarations, this block **MUST** use top‑level constants instead of redefining values inside the entry function or helpers; when the language forbids top‑level declarations, group these parameters at the start of the entry function. (Why: collecting adjustable values in one visible place makes examples easier to understand and update.) \\[HIGH]\n\n### Error and log style\n\n- Quoted UI/log messages **MUST** appear verbatim in quotation marks. (Why: exact strings are searchable and prevent confusion.)\n- Error codes and identifiers **MUST** be rendered in code font (e.g., `ERR_FEE_TOO_LOW`). (Why: monospace distinguishes tokens and aids copy/paste.)\n- When summarizing behavior instead of quoting, **MUST NOT** change semantics and avoid using quotes; indicate that it is a summary. (Why: paraphrases should not be mistaken for literal messages and must stay accurate.)\n\nGood\n\n```bash\nton-node start --ledger <LEDGER_DIR> --network testnet\n```\n\nExpected output\n\n```text\nNode started. Workchain: 0  Shard: -1  Status: running\n```\n\nDefine placeholders (first use):\n`<LEDGER_DIR>` — path to the local ledger directory.\n`<RPC_URL>` — HTTPS endpoint of the TON RPC provider.\n\nBad\n\n```bash\n$ ton-node start --ledger /home/bob/ledger --network mainnet  # includes prompt, hard-coded values\n```\n\n### 10.2 Partial snippets\n\n- Partial snippets (focused excerpts) **MAY** be used when teaching a narrow concept, even if not runnable alone. (Why: small, targeted examples clarify one idea without setup noise.)\n- Partial snippets **MUST** be labeled clearly above the block: “Not runnable”. (Why: prevents readers from attempting to execute incomplete code.)\n- Partial snippets **SHOULD** link to a full runnable example or reference entry showing complete context. (Why: gives readers a path to working code.)\n\nNot runnable\n\n```rust\nlet to = Address::from_str(\"EQC_REPLACE_WITH_ADDRESS\").unwrap();\nlet amount = Coins::from_nano(1_000_000_000);\nlet body = build_transfer_body(to, amount);\n```\n\n### 10.3 Safety and secrets in code\n\n- Secrets (keys, mnemonics, API tokens) **MUST NOT** appear in examples. Use placeholders or test keys that are clearly invalid. (Why: prevents accidental leaks and unsafe copying.) \\[HIGH]\n- Commands that could cause loss of funds or data **MUST** be guarded by a Warning/Caution per [§11](#11-safety-critical-content-blockchain-specific) and **SHOULD** default to testnet. (Why: explicit risk labeling and safe defaults protect readers.) \\[HIGH]\n\n### 10.4 OS and language variants\n\n- When steps differ by OS or language, you **SHOULD** provide tabs or distinct subsections (e.g., Linux / macOS / Windows; JS / Python / Rust). (Why: separates platform differences so readers don’t mix instructions.)\n- If only one variant is provided, the page **MUST** state that limitation. (Why: sets expectations and avoids readers searching for missing variants.)\n\n### 10.5 Comments and omissions\n\n- Use language‑appropriate comments to mark omissions (`// …`); **MUST NOT** use literal ellipses that change syntax. (Why: literal ellipses can create invalid code.) \\[HIGH]\n- Explanatory comments in examples **MUST** appear on their own line immediately above the code they describe; **MUST NOT** use trailing end‑of‑line comments such as `foo(42); // sends a test message` in documentation snippets. (Why: stacked comment‑then‑code is easier to scan and keeps copy‑pasted lines clean.) \\[HIGH]\n- Exception: Fift and TVM assembly stack comments **MAY** appear as trailing end‑of‑line comments to show the stack state at that point (e.g., `1 2 + // 3`). This is idiomatic in stack‑based languages and aids comprehension. (Why: stack comments are a well‑established convention in Fift and TVM assembly; forcing them to a separate line would harm readability.)\n- Keep comments minimal and instructional; avoid commentary or humor. (Why: extraneous remarks distract from the task and age poorly.)\n\n## 11. Safety‑critical content (blockchain‑specific)\n\nObjective. Prevent reader harm when funds, keys, or validator/network state are involved. (Why: mistakes here can cause irreversible loss or outages.)\n\n### 11.1 When a safety callout is required\n\nA Caution or Warning **MUST** appear when a page or step: (Why: visible callouts make risk obvious before a reader runs a command.) \\[HIGH]\n\n- moves funds or changes fee/withdrawal behavior; (Why: users can lose money or block withdrawals.) \\[HIGH]\n\n- exposes, stores, or transmits private keys/mnemonics; (Why: leaked secrets allow account takeover and theft.) \\[HIGH]\n\n- modifies validator configuration, networking, or consensus‑affecting parameters; (Why: misconfiguration can halt or fork nodes and degrade the network.) \\[HIGH]\n\n- performs chain‑affecting operations (e.g., resharding, pruning, halting, replay). (Why: these actions can corrupt the state, reduce availability, or cause data loss.) \\[HIGH]\n\nIf page has many actions potentially requiring a safety callout, you **MAY** combine these into a page‑level safety summary plus short local callouts instead of repeating full details every time. (Why: a shared summary avoids repetition while still making risks visible.)\n\n### 11.2 How to write the callout\n\nA page that contains safety-critical actions **MUST** clearly communicate all of the following, either in a page‑level safety summary, in local callouts near each step, or in combination: (Why: readers need to know the risk, scope, recovery, and safe environment before proceeding.) \\[HIGH]\n\n1. Risk (what can go wrong), (Why: sets severity and helps decide whether to proceed.)\n1. Scope (what the command affects), (Why: clarifies blast radius—single node, wallet, or network.)\n1. Rollback/mitigation steps where feasible, and (Why: gives a path to recovery or damage control.)\n1. Environment label (testnet vs mainnet) with safer default instructions first. (Why: testnet reduces harm; explicit labels prevent accidental mainnet use.)\n\n- These elements describe the information the reader needs; they are **NOT** required as literal labels such as “Risk:” or “Scope:”. Safety callouts **SHOULD** read as concise, natural prose rather than templated checklists. (Why: natural language is easier to read and avoids robotic, placeholder‑style warnings.)\n\nCommon patterns:\n\n- Page‑level safety summary. Place a single `<Aside>` near the top of the guide that describes overall risk, scope, rollback/mitigation strategy, and testnet/mainnet expectations for the full set of commands. (Why: one visible summary prevents readers from missing critical context.)\n- Local step‑level warnings. Add short `<Aside>` elements next to each hazardous step that call out the specific risk or environment for that step and, when needed, refer back to the page‑level summary instead of repeating full details (for example, “See the safety note at the top of this page before running this on mainnet.”). (Why: local notes tie the warning to the exact action without duplicating the whole summary.)\n\nRendering (component) \\[HIGH]\n\n- Safety callouts **MUST** use the `<Aside>` component; **MUST NOT** use Markdown blockquotes (`>`) or headings to simulate warnings. (Why: a single component keeps appearance, accessibility, and behavior consistent.)\n- Mapping: use `type=\"caution\"` for Caution; use `type=\"danger\"` for Warning. Set an explicit `title` when needed (e.g., `title=\"Funds at risk\"`). (Why: consistent severity mapping aligns wording with visual severity.)\n- Allowed types: The only supported `<Aside>` `type` values are `\"note\"`, `\"tip\"`, `\"caution\"`, and `\"danger\"`. Do not use other values (e.g., `\"important\"`, `\"warning\"`). To display those labels, set `title` (e.g., `title=\"Important\"`) while keeping a supported `type`. (Why: keeping to the supported set ensures consistent rendering and avoids runtime fallbacks.)\n\nExample (MDX)\n\n````mdx\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside type=\"danger\" title=\"Funds at risk\">\n  Sending TON on mainnet is irreversible. Start with a small transfer on TON Testnet, then repeat on TON Mainnet only after checking the address and network carefully; there is no rollback on mainnet.\n\n  ```bash\n  jetton transfer --to <ADDR> --amount <AMOUNT> --network testnet\n  ```\n</Aside>\n````\n\n### 11.3 Safer defaults\n\n- Task pages **SHOULD** use testnet endpoints by default and mention the switch to mainnet explicitly. (Why: safe defaults prevent costly mistakes.)\n- Destructive flags (e.g., `--purge`, `--force`) **MUST** be opt‑in and accompanied by a callout. (Why: explicit opt‑in and warnings reduce accidental data loss.) \\[HIGH]\n\n### 11.4 Key handling and storage\n\n- Keys **MUST** be represented as placeholders or generated ephemeral testing artifacts. (Why: prevents real secrets from being copied into scripts or screenshots.) \\[HIGH]\n- In guides, prefer environment variables or keystores; never inline secrets. (Why: avoids persisting secrets in history, logs, or source control.) \\[HIGH]\n- Reference pages **MAY** document secure storage options but **MUST NOT** encourage unsafe patterns. (Why: guidance is helpful, but normalizing bad practices leads to leaks.) \\[HIGH]\n\n## 12. Links and cross‑references\n\nObjective. Reduce duplication and let readers jump straight to detail. (Why: direct links cut search time and prevent restating facts in multiple places.)\n\n### 12.1 Link text\n\n- Link text **MUST** be descriptive and indicate the destination. You **MUST NOT** use generic labels like \"click here\", \"here\", \"this\", \"this link\", \"this page\", or bare URLs as link text. \\[HIGH] (Why: meaningful text lets readers scan quickly to determine where a link leads; generic labels force readers to examine surrounding context.)\n\n- You **MUST NOT** use mechanics‑focused verbs like \"click\", \"tap\", \"follow\", or \"go to\" as part of link text. Focus on content, not interaction mechanics. \\[HIGH] (Why: drawing attention to the clicking action distracts from the content; not all users click — some tap, use keyboards, or use assistive technology.)\n\n- Link text **SHOULD** describe the destination, not the action of navigating. One effective technique: use the title or topic of the target page as the link text and integrate it into the sentence.\n\n  - Bad: `\"To learn about fees, click [here](/fees).\"`\n  - Bad: `\"Click [here](/fees) for fee information.\"`\n  - Bad: `\"[This page](/fees) explains fees.\"`\n  - Good: `\"The [fee structure](/fees) determines transaction costs.\"`\n  - Good: `\"Transaction costs depend on the [fee structure](/fees).\"`\n\n- When a link must stand alone (e.g., at the end of a sentence or after a colon), make the link text self‑explanatory:\n\n  - Bad: `\"For more details, see [here](/validator-setup).\"`\n  - Good: `\"For more details, see [Validator setup](/validator-setup).\"`\n  - Good: `\"Related guide: [Set up a validator](/validator-setup).\"`\n\n- Link labels **SHOULD** be plain text or inline code for identifiers (see [§6.2](#62-quotation-marks-and-emphasis) for emphasis restrictions on link text). (Why: unstyled labels keep links readable and avoid redundant visual emphasis.)\n\n- Standalone \"stub\" sentences whose only job is to say \"See …\" or \"Read here …\" followed by a link (for example, `[Read here](/standard/wallets/mnemonics) to learn more.` or `See [mnemonics](/standard/wallets/mnemonics) for more details.`) **MUST NOT** appear in running prose. Instead, attach the link to the relevant term or phrase in a normal sentence (for example, `The [mnemonics guide](/standard/wallets/mnemonics) explains why.`). (Why: inline links keep the text flowing and avoid postponing useful links to trailing meta‑sentences.) \\[HIGH]\n\n- Accessibility and SEO note: Screen readers often present links out of context (e.g., a list of all links on a page). Generic link text like \"here\" or \"click here\" becomes meaningless when read in isolation. Search engines also use link text to understand page relationships. Descriptive link text improves both accessibility and discoverability. (Why: links must make sense without surrounding prose.)\n\n### 12.2 What to link (and what not)\n\n- In a guide, the first useful mention of a flag, parameter, error code, or data type on the page **MUST** link to the canonical reference anchor. You **MAY** also link its first mention in other H2/H3 sections on long pages that are frequently deep‑linked or read out of order. (Why: readers see the spec at the moment they need it, even when entering mid‑page.) \\[HIGH]\n\n- This rule explicitly includes TVM exit codes (e.g., `-13`, `37`), send modes (e.g., `mode 64`, `mode 128`), reserve modes, and similar numeric constants that have documented meanings. These **MUST** be linked to their corresponding reference anchors on first mention, not left as bare code spans. (Why: numeric constants are opaque without context; links let readers understand them instantly.) \\[HIGH]\n\n- Within a single H2/H3 section, link only the first meaningful mention of an important term or reference target. When the same term appears in a different H2/H3 section, you **MAY** link its first mention again there. Avoid linking every occurrence inside one section; add a repeated link only when separated by many screens and it clearly helps the reader. (Why: per‑section first links help when deep‑linking to a subsection without turning the page into a link farm.)\n\n- Link concepts judiciously: if the reader is likely to wonder “what does that mean?”, link the term on its first useful mention in that H2/H3 section. Subsequent mentions in the same section **SHOULD** be plain text unless the gap is large and a repeated link clearly helps. (Why: section‑local first links help readers who land on a deep link without over‑linking common words.)\n\n- On the first useful mention of a core TON term on a page, you **SHOULD** link to the Glossary (Foundations → Glossary), unless the page itself defines it. On long pages, you **MAY** also link the first mention of that term in other H2/H3 sections, following the per‑section rules above. (Why: keeps definitions consistent and easy to find while still helping readers who enter mid‑page.)\n\n- Over‑linking common words is discouraged; link what is plausibly useful. (Why: excessive links slow reading and distract from the task.)\n\n- Guides **MUST NOT** duplicate reference tables; summarize and link instead. (Why: duplication drifts and creates conflicting sources of truth.)\n\n- Internal first. When both an internal TON Docs page and an external source exist, you **MUST** link the internal page by default (including instead of the TEPs repository). Exception: pages whose purpose is to document a standard contract/TEP **MAY** also link the corresponding TEP as the canonical spec. If no relevant internal page exists, linking to the external source is acceptable. (Why: internal pages are newcomer‑friendly; TEPs are normative but hard to parse for new readers.)\n\nExample (good)\n\nStart the node with `--threads` (see [validator flags → `--threads`](/ecosystem/nodes/overview#validator-node)) to increase parallelism.\n\n### 12.3 Link targets and format\n\n- Internal links **MUST** be root‑absolute and stable (start with `/`); anchors **MUST** resolve correctly. **MUST NOT** use relative segments like `./` or `../` in Markdown/MDX link URLs or HTML/JSX. (Why: files and folders move frequently; root‑absolute links remain correct across moves; relative segments are brittle and costly to maintain.) \\[HIGH]\n\n- Cross‑section links **SHOULD** deep‑link to the exact section or anchor instead of the page top. (Why: deep links land readers on the exact answer.)\n\n- A See also section **MAY** close a page with 1–3 essential links; prefer a linear path that needs none. (Why: minimal exits keep readers on task while still offering critical follow‑ups.)\n\n- When linking to the same internal target multiple times on a page, you **SHOULD** prefer reference‑style Markdown links so the URL appears once in a shared definition block. For example:\n\n  ```md\n  Use the [jetton wallet][jetton-wallet] contract where applicable; the [jetton wallet reference][jetton-wallet] describes all fields.\n\n  [jetton-wallet]: /standard/jettons/wallet\n  ```\n\n  This keeps body text readable and makes URL updates cheaper, while still requiring root‑absolute URLs in the reference definition. (Why: shared link definitions reduce visual noise and simplify maintenance.)\n\n### 12.4 Avoid circularity and drift\n\n- Each fact **MUST** have a single canonical home. If you need the same fact elsewhere, link to it. (Why: one source avoids conflicting copies and simplifies updates.)\n- **MUST NOT** link to outdated or superseded pages except when documenting historical behavior. (Why: stale links propagate errors and erode trust.) \\[HIGH]\n\n### 12.5 Images and media\n\n- Images **MUST** be embedded using the `<Image>` MDX component. Markdown image syntax `![...](...)` and raw `<img ...>` are **PROHIBITED**. (Why: the component provides dark‑theme control, consistent sizing/zoom, and stable rendering.) \\[HIGH]\n- Image sources **MUST** be root‑absolute and live under `/resources/images/` (for example, `<Image src=\"/resources/images/<GROUP>/<FILE>.png\" />`, where `<GROUP>` is the logical image category and `<FILE>` is the filename). **MUST NOT** use relative `src` such as `./` or `../`. (Why: content moves often; root‑absolute paths remain valid.) \\[HIGH]\n- Provide a `darkSrc` when contrast or readability differs in dark mode. Keep aspect ratios consistent across a page to avoid layout shift. (Why: visual stability improves reading flow.)\n- SVG note: if `src` points to an SVG and `darkSrc` is omitted, the dark‑theme image is auto‑inverted. Supply an explicit `darkSrc` when inversion is not desired. (Why: ensures accurate colors and legibility.)\n- Provide meaningful, non‑empty `alt` text for every image; `alt` **MUST NOT** be empty. (Why: screen readers rely on `alt` to convey image meaning; empty `alt` hides content from assistive tech.) \\[HIGH]\n- When using `<Image>`, prefer the `width`/`height` props for predictable layout; avoid arbitrary inline styling. (Why: predictable dimensions prevent layout shift and maintain consistency.)\n\n### 12.6 External references\n\nObjective. Use authoritative, stable sources and deep links; avoid volatile or non‑authoritative pages. (Why: reliable links reduce drift, link rot, and conflicting guidance.)\n\n- Authority order. You **MUST** prefer: (1) official project documentation/specs/standards (link internal TON Docs when available before external repos); (2) vendor documentation for tools used; (3) primary sources (RFCs, papers). Community wikis/blogs **MAY** be linked only when no official source exists and **MUST** be labeled as background. (Why: authoritative sources change less and carry clearer guarantees; internal docs are optimized for comprehension.)\n- Wikipedia and crowd‑edited sources. Wikipedia **MAY** be linked for general, well‑known non‑TON concepts when the link is informational and not supporting a requirement or API/behavior semantics. For normative claims or when precision matters, **MUST** link a spec or official docs (e.g., RFC 8032 for Ed25519). (Why: Wikipedia is useful for broad context; specs are stable for requirements.)\n- Q/A forums and social posts. Stack Overflow, Reddit, and personal blogs **MUST NOT** be used as normative references. They **MAY** appear as background in the Explanation pages when no official source exists. (Why: anecdotal content is volatile and easily outdated.)\n- TEPs specifics. Prefer the internal TON Docs page that explains a standard over linking directly to the TEPs repository. On pages that are themselves standards or reference docs (e.g., standard contracts), you **MAY** include a precise deep link to the corresponding TEP as the canonical spec. Avoid linking the repository root; link the exact TEP and section. (Why: TEPs are normative but difficult for newcomers; internal docs provide context while still letting experts reach the spec.)\n- Stable permalinks (situation‑aware). When linking to specific code/files/lines or exact doc sections where content must remain reproducible, you **SHOULD** use a versioned or permanent URL (e.g., GitHub tag/commit permalink; versioned docs; DOI). If a versioned URL exists and the reference is normative or precision‑critical, you **MUST NOT** link to moving targets like “main”, “HEAD”, or “latest”. For general project references (homepage or repo root), you **MAY** use the canonical current URL. (Why: permalinks keep exact references stable; simple links are fine when versioning adds no value.) \\[HIGH]\n- Deep links. You **SHOULD** link to the exact section/anchor that holds the needed fact, not the page top. (Why: deep links land readers on the answer and reduce scanning.)\n- Clean URLs. Links **MUST** use HTTPS, **MUST NOT** include shorteners or tracking parameters (e.g., `utm_*`), and **MUST NOT** point to unofficial mirrors/gists when an official location exists. (Why: clean, canonical URLs are trustworthy and durable.) \\[HIGH]\n- Language and availability. Link to the English source by default. If the authoritative page is non‑English, **MUST** label the link with the language (e.g., “(in Russian)”). Avoid paywalled sources as primary; if unavoidable, **SHOULD** provide an open alternative or summarize key facts locally. (Why: sets expectations and preserves access.)\n\n## 13. Terminology and naming\n\nObjective. Enforce a single source of truth for terms and casing. (Why: one authoritative lexicon prevents confusion, reduces review churn, and keeps search/indexing consistent.)\n\n### 13.1 Term bank (canonical source)\n\n- A project term bank **MUST** define canonical terms, spellings, hyphenation, casing, and banned variants with replacements (e.g., allowlist/denylist for whitelist/blacklist). (Why: clear entries stop ad‑hoc wording and mixed casing from spreading.)\n- You **MUST** consult the term bank before introducing new names; additions **SHOULD** be reviewed by editors. (Why: gatekeeping new terms prevents drift and conflicting synonyms.)\n- The term bank **SHOULD** mark which terms are link‑worthy for first‑use cross‑links and record their canonical doc URLs. First‑use linking rules in [§12.2](#122-what-to-link-and-what-not) **SHOULD** apply only to terms above this importance threshold to avoid over‑linking minor notions. (Why: a curated set of link‑worthy terms keeps pages readable while still making key concepts discoverable.)\n- Flags, parameters, error codes, and data types documented in guides **MUST** be included in this link‑worthy set so first‑use links in [§12.2](#122-what-to-link-and-what-not) always have a canonical target. This includes TVM exit codes, send modes, reserve modes, and other numeric constants with documented semantics. (Why: treating these technical items as link‑worthy ensures readers can jump straight to their reference definitions.) \\[HIGH]\n\n### 13.2 General casing rules\n\n- Generic concepts **MUST NOT** be capitalized mid‑sentence (use \"smart contract,\" not \"Smart Contract\"). (Why: random caps imply proper nouns and slow reading.) \\[HIGH]\n- Proper nouns and official product/feature names **MUST** follow the term bank (e.g., TON, TON Connect). (Why: consistent branding and accurate references.)\n- Code identifiers (types, fields, flags) **MUST** appear in code font with exact case. (Why: preserves copy/paste fidelity and distinguishes code from prose.) \\[HIGH]\n\n### 13.3 Hyphenation and abbreviations\n\n- Multi‑word mechanism names are common nouns and **SHOULD** be hyphenated: proof‑of‑stake, zero‑knowledge. (Why: hyphenation clarifies compounds and matches industry norms.)\n- Abbreviated forms **MUST** follow the project style: ZK‑proof, ZK‑rollup (uppercase ZK, hyphenated compound). (Why: consistent abbreviation improves recognition and search.)\n- Use mainnet as a common noun; use TON Mainnet when referring to the proper name of the network. (Declare this explicitly in the term bank.) (Why: distinguishes generic network type from the named network.)\n- Use testnet as a common noun; use TON Testnet when referring to the proper name of the network. (Why: same distinction as mainnet; avoids mixed casing.)\n\n### 13.4 TON‑specific examples\n\nNon‑exhaustive; finalize in the term bank. (Why: examples guide writers now, while the term bank remains the single source of truth.)\n\n- TON, TON Blockchain, TON Ecosystem (proper nouns).\n- smart contract, wallet, account, message, jetton, nominator, validator, collator, node, liteserver (common nouns, lowercase mid‑sentence).\n- accountchain, shardchain, workchain, masterchain, basechain — common nouns; use lowercase mid‑sentence. **MUST NOT** use CamelCase forms (`ShardChain`, `WorkChain`, `MasterChain`, `BaseChain`, `AccountChain`) or spaced variants (e.g., “Shard Chain”).\n- BoC (abbrev.) / bag of cells (common noun). Abbreviation **MUST** be “BoC” (not “BOC”).\n  Note: Do **NOT** introduce “master/slave” metaphors in new text; use primary/replica or similar. (Why: maintains inclusive language.)\n\n### 13.5 Placeholder names\n\n- In commands and prose, placeholders **MUST** be `<ANGLE_CASE>` with descriptive names: `<WALLET_ADDR>`, `<AMOUNT_TON>`, `<RPC_URL>`. (Why: a single, visible pattern reduces copy/paste mistakes.)\n- In programming‑language code, placeholders **MAY** use `UPPER_SNAKE` without angle brackets when `< >` would clash with syntax (see [§10.1](#101-general-rules)). (Why: avoids syntax errors while keeping placeholders obvious.)\n- **MUST NOT** use `{curly}` or `[square]` placeholder syntax in copy‑pasteable commands, as they are easy to misread as literal characters. (Why: braces/brackets are often treated as literals by shells and new users.) \\[HIGH]\n\n### 13.6 Banned and preferred terms\n\n- Banned (inclusive/biased): whitelist/blacklist; master/slave; sanity check. \\[HIGH]\n- Banned (filler/tone): simply, just, obviously, clearly, please note.\n- Preferred: (omit filler); allowlist/denylist; primary/replica; smoke check or basic check.\n  Rationale: clarity, inclusivity, and reduced ambiguity.\n\n## 14. Numbers, units, date, and time\n\nObjective. Present quantitative information unambiguously for a global developer audience. (Why: consistent formats prevent locale‑based misreads and implementation errors.)\n\n### 14.1 Numerals and separators\n\n- You **MUST** use numerals for all technical quantities (latency, memory, fees, block heights, versions, ports), regardless of size. (Why: digits are faster to scan and less ambiguous than words in technical contexts.)\n\n  - Good: “Set the fee to 0.2 TON.”\n- For general prose without units, you **MAY** spell out zero–nine and use numerals for 10+, but prefer numerals whenever a value matters to a task. (Why: numbers highlight actionable values and make comparisons obvious.)\n- You **SHOULD** use thousands separators for numbers ≥ 10,000: 10,000, 1,234,567. (Why: separators improve readability and reduce digit‑counting mistakes.)\n- **MUST NOT** add separators to codes/IDs (e.g., block hashes, transaction IDs, addresses), even if they contain digits; keep copyable values intact. (Why: added punctuation breaks copy/paste and changes identifiers.) \\[HIGH]\n- Decimal separator **MUST** be a dot: 3.1415. (Why: a single convention avoids comma/dot confusion across locales and matches most APIs.)\n\n### 14.2 Units and conventions\n\n- Use binary units (KiB, MiB, GiB) for memory/storage sizes and SI units (kB, MB, Gbps, ms) for network throughput, latency, and timing. Be consistent within each category. (Why: binary vs SI units have different meanings; consistency prevents 2× errors.)\n- Currency amounts **MUST** specify the unit (e.g., TON, USDT). When precision matters, show decimals explicitly (e.g., 0.000001 TON). (Why: omitting units or precision leads to costly misinterpretation.) \\[HIGH]\n- Address/hash values **MUST NOT** be silently truncated. If truncation aids readability, use a consistent truncation pattern (e.g., first 4 / last 4 with an ellipsis: `EQC…9gA`) and state clearly that the value is truncated. (Why: silent truncation causes copy/paste failures and verification mistakes.) \\[HIGH]\n\n### 14.3 Dates and times\n\n- Dates **MUST** use ISO‑8601 format YYYY‑MM‑DD (e.g., 2025‑02‑11). (Why: ISO is unambiguous and sorts correctly.)\n- Times **SHOULD** be 24‑hour and, where relevant, UTC (e.g., 14:30 UTC). (Why: avoids AM/PM ambiguity and timezone drift.)\n\n  - Use UTC for timestamps that might be compared across regions (e.g., transactions, block times, cron examples). (Why: a single timezone ensures consistent ordering and comparison.)\n- Ranges **MUST** be explicit: 2025‑02‑11 14:30–15:00 UTC. (Why: clear start/end with timezone prevents misaligned windows.)\n- **MUST NOT** use ambiguous forms like `11/2/2025`. (Why: day/month order varies by locale and leads to errors.)\n- Changelogs **SHOULD** include a date stamp in ISO format. (Why: stable, sortable dates aid release tracking.)\n\n### 14.4 Magnitudes and math\n\n- Prefer engineering prefixes for readability: 1.2 GiB, 250 ms, 500 kB/s. (Why: normalized units make scale comparisons quick and reduce cognitive load.)\n- Inline math **SHOULD** use KaTeX/LaTeX components when formulas help clarity. (Why: consistent rendering and accessibility across themes and locales.)\n\nRationale: Consistent numeric style reduces misreads and eases localization.\n\n## 15. Accessibility and internationalization\n\nObjective. Ensure content is usable by all readers and easy to localize. (Why: accessible, localization‑ready text works for non‑native readers, assistive technologies, and translations without rewrites.)\n\n### 15.1 Language and reading\n\n- Content **MUST** use plain, international English; avoid idioms, slang, and culture‑specific metaphors. (Why: idioms and slang do not translate well and confuse global readers.)\n- Link text and headings **MUST** be descriptive (screen‑reader friendly). Avoid “click here” (see [§12](#12-links-and-cross-references)). (Why: descriptive text improves scanning and is meaningful when read aloud by assistive tech.)\n- Avoid gendered or ableist terms; use inclusive alternatives (see [Appendix B](#b-banned-and-preferred-terms)). (Why: inclusive language prevents exclusion and avoids unnecessary friction.)\n\n### 15.2 Structure and tables\n\n- Tables **SHOULD** include header rows; keep cell content short and scannable. (Why: headers provide context for readers and screen readers; brief cells are easier to parse.)\n- Units **MUST** be shown in headers or cells (e.g., “Latency (ms)”, “Size — MiB”). (Why: explicit units prevent misinterpretation of values.)\n- Columns whose cells are primarily numeric values (for example, counts, sizes, fees, percentages, timings) **MUST** be right‑aligned so digits line up vertically. (Why: aligned digits make numeric comparisons easier and reduce misreads.) \\[HIGH]\n- Columns whose cells contain identifiers such as addresses, hashes, transaction IDs, or error codes are not numeric columns and **MAY** remain left‑aligned. (Why: identifier strings are scanned, copied, and compared differently than numeric quantities.)\n- Cells **SHOULD NOT** contain multi‑paragraph text; move extended explanations below the table. (Why: long prose in tables is hard to read and harms accessibility/layout.)\n- Long lists inside cells **SHOULD** be converted to bullet lists placed below the table. (Why: lists outside tables are easier to scan and navigate.)\n- Provide text alternatives for complex figures when feasible. (Why: alt or adjacent text lets screen‑reader users and translators access the content.)\n- Keyboard‑only navigation **SHOULD** be considered when adding interactive elements. (Why: some users cannot use a mouse; keyboard support is a basic accessibility need.)\n- Emojis **MAY** appear in compact tables as secondary indicators only when they follow a widely understood convention (e.g., `✅ Supported`, `❌ Not supported`) and are paired with clear text in the same cell. **MUST NOT** rely on emojis alone to encode meaning or status, and **MUST NOT** use decorative pictograms or one‑off icons that do not have a clear, conventional meaning. (Why: paired, conventional indicators remain accessible and understandable when emojis do not render or in translation.)\n\n### 15.3 Localization readiness\n\n- Prefer stable terminology from the term bank ([Appendix B](#b-banned-and-preferred-terms) references) to minimize translation drift. (Why: consistent terms reduce rework and inconsistent translations.)\n- Dates/times already follow ISO conventions (see [§14.3](#143-dates-and-times)), which **SHOULD** simplify localization. (Why: ISO formats are unambiguous across locales and require minimal adaptation.)\n\nRationale: Clear, inclusive writing and accessible assets improve comprehension for global audiences and translation tools.\n\n## 16. File, navigation, and frontmatter conventions\n\nContent of this section mostly describes contents of `docs.json` and `[...](...)` markdown links in `.mdx` files.\n\n### 16.1 Sidebar groups and ordering\n\nObjective. Keep navigation predictable and reduce decision points. (Why: consistent ordering helps readers find the right kind of page without scanning the whole section.)\n\nRules (binding).\n\n- The onboarding path **SHOULD** be a dedicated “Step by step” group near the top of the sidebar. Keep it linear and link out for depth. (Why: newcomers progress faster with one clear path.)\n- Within every topical group (e.g., Ecosystem, Language reference, Standard contracts, TVM, Foundations, Smart‑contract patterns, Contribute; Integrate when present), pages **MUST** be ordered: Explanation → How‑to → Reference. (Why: readers scan “why” first, then “how”, then exact details.)\n- The Explanation page **SHOULD** be the group’s overview (often `overview.mdx`). Keep it conceptual and brief, and link to How‑to/Reference as needed. (Why: one conceptual entry frames the section and reduces duplication.)\n- Reference pages **MUST** be the canonical source for flags/fields/errors/types. Guides **MUST NOT** duplicate tables; they **SHOULD** deep‑link to anchors. (Why: single source of truth stays accurate and reduces maintenance.)\n\nObjective. Keep repository structure and UI labels consistent. (Why: predictable structure speeds editing, improves search/TOC behavior, and reduces merge and build issues.)\n\n### 16.2 Files and titles\n\n- Filenames **MUST** use kebab‑case.md or kebab‑case.mdx (e.g., `validator-setup.mdx`). (Why: kebab‑case avoids case‑sensitivity bugs, reads well in URLs, and is easy to grep.) \\[HIGH]\n- Filenames **MUST NOT** have uppercase characters, i.e. `foo-bAR.mdx`. \\[HIGH]\n- Filenames **MUST NOT** have cyrillic characters, i.e. `сhoice.mdx`. \\[HIGH]\n\n### 16.3 Navigation labels\n\n- Sidebar and nav labels **SHOULD** be short (2–4 words), unique, and mirror in‑page headings. (Why: short, unique labels prevent truncation and speed scanning.)\n\n- Sidebar labels **MAY** be concise aliases of the page title; they **SHOULD** preserve the title’s meaning even if wording is shortened. (Why: sidebars have less space; preserving meaning avoids confusion.)\n\n- Child pages inside a sidebar group **MUST NOT** repeat the group name in `sidebarTitle` when that word adds no new meaning. Rely on the group label as context and choose a short, distinct label instead. (Why: avoiding redundant group nouns keeps nested labels concise and scannable.) \\[HIGH]\n  - Example: in a group `Addresses`, prefer `sidebarTitle: \"Overview\"` or `sidebarTitle: \"Deriving\"` over `sidebarTitle: \"Addresses overview\"` or `sidebarTitle: \"Deriving addresses\"`.\n\n- Avoid duplicate “Introduction” labels—make them specific (e.g., “Intro to sharding”). (Why: generic labels create indistinguishable TOC items and weak deep links.)\n\n- Frontmatter keys. Use only page metadata supported by Mintlify (see project docs) and `noindex: true` when a page must be excluded from search indexing. **MUST NOT** introduce custom frontmatter keys for internal taxonomy (e.g., `doc_type`, `audience`, custom `status`). Represent such information in the page content or navigation instead. (Why: unsupported keys add maintenance burden, break tooling, and confuse contributors.)\n\n- Length cap. If the frontmatter `title` exceeds 30 characters, the page **MUST** set `sidebarTitle`, and the `sidebarTitle` **MUST** be ≤ 30 characters. If the `title` is ≤ 30 characters, `sidebarTitle` is OPTIONAL; when provided, it **SHOULD** be ≤ 30 characters. Prefer removing non‑essential words over truncation; labels **MUST NOT** end with ellipses; preserve meaning and proper‑noun/case accuracy. (Why: short, clear labels fit sidebars and remain scannable.)\n\n  Example\n\n  ```mdx\n  ---\n  title: \"How to troubleshoot validator connectivity issues on restrictive firewalls\"\n  sidebarTitle: \"Validator connectivity\"\n  ---\n  ```\n\n- How‑to frontmatter pattern. How‑to pages **MUST** set `title: \"How to X\"` and **MUST** set `sidebarTitle` to either `X` or a shorter alias of X that relies on the sidebar group for context and does not repeat the group name needlessly, where X is the task phrased in sentence case. If X begins with a letter, capitalize its first character; preserve exact casing for proper nouns and code tokens inside X. (Why: consistent titles match “how to …” searches; concise sidebar labels aid scanning while avoiding redundant group nouns and keeping identifiers accurate.) \\[HIGH]\n\n- Title vs sidebar semantics. The frontmatter `title` **MUST** be context‑free and self‑describing for search and deep links; the `sidebarTitle` **SHOULD** be concise and rely on the current navigation context. One‑word generic titles (e.g., “Overview”, “Introduction”) **MUST NOT** be used as `title` except on top‑level pages (`/the-page`) or when the page is a proper name/term (e.g., “Tonkeeper”, “TON Center”). In those cases, a one‑word `title` **MAY** be used. Otherwise, the `title` **SHOULD** replicate or expand the section/folder name (e.g., “Sharding overview”), and the `sidebarTitle` **MAY** be “Overview”. (Why: descriptive titles improve discoverability and stand alone; short sidebar labels read better in context.)\n\n  Example\n\n  ```mdx\n  ---\n  title: \"Sharding overview\"\n  sidebarTitle: \"Overview\"\n  ---\n  ```\n\n  Example\n\n  ```mdx\n  ---\n  title: \"How to get testnet Toncoin\"\n  sidebarTitle: \"Get testnet Toncoin\"\n  ---\n  ```\n\n### 16.4 Links and anchors\n\n- Internal links **MUST** be root‑absolute (start with `/`) and **MUST NOT** include `./` or `../`; ensure anchors are stable. (Why: root‑absolute links survive file moves and changes to the information architecture; relative segments break during reorganizations.) \\[HIGH]\n- Trailing slashes: Follow a single repo‑wide policy set by the site generator, and apply it consistently across all internal links. (Why: consistency prevents duplicate routes, cache misses, and SEO issues.)\n- Cross‑section links **SHOULD** target specific anchors rather than page tops. (Why: deep links land readers directly on the needed detail.)\n\n### 16.5 Status labels\n\n- Pages and features **MAY** declare a status in content at the top of the page using an `<Aside>` with a clear title (e.g., `title=\"Deprecated\"` or `title=\"Experimental\"`). Do not introduce custom frontmatter keys for status. (Why: status is visible to readers and does not require unsupported metadata.)\n- If deprecated, the page **MUST** include the replacement (link to successor) and the removal timeline (date or version) in the callout. You **MAY** set `noindex: true` in frontmatter to exclude the page from search when appropriate. (Why: clear migration guidance reduces breakage; de‑indexing avoids surfacing outdated pages.)\n- If experimental, briefly state scope and limitations; link to the stable alternative when available. (Why: scope limits misuse and points to the dependable path.)\n- Status labels (experimental/deprecated) are independent of safety callouts (see [§11](#11-safety-critical-content-blockchain-specific)). Apply both when applicable. (Why: status communicates lifecycle; safety communicates risk—readers need both.)\n\n### 16.6 Components used in content\n\n- On normal documentation pages, **SHOULD NOT** use `<Card>` components; prefer headings, lists, and inline links for navigation and structure. (Why: cards add visual chrome that is rarely needed for comprehension.)\n\n- Existing `<Card>` usages **SHOULD** be confined to top‑level index or overview pages where the card layout clearly improves navigation. Over time, simplify or remove cards that do not provide a clear navigation benefit. (Why: keeping cards to a few deliberate entry pages avoids fragmenting the visual style.)\n\n- When an index‑style page genuinely needs card‑like tiles, you **MAY** use `<Card>`; keep the content inside each card minimal and avoid duplicating information from the linked pages. (Why: cards should support navigation, not introduce a second layer of prose.)\n\n- More generally, follow the “minimal styling” workflow from [§6.2](#62-quotation-marks-and-emphasis): components such as `<Card>`, `<Aside>`, `<Image>`, or tab containers **SHOULD** appear only when they improve comprehension or navigation, not as decoration. (Why: reduced decorative chrome makes structure and behavior stand out.)\n\n## 17. Content hygiene and timeless writing\n\nObjective. Reduce staleness, duplication, and maintenance costs. (Why: fresh, non‑duplicated content is cheaper to maintain and more trustworthy for readers.)\n\n### 17.1 Single source of truth\n\n- Each fact **MUST** have a canonical home. If you need the same fact elsewhere, link to it (see [§12](#12-links-and-cross-references)). (Why: one source prevents contradictions and simplifies updates.)\n- Guides **MUST NOT** replicate reference tables; summarize and link. (Why: duplicated tables drift and become incorrect.)\n\n### 17.2 Timelessness\n\n- You **SHOULD NOT** use words like “currently”, “new”, or “soon”. (Why: time‑relative words stale quickly and lose meaning.)\n- Prefer durable phrasing: “Since v2.3, X is supported,” not “newly added.” (Why: version‑based phrasing stays accurate over time.)\n- Remove version qualifiers once they’re no longer useful. (Why: eliminates outdated noise and keeps prose evergreen.)\n\n### 17.3 Freshness and updates\n\n- When behavior changes, the relevant pages **MUST** be updated promptly. (Why: outdated steps cause failures and support load.)\n- Large refactors **SHOULD** include redirects and update cross‑links. (Why: preserves deep links and prevents 404s.)\n- Avoid re‑documenting external tools; link to official docs and focus on TON‑specific usage. (Why: external details change often; linking reduces churn.)\n\n### 17.4 Proofread\n\n- Read aloud or skim with a “scanner’s eye”; long sentences **SHOULD** be split (see [§8](#8-readability-and-scannability)). (Why: catches awkward phrasing and improves scannability.)\n- Check terms against the term bank; enforce casing and spelling consistently. (Why: consistent terminology improves comprehension and search.)\n\nRationale: “Timeless” style and a canonical home for facts keep the docs trustworthy and maintainable.\n\n## 18. Style exceptions and edge cases\n\nObjective. Provide a controlled escape hatch without eroding consistency. (Why: limited, trackable exceptions solve real edge cases without letting the style drift.)\n\n- Any deviation from this guide **MUST** document: the rule being overridden, the reason, the scope (pages affected), the owner, and an expiry or review date. (Why: documentation, ownership, and a sunset make exceptions accountable and reversible.)\n- Exceptions **SHOULD** be rare, time‑boxed, and revisited. (Why: scarcity prevents precedent; time limits force cleanup.)\n- For audience‑critical reasons (e.g., highly advanced research notes), a page **MAY** relax sentence‑length norms ([§8](#8-readability-and-scannability)) or include extra theory in a how‑to ([§3](#3-documentation-framework-content-types)), but the page **MUST** clearly state the rationale at the top (e.g., Audience: Advanced). (Why: transparency lets readers self‑select and prevents surprise.)\n- When quoting external code or configuration verbatim for legal or technical reasons, formatting **MAY** violate some house rules if changing it would misrepresent the original. Such cases **SHOULD** be rare and, for large or recurring examples, **SHOULD** be documented as style exceptions with scope and owner. (Why: fidelity to external sources sometimes takes priority over local formatting rules.)\n- A safety requirement ([§11](#11-safety-critical-content-blockchain-specific)) **MUST NOT** be waived. (Why: reader safety outweighs convenience.) \\[HIGH]\n\nRationale: Exceptions exist to serve clarity, not convenience. They are documented so future editors can normalize them later.\n\n## 19. Appendices\n\n### A. Admonition levels and usage\n\nUse the least severe callout that communicates the point; overuse reduces impact. (Why: calibrated severity keeps important warnings noticeable; overuse leads to alert fatigue.)\n\nImplementation. Render callouts with the `<Aside>` component (see `/snippets/aside.mdx`). **MUST NOT** use Markdown blockquotes (`>`) to simulate callouts. The only supported `type` values are `note`, `tip`, `caution`, and `danger`. Map levels to types: Note → `type=\"note\"`; Tip → `type=\"tip\"`; Caution → `type=\"caution\"`; Warning → `type=\"danger\"`. Use `title` to set the visible label when needed (e.g., `title=\"Important\"`). (Why: consistent components and a fixed type set keep callouts accessible and visually coherent.) \\[HIGH]\n\n- On pages with multiple hazardous actions, combine a page‑level safety `<Aside>` at the top (describing overall risk, scope, rollback/mitigation where feasible, and environment) with short local `<Aside>` elements near each dangerous step that can refer back to the summary instead of repeating it. (Why: the combination keeps risks visible without duplicating long warnings at every step.)\n\n| Level     | When to use                                              | MUST include                                    |\n| --------- | -------------------------------------------------------- | ----------------------------------------------- |\n| Note      | Auxiliary info or minor edge cases                       | Short, actionable text only                     |\n| Tip       | Productivity boosters, shortcuts                         | A clear benefit (“Saves time by …”)             |\n| Important | Prerequisites, state assumptions, gotchas                | The condition and its effect                    |\n| Caution   | Potential data loss or non‑recoverable state             | Risk + mitigation/rollback                      |\n| Warning   | Security, funds/keys/validator risk, chain‑affecting ops | Risk + scope + rollback + testnet/mainnet label |\n\n(Why: the “MUST include” fields ensure every callout contains the minimum information a reader needs to act safely.)\n\nExamples\n\n- Important — prerequisite\n  “This guide requires a funded testnet wallet.”\n\n- Caution — data loss\n  “`--purge-ledger` removes local data. Back up `<LEDGER_DIR>` before running.”\n\n- Warning — funds at risk\n  “Transfers on mainnet are final.”\n\n- Warning — page with many risky steps\n  “Read the safety note at the top of this page before running any mainnet commands.”\n\n(Admonition usage aligns with the safety requirements in [§11](#11-safety-critical-content-blockchain-specific).)\n\n### B. Banned and preferred terms\n\nUse this list in combination with the project term bank (see [§13](#13-terminology-and-naming)). Editors **MUST** expand it over time. (Why: the lexicon evolves; keeping it current prevents drift and inconsistency.)\n\nFiller/tone (ban outright) (Why: filler adds no information and can sound condescending.)\n\n- Banned: simply, just, obviously, clearly, please note, super‑, ASAP\n- Use instead: omit or state the concrete action/effect\n\nMarketing/promotional (ban outright) (Why: marketing language erodes trust, adds no actionable information, and ages poorly.)\n\n- Banned superlatives: blazingly fast, revolutionary, world‑class, seamless, best‑in‑class, powerful, cutting‑edge, game‑changing, next‑generation\n- Banned vague adjectives (without measurable criteria): reliable, robust, essential, elegant, intuitive, flexible, comprehensive, scalable, efficient, optimal, superior\n- Banned dramatic/emotional words: elusive, challenging (as drama), painful, frustrating, nightmare, perfectly, beautifully, amazing, incredible, stunning\n- Banned intensity words: instantly (unless literal), immediately (unless literal), extremely, incredibly, massive, huge (for non‑quantified values)\n- Banned storytelling openers: \"Imagine…\", \"Picture this…\", \"Have you ever…\", \"What if…\"\n- Use instead: measurable facts, specific numbers, concrete conditions, or omit entirely\n\nInclusivity (Why: inclusive terms are clearer for everyone and avoid excluding readers.)\n\n- Banned: whitelist/blacklist → Preferred: allowlist/denylist\n- Banned: master/slave → Preferred: primary/replica (or leader/follower, depending on context)\n- Banned: sanity check → Preferred: basic check / smoke check\n- Banned: dummy value → Preferred: sample value / placeholder\n- Banned: crazy/insane → Preferred: unexpected / invalid\n\nClarity (Why: simpler words are read and translated more reliably.)\n\n- Avoid: utilize → Use: use\n- Avoid: prior to → Use: before\n- Avoid: in order to → Use: to\n- Avoid: leverage (as verb) → Use: use/apply\n- Avoid: handle → Use: process/manage (be specific)\n\nTON‑specific casing (selected; see [§13](#13-terminology-and-naming) for more) (Why: exact casing improves search, recognition, and copy/paste fidelity.)\n\n- Correct: TON, TON Mainnet; smart contract; bag of cells; BoC; accountchain, shardchain, workchain, masterchain, basechain; ZK‑proof, ZK‑rollup.\n- Incorrect: Ton; ton mainnet; Smart Contract; BOC; ShardChain; Shard Chain; WorkChain.\n"
  },
  {
    "path": "contribute/style-guide.mdx",
    "content": "---\ntitle: \"Documentation style guide\"\nsidebarTitle: \"Style guide\"\n---\n\nThis guide covers the basics: how to structure pages, write examples, and keep docs consistent and safe.\n\n## Write for the reader\n\n- Default audience: experienced software developers new to blockchain. Explain TON-specific concepts. Do not re-teach general programming. This keeps pages focused.\n- Be answer‑first. Start with what the reader will achieve, what they need, and the steps. This shortens the time to success.\n- Lead with a working example. Show a copy‑pasteable snippet early and the expected output. This shows it works.\n- Use a neutral, precise tone. Write in the present tense, active voice, and second person (“Run the node”). This makes actions clear.\n- Avoid marketing or hype (“blazingly fast”, “seamless”, “revolutionary”) and vague praise. Prefer measurable facts or omit the claim.\n- Keep it scannable. Use short sections and paragraphs, clear headings, lists, and tables. Most readers skim to find the next action.\n- Aim for one main idea per sentence. Split long, multi‑clause sentences or turn them into lists.\n- Use bold only for a few scan‑worthy words in a paragraph, not full sentences or tokens. If a skimming reader loses nothing when the bold is removed, drop it.\n- Use italics for new or defined terms and subtle emphasis; use bold for words a skimming reader should find quickly.\n- Draft in plain text first. During editing, add minimal emphasis and remove any styling that does not change meaning.\n\n## Page types\n\n- Step-by-step guides — for beginners; handhold from zero to first success on one happy path; explain from scratch, define terms, and link out for depth.\n- How-tos — a focused recipe for a specific outcome; assume concepts known and show only what’s needed.\n- Explanation — concepts, architecture, and trade‑offs; clarify why and when, with minimal examples.\n- Reference — exact, complete facts (APIs, CLI, types, errors); stable anchors and minimal prose.\n- Don’t mix types on the same page.\n\n## Where pages go\n\n- Keep the flow linear; follow the `docs.json` sidebar.\n- In each topic group, order pages: Explanation → How‑to → Reference.\n- Canonical specs — `reference/`. Link to it; don’t duplicate tables or parameters.\n\n## Structure pages for success\n\n- Start with Objective and Prerequisites so readers know they’re in the right place. Use Prerequisites for things the reader must have or have done; use an Audience note for skills or knowledge.\n- Make each step a single action; use sub‑bullets for options.\n- Include Verify and Troubleshoot so readers can confirm success and fix common errors.\n- End with Next steps / See also only if essential (1–3 links). Prefer a linear path that needs no extra navigation.\n\n## Examples that run\n\n- Make commands copy‑pasteable. Do not include shell prompts like `$` or `>`. Prompts break commands when pasted.\n- Separate command and output. Use two fenced blocks. Mixing them causes copy errors.\n- Use `<ANGLE_CASE>` placeholders in commands and prose and define each on first use (for example, `<RPC_URL>`). In code, use `UPPER_SNAKE` if `< >` clashes with syntax. One clear convention prevents hard‑coded values from slipping in.\n- Tag code fences with a language (`bash`, `json`, `rust`, and so on). This enables correct highlighting and tooling.\n- Prefer end‑to‑end examples on testnet by default. Safe defaults encourage trying the steps.\n- Label partial snippets as Not runnable and link to a complete example.\n- Do not hard‑wrap long commands. Use soft wrap in the UI or safe continuation if the shell supports it. Hard wraps break execution.\n- For UI buttons, menu items, and key names, wrap the label in `<kbd>…</kbd>` instead of quotes or bold. This keeps controls easy to spot and consistent with the main style guide.\n\nGood\n\n```bash\nton-node start --ledger <LEDGER_DIR> --network testnet\n```\n\nExpected output\n\n```text\nNode started. Workchain: 0  Shard: -1  Status: running\n```\n\nDefine placeholders\n`<LEDGER_DIR>` — local ledger directory.\n`<RPC_URL>` — HTTPS endpoint of your TON RPC provider.\n\n## Safety warnings\n\nAdd a Caution or Warning when a step moves funds, changes fees or withdrawals, exposes or stores private keys or mnemonics, modifies validator or network settings, or performs chain‑affecting operations such as resharding, pruning, halting, or replay. These actions can cause irreversible loss or outages.\n\nOn long guides with many risky commands, combine a clear page‑level warning at the top (covering risk, scope, rollback where feasible, and environment) with short local notes next to each critical step. Local notes can be brief if they point back to the main warning.\n\nPattern\n\n> Warning — funds at risk\n> Running the next command on mainnet transfers funds irreversibly.\n> Safer first (testnet):\n>\n> ```bash\n> jetton transfer --to <ADDR> --amount <AMOUNT> --network testnet\n> ```\n>\n> If you must use mainnet: no rollback; on‑chain transfers are final.\n\nDefault to testnet in task pages. Make destructive flags opt‑in and document mitigations.\n\n## Necessary disclaimers\n\nAdd a Caution or Warning when a page or step:\n\n- Moves funds or changes fee/withdrawal behavior.\n- Exposes, stores, or transmits private keys or mnemonics.\n- Modifies validator configuration, networking, or other consensus‑affecting parameters.\n- Performs chain‑affecting operations (for example, resharding, pruning, halting, replay).\n- Uses destructive flags or commands that delete, rewrite, or lock state (for example, `--purge`, `--force`).\n- Runs on mainnet, where actions are irreversible; label the environment and give the safer testnet first.\n\nMake sure the guide as a whole clearly covers the risk, scope, rollback or mitigation (where feasible), and the environment label (testnet vs mainnet). For a single hazardous step, put these points directly in its callout. On long risky guides, put a big safety callout at the top and keep step‑level notes short, pointing back to that summary.\n\n## Titles and headings\n\n- Use sentence case. Keep headings concise and unique.\n- Use imperatives for tasks (“Deploy a validator”); nouns for concepts (“Validator architecture”). Titles should signal action vs. explanation.\n- Don’t style headings, except when an identifier needs code font.\n- Use clear section labels such as Verify, Troubleshoot, and See also.\n\n## Link to details, don’t duplicate\n\n- On first useful mention, link flags, parameters, error codes, and data types to their reference anchors.\n- Do not paste reference tables into guides. Link instead. Duplicated tables go stale.\n- Use descriptive link text that names the destination, not generic labels like “click here”, “here”, or “this page”, and avoid mechanics-focused link labels like “click” or “go to”.\n- Link core TON terms to the Glossary on first useful mention unless you define them on the page.\n- Internal links **MUST** be root‑absolute (start with `/`). Deep‑link to the exact section or anchor that contains the needed fact (not the page top). **MUST NOT** use relative segments like `./` or `../` in any Markdown/MDX link. (Why: content moves frequently; root‑absolute links survive reorganizations.)\n\n## Images\n\n- Use the `<Image>` component for all images. Markdown image syntax `![...](...)` and raw `<img ...>` are not allowed.\n- Store images under `resources/images/` and reference them with root‑absolute paths, for example `<Image src=\"/resources/images/<GROUP>/<FILE>.png\" />`. **MUST NOT** use relative `src` such as `./` or `../`.\n- Provide meaningful, non‑empty `alt` text (never `alt=\"\"`); add `darkSrc` when the dark theme needs different contrast. Keep sizes/aspect ratios consistent across a page.\n- SVGs: if you omit `darkSrc`, colors are auto‑inverted in dark mode; add `darkSrc` if inversion isn’t correct.\n\n## Terminology and names\n\n- Use the project term bank for canonical spellings, casing, and preferred terms. One vocabulary prevents drift.\n  Examples: TON, jetton, smart contract, BoC (bag of cells), accountchain, shardchain, workchain, masterchain, basechain.\n- Prefer allowlist and denylist over whitelist and blacklist. These are clearer and inclusive.\n- Use mainnet and testnet as common nouns. Use TON Mainnet and TON Testnet for the proper names. This distinguishes the generic type from the named network.\n\n## Files, front matter, labels\n\n- Filenames use `kebab-case.md` or `kebab-case.mdx` (for example, `validator-setup.mdx`). This is readable and consistent across platforms.\n- Optional front matter can declare `doc_type`, `audience`, and `status` (experimental or deprecated). If deprecated, add an Important callout with the replacement and timeline.\n- Keep sidebar labels short (2–4 words) and mirror in‑page headings.\n\n## Accessibility\n\n- Use plain English; avoid idioms and culture-specific references.\n- Use American English spelling (e.g., color, analyze).\n- Write descriptive headings and link text.\n- Tables should have headers and units (for example, “Latency (ms)”) and keep cells brief.\n- Provide text alternatives for complex figures when possible.\n- Avoid emojis. Only use them where they follow a common convention (for example, `✅ Supported`, `❌ Not supported`) and always pair them with text.\n\n## Secrets and environments\n\n- Never include real keys, mnemonics, or tokens. Use placeholders or clearly invalid test values. This prevents accidental leaks.\n- Prefer environment variables or keystores over inlining secrets.\n- Call out commands that can delete, rewrite, or lock state.\n- Label the environment when it matters (testnet vs mainnet).\n"
  },
  {
    "path": "docs.json",
    "content": "{\n  \"$schema\": \"https://mintlify.com/docs.json\",\n  \"theme\": \"maple\",\n  \"name\": \"TON Docs\",\n  \"logo\": {\n    \"light\": \"/resources/logo/light.svg\",\n    \"dark\": \"/resources/logo/dark.svg\"\n  },\n  \"favicon\": \"/favicon.png\",\n  \"colors\": {\n    \"primary\": \"#0098EA\",\n    \"light\": \"#F7F9FB\",\n    \"dark\": \"#1E2337\"\n  },\n  \"fonts\": {\n    \"family\": \"Inter\"\n  },\n  \"appearance\": {\n    \"default\": \"system\",\n    \"strict\": false\n  },\n  \"thumbnails\": {\n    \"appearance\": \"dark\",\n    \"background\": \"/resources/logo/og-image-bg.svg\"\n  },\n  \"styling\": {\n    \"eyebrows\": \"breadcrumbs\"\n  },\n  \"contextual\": {\n    \"options\": [\n      \"copy\",\n      \"chatgpt\",\n      \"claude\",\n      \"grok\",\n      \"perplexity\",\n      \"mcp\",\n      \"cursor\",\n      \"vscode\"\n    ]\n  },\n  \"navigation\": {\n    \"pages\": [\n      \"start-here\",\n      \"get-support\",\n      \"from-ethereum\",\n      \"more-tutorials\",\n      \"old\",\n      {\n        \"group\": \"Ecosystem\",\n        \"pages\": [\n          {\n            \"group\": \"AI\",\n            \"expanded\": true,\n            \"pages\": [\n              \"ecosystem/ai/mcp\"\n            ]\n          },\n          {\n            \"group\": \"Wallet apps\",\n            \"pages\": [\n              \"ecosystem/wallet-apps/web\",\n              \"ecosystem/wallet-apps/tonkeeper\",\n              \"ecosystem/wallet-apps/get-coins\",\n              \"ecosystem/wallet-apps/deep-links\",\n              \"ecosystem/wallet-apps/addresses-workflow\"\n            ]\n          },\n          {\n            \"group\": \"Explorers\",\n            \"pages\": [\n              \"ecosystem/explorers/overview\",\n              \"ecosystem/explorers/tonviewer\"\n            ]\n          },\n          \"ecosystem/sdks\",\n          {\n            \"group\": \"APIs\",\n            \"pages\": [\n              \"ecosystem/api/overview\",\n              {\n                \"group\": \"TON Center\",\n                \"expanded\": true,\n                \"pages\": [\n                  \"ecosystem/api/toncenter/introduction\",\n                  \"ecosystem/api/toncenter/rate-limit\",\n                  \"ecosystem/api/toncenter/get-api-key\",\n                  {\n                    \"group\": \"API v2\",\n                    \"pages\": [\n                      \"ecosystem/api/toncenter/v2/overview\",\n                      \"ecosystem/api/toncenter/v2-authentication\",\n                      \"ecosystem/api/toncenter/v2-errors\",\n                      \"ecosystem/api/toncenter/v2-tonlib-types\"\n                    ],\n                    \"openapi\": {\n                      \"source\": \"ecosystem/api/toncenter/v2.json\",\n                      \"directory\": \"ecosystem/api/toncenter/v2\"\n                    }\n                  },\n                  {\n                    \"group\": \"API v3\",\n                    \"pages\": [\n                      \"ecosystem/api/toncenter/v3/overview\",\n                      \"ecosystem/api/toncenter/v3-errors\",\n                      \"ecosystem/api/toncenter/v3-authentication\",\n                      \"ecosystem/api/toncenter/v3-pagination\"\n                    ],\n                    \"openapi\": {\n                      \"source\": \"ecosystem/api/toncenter/v3.yaml\",\n                      \"directory\": \"ecosystem/api/toncenter/v3\"\n                    }\n                  },\n                  {\n                    \"group\": \"Nominator Pools API\",\n                    \"openapi\": {\n                      \"source\": \"ecosystem/api/toncenter/smc-index.json\",\n                      \"directory\": \"ecosystem/api/toncenter/smc-index\"\n                    }\n                  }\n                ]\n              },\n              \"ecosystem/api/price\"\n            ]\n          },\n          \"ecosystem/status\",\n          \"ecosystem/analytics\",\n          {\n            \"group\": \"Oracles\",\n            \"pages\": [\n              \"ecosystem/oracles/overview\",\n              \"ecosystem/oracles/redstone\",\n              \"ecosystem/oracles/pyth\"\n            ]\n          },\n          \"ecosystem/bridges\",\n          {\n            \"group\": \"TON Connect\",\n            \"pages\": [\n              \"ecosystem/ton-connect/overview\",\n              \"ecosystem/ton-connect/dapp\",\n              \"ecosystem/ton-connect/wallet\",\n              \"ecosystem/ton-connect/manifest\",\n              \"ecosystem/ton-connect/message-lookup\"\n            ]\n          },\n          {\n            \"group\": \"AppKit\",\n            \"tag\": \"new\",\n            \"pages\": [\n              \"ecosystem/appkit/overview\",\n              \"ecosystem/appkit/init\",\n              \"ecosystem/appkit/toncoin\",\n              \"ecosystem/appkit/jettons\"\n            ]\n          },\n          {\n            \"group\": \"WalletKit\",\n            \"pages\": [\n              \"ecosystem/walletkit/overview\",\n              {\n                \"group\": \"Web\",\n                \"pages\": [\n                  \"ecosystem/walletkit/web/init\",\n                  \"ecosystem/walletkit/web/wallets\",\n                  \"ecosystem/walletkit/web/connections\",\n                  \"ecosystem/walletkit/web/events\",\n                  \"ecosystem/walletkit/web/toncoin\",\n                  \"ecosystem/walletkit/web/jettons\",\n                  \"ecosystem/walletkit/web/nfts\"\n                ]\n              },\n              {\n                \"group\": \"iOS\",\n                \"pages\": [\n                  \"ecosystem/walletkit/ios/installation\",\n                  \"ecosystem/walletkit/ios/init\",\n                  \"ecosystem/walletkit/ios/wallets\",\n                  \"ecosystem/walletkit/ios/data\",\n                  \"ecosystem/walletkit/ios/transactions\",\n                  \"ecosystem/walletkit/ios/events\",\n                  \"ecosystem/walletkit/ios/webview\"\n                ]\n              },\n              {\n                \"group\": \"Android\",\n                \"pages\": [\n                  \"ecosystem/walletkit/android/installation\",\n                  \"ecosystem/walletkit/android/init\",\n                  \"ecosystem/walletkit/android/wallets\",\n                  \"ecosystem/walletkit/android/data\",\n                  \"ecosystem/walletkit/android/events\",\n                  \"ecosystem/walletkit/android/transactions\",\n                  \"ecosystem/walletkit/android/webview\"\n                ]\n              },\n              \"ecosystem/walletkit/qa-guide\",\n              \"ecosystem/walletkit/native-web\",\n              \"ecosystem/walletkit/browser-extension\"\n            ]\n          },\n          {\n            \"group\": \"TON Pay\",\n            \"pages\": [\n              \"ecosystem/ton-pay/overview\",\n              \"ecosystem/ton-pay/quick-start\",\n              \"ecosystem/ton-pay/on-ramp\",\n              {\n                \"group\": \"Payment integration\",\n                \"pages\": [\n                  \"ecosystem/ton-pay/payment-integration/transfer\",\n                  \"ecosystem/ton-pay/payment-integration/payments-react\",\n                  \"ecosystem/ton-pay/payment-integration/payments-tonconnect\",\n                  \"ecosystem/ton-pay/payment-integration/status-info\"\n                ]\n              },\n              {\n                \"group\": \"UI integration\",\n                \"pages\": [\n                  \"ecosystem/ton-pay/ui-integration/button-react\",\n                  \"ecosystem/ton-pay/ui-integration/button-js\"\n                ]\n              },\n              \"ecosystem/ton-pay/webhooks\",\n              \"ecosystem/ton-pay/api-reference\"\n            ]\n          },\n          {\n            \"group\": \"TMA: Telegram Mini Apps\",\n            \"pages\": [\n              \"ecosystem/tma/overview\",\n              \"ecosystem/tma/create-mini-app\",\n              {\n                \"group\": \"Telegram UI\",\n                \"pages\": [\n                  \"ecosystem/tma/telegram-ui/overview\",\n                  \"ecosystem/tma/telegram-ui/getting-started\",\n                  \"ecosystem/tma/telegram-ui/platform-and-palette\",\n                  {\n                    \"group\": \"Reference\",\n                    \"pages\": [\n                      \"ecosystem/tma/telegram-ui/reference/avatar\"\n                    ]\n                  }\n                ]\n              },\n              {\n                \"group\": \"Analytics\",\n                \"pages\": [\n                  \"ecosystem/tma/analytics/analytics\",\n                  \"ecosystem/tma/analytics/supported-events\",\n                  \"ecosystem/tma/analytics/preparation\",\n                  \"ecosystem/tma/analytics/install-via-script\",\n                  \"ecosystem/tma/analytics/install-via-npm\",\n                  \"ecosystem/tma/analytics/api-endpoints\",\n                  \"ecosystem/tma/analytics/managing-integration\",\n                  \"ecosystem/tma/analytics/faq\"\n                ]\n              }\n            ]\n          },\n          {\n            \"group\": \"Blockchain nodes\",\n            \"expanded\": true,\n            \"pages\": [\n              \"ecosystem/nodes/overview\",\n              {\n                \"group\": \"C++ node\",\n                \"pages\": [\n                  \"ecosystem/nodes/cpp/setup-mytonctrl\",\n                  \"ecosystem/nodes/cpp/run-validator\",\n                  \"ecosystem/nodes/cpp/integrating-with-prometheus\",\n                  \"ecosystem/nodes/cpp/setup-mylocalton\",\n                  {\n                    \"group\": \"MyTonCtrl reference\",\n                    \"pages\": [\n                      \"ecosystem/nodes/cpp/mytonctrl/overview\",\n                      \"ecosystem/nodes/cpp/mytonctrl/core\",\n                      \"ecosystem/nodes/cpp/mytonctrl/installer\",\n                      \"ecosystem/nodes/cpp/mytonctrl/wallet\",\n                      \"ecosystem/nodes/cpp/mytonctrl/validator\",\n                      \"ecosystem/nodes/cpp/mytonctrl/collator\",\n                      \"ecosystem/nodes/cpp/mytonctrl/pools\",\n                      \"ecosystem/nodes/cpp/mytonctrl/liquid-staking\",\n                      \"ecosystem/nodes/cpp/mytonctrl/custom-overlays\",\n                      \"ecosystem/nodes/cpp/mytonctrl/utilities\",\n                      \"ecosystem/nodes/cpp/mytonctrl/alerting\",\n                      \"ecosystem/nodes/cpp/mytonctrl/backups\",\n                      \"ecosystem/nodes/cpp/mytonctrl/btc-teleport\"\n                    ]\n                  }\n                ]\n              },\n              {\n                \"group\": \"Rust node\",\n                \"pages\": [\n                  \"ecosystem/nodes/rust/quick-start\",\n                  \"ecosystem/nodes/rust/architecture\",\n                  \"ecosystem/nodes/rust/global-config\",\n                  \"ecosystem/nodes/rust/logs-config\",\n                  \"ecosystem/nodes/rust/node-config\",\n                  \"ecosystem/nodes/rust/metrics\",\n                  \"ecosystem/nodes/rust/node-config-ref\",\n                  \"ecosystem/nodes/rust/probes\",\n                  \"ecosystem/nodes/rust/monitoring\"\n                ]\n              }\n            ]\n          },\n          {\n            \"group\": \"Staking\",\n            \"pages\": [\n              \"ecosystem/staking/overview\",\n              \"ecosystem/staking/liquid-staking\",\n              \"ecosystem/staking/single-nominator\",\n              \"ecosystem/staking/nominator-pools\"\n            ]\n          }\n        ]\n      },\n      {\n        \"group\": \"Payment processing\",\n        \"pages\": [\n          \"payments/overview\",\n          \"payments/toncoin\",\n          \"payments/jettons\"\n        ]\n      },\n      {\n        \"group\": \"Standard contracts\",\n        \"pages\": [\n          {\n            \"group\": \"Wallets\",\n            \"pages\": [\n              \"standard/wallets/how-it-works\",\n              \"standard/wallets/mnemonics\",\n              \"standard/wallets/comparison\",\n              \"standard/wallets/performance\",\n              \"standard/wallets/interact\",\n              \"standard/wallets/history\",\n              \"standard/wallets/v4\",\n              {\n                \"group\": \"V5\",\n                \"pages\": [\n                  \"standard/wallets/v5\",\n                  \"standard/wallets/v5-api\"\n                ]\n              },\n              {\n                \"group\": \"Highload Wallets\",\n                \"pages\": [\n                  \"standard/wallets/highload/overview\",\n                  {\n                    \"group\": \"Highload Wallet v3\",\n                    \"pages\": [\n                      \"standard/wallets/highload/v3/create\",\n                      \"standard/wallets/highload/v3/send-single-transfer\",\n                      \"standard/wallets/highload/v3/send-batch-transfers\",\n                      \"standard/wallets/highload/v3/verify-is-processed\",\n                      \"standard/wallets/highload/v3/specification\"\n                    ]\n                  },\n                  {\n                    \"group\": \"Highload Wallet v2\",\n                    \"pages\": [\n                      \"standard/wallets/highload/v2/specification\"\n                    ]\n                  }\n                ]\n              },\n              \"standard/wallets/lockup\",\n              {\n                \"group\": \"Preprocessed Wallet V2\",\n                \"pages\": [\n                  \"standard/wallets/preprocessed-v2/specification\",\n                  \"standard/wallets/preprocessed-v2/interact\"\n                ]\n              },\n              \"standard/wallets/restricted\"\n            ]\n          },\n          {\n            \"group\": \"Tokens\",\n            \"expanded\": true,\n            \"pages\": [\n              \"standard/tokens/overview\",\n              \"standard/tokens/metadata\",\n              {\n                \"group\": \"Jettons\",\n                \"pages\": [\n                  \"standard/tokens/jettons/overview\",\n                  \"standard/tokens/jettons/how-it-works\",\n                  \"standard/tokens/jettons/comparison\",\n                  \"standard/tokens/jettons/mintless/overview\",\n                  \"standard/tokens/jettons/mint\",\n                  \"standard/tokens/jettons/burn\",\n                  \"standard/tokens/jettons/find\",\n                  \"standard/tokens/jettons/transfer\",\n                  \"standard/tokens/jettons/wallet-data\",\n                  \"standard/tokens/jettons/supply-data\",\n                  \"standard/tokens/jettons/mintless/deploy\",\n                  \"standard/tokens/jettons/api\"\n                ]\n              },\n              {\n                \"group\": \"NFT\",\n                \"pages\": [\n                  \"standard/tokens/nft/overview\",\n                  \"standard/tokens/nft/how-it-works\",\n                  \"standard/tokens/nft/deploy\",\n                  \"standard/tokens/nft/transfer\",\n                  \"standard/tokens/nft/metadata\",\n                  \"standard/tokens/nft/verify\",\n                  \"standard/tokens/nft/comparison\",\n                  \"standard/tokens/nft/sbt\",\n                  \"standard/tokens/nft/reference\",\n                  \"standard/tokens/nft/nft-2.0\",\n                  \"standard/tokens/nft/api\"\n                ]\n              },\n              \"standard/tokens/airdrop\"\n            ]\n          },\n          \"standard/vesting\"\n        ]\n      },\n      {\n        \"group\": \"Contract development\",\n        \"pages\": [\n          \"contract-dev/first-smart-contract\",\n          {\n            \"group\": \"IDEs and editor plugins\",\n            \"pages\": [\n              \"contract-dev/ide/overview\",\n              \"contract-dev/ide/vscode\",\n              \"contract-dev/ide/jetbrains\"\n            ]\n          },\n          {\n            \"group\": \"Development environment\",\n            \"pages\": [\n              \"contract-dev/blueprint/overview\",\n              \"contract-dev/blueprint/develop\",\n              \"contract-dev/blueprint/deploy\",\n              \"contract-dev/blueprint/coverage\",\n              \"contract-dev/blueprint/benchmarks\",\n              \"contract-dev/blueprint/config\",\n              \"contract-dev/blueprint/cli\",\n              \"contract-dev/blueprint/api\"\n            ]\n          },\n          {\n            \"group\": \"Testing\",\n            \"pages\": [\n              \"contract-dev/testing/overview\",\n              \"contract-dev/testing/reference\"\n            ]\n          },\n          \"contract-dev/debug\",\n          \"contract-dev/signing\",\n          \"contract-dev/contract-sharding\",\n          \"contract-dev/security\",\n          \"contract-dev/gas\",\n          \"contract-dev/on-chain-jetton-processing\",\n          \"contract-dev/using-on-chain-libraries\",\n          \"contract-dev/random\",\n          \"contract-dev/upgrades\",\n          \"contract-dev/vanity\",\n          \"contract-dev/zero-knowledge\"\n        ]\n      },\n      {\n        \"group\": \"Languages\",\n        \"pages\": [\n          {\n            \"group\": \"Tolk\",\n            \"tag\": \"recommended\",\n            \"pages\": [\n              \"languages/tolk/overview\",\n              \"languages/tolk/basic-syntax\",\n              \"languages/tolk/idioms-conventions\",\n              \"languages/tolk/examples\",\n              {\n                \"group\": \"Type system\",\n                \"pages\": [\n                  \"languages/tolk/types/list-of-types\",\n                  \"languages/tolk/types/numbers\",\n                  \"languages/tolk/types/booleans\",\n                  \"languages/tolk/types/address\",\n                  \"languages/tolk/types/cells\",\n                  \"languages/tolk/types/strings\",\n                  \"languages/tolk/types/structures\",\n                  \"languages/tolk/types/aliases\",\n                  \"languages/tolk/types/generics\",\n                  \"languages/tolk/types/enums\",\n                  \"languages/tolk/types/nullable\",\n                  \"languages/tolk/types/unions\",\n                  \"languages/tolk/types/tensors\",\n                  \"languages/tolk/types/tuples\",\n                  \"languages/tolk/types/maps\",\n                  \"languages/tolk/types/callables\",\n                  \"languages/tolk/types/void-never\",\n                  \"languages/tolk/types/type-checks-and-casts\",\n                  \"languages/tolk/types/overall-tvm-stack\",\n                  \"languages/tolk/types/overall-serialization\"\n                ]\n              },\n              {\n                \"group\": \"Syntax details\",\n                \"pages\": [\n                  \"languages/tolk/syntax/variables\",\n                  \"languages/tolk/syntax/conditions-loops\",\n                  \"languages/tolk/syntax/exceptions\",\n                  \"languages/tolk/syntax/functions-methods\",\n                  \"languages/tolk/syntax/structures-fields\",\n                  \"languages/tolk/syntax/pattern-matching\",\n                  \"languages/tolk/syntax/mutability\",\n                  \"languages/tolk/syntax/operators\",\n                  \"languages/tolk/syntax/imports\"\n                ]\n              },\n              {\n                \"group\": \"Language features\",\n                \"pages\": [\n                  \"languages/tolk/features/message-handling\",\n                  \"languages/tolk/features/contract-storage\",\n                  \"languages/tolk/features/contract-getters\",\n                  \"languages/tolk/features/message-sending\",\n                  \"languages/tolk/features/auto-serialization\",\n                  \"languages/tolk/features/lazy-loading\",\n                  \"languages/tolk/features/jetton-payload\",\n                  \"languages/tolk/features/standard-library\",\n                  \"languages/tolk/features/asm-functions\",\n                  \"languages/tolk/features/compiler-optimizations\"\n                ]\n              },\n              {\n                \"group\": \"Migrating from FunC\",\n                \"pages\": [\n                  \"languages/tolk/from-func/tolk-vs-func\",\n                  \"languages/tolk/from-func/stdlib-comparison\",\n                  \"languages/tolk/from-func/converter\"\n                ]\n              },\n              \"languages/tolk/changelog\"\n            ]\n          },\n          {\n            \"group\": \"TL-B\",\n            \"pages\": [\n              \"languages/tl-b/overview\",\n              \"languages/tl-b/syntax-and-semantics\",\n              \"languages/tl-b/simple-examples\",\n              \"languages/tl-b/complex-and-non-trivial-examples\",\n              \"languages/tl-b/tep-examples\",\n              \"languages/tl-b/tooling\"\n            ]\n          },\n          {\n            \"group\": \"Fift\",\n            \"pages\": [\n              \"languages/fift/overview\",\n              \"languages/fift/fift-and-tvm-assembly\",\n              \"languages/fift/deep-dive\",\n              \"languages/fift/multisig\",\n              \"languages/fift/whitepaper\"\n            ]\n          },\n          {\n            \"group\": \"FunC\",\n            \"pages\": [\n              \"languages/func/overview\",\n              \"languages/func/cookbook\",\n              {\n                \"group\": \"Language\",\n                \"expanded\": true,\n                \"pages\": [\n                  \"languages/func/comments\",\n                  \"languages/func/types\",\n                  \"languages/func/literals\",\n                  \"languages/func/operators\",\n                  \"languages/func/expressions\",\n                  \"languages/func/statements\",\n                  {\n                    \"group\": \"Program declarations\",\n                    \"expanded\": true,\n                    \"pages\": [\n                      \"languages/func/declarations-overview\",\n                      \"languages/func/functions\",\n                      \"languages/func/special-functions\",\n                      \"languages/func/asm-functions\",\n                      \"languages/func/global-variables\",\n                      \"languages/func/compiler-directives\"\n                    ]\n                  },\n                  \"languages/func/built-ins\",\n                  \"languages/func/dictionaries\"\n                ]\n              },\n              {\n                \"group\": \"Libraries\",\n                \"expanded\": true,\n                \"pages\": [\n                  \"languages/func/stdlib\",\n                  \"languages/func/libraries\"\n                ]\n              },\n              \"languages/func/changelog\",\n              \"languages/func/known-issues\"\n            ]\n          },\n          \"languages/tact\"\n        ]\n      },\n      {\n        \"group\": \"TVM: TON Virtual Machine\",\n        \"pages\": [\n          \"tvm/overview\",\n          {\n            \"group\": \"Tools\",\n            \"pages\": [\n              \"tvm/tools/txtracer\",\n              \"tvm/tools/retracer\",\n              \"tvm/tools/tvm-explorer\",\n              \"tvm/tools/ton-decompiler\"\n            ]\n          },\n          \"tvm/instructions\",\n          \"tvm/builders-and-slices\",\n          \"tvm/continuations\",\n          \"tvm/registers\",\n          \"tvm/gas\",\n          \"tvm/initialization\",\n          \"tvm/exit-codes\",\n          \"tvm/get-method\"\n        ]\n      },\n      {\n        \"group\": \"Blockchain foundations\",\n        \"pages\": [\n          {\n            \"group\": \"Serialization\",\n            \"pages\": [\n              \"foundations/serialization/cells\",\n              \"foundations/serialization/library\",\n              \"foundations/serialization/merkle\",\n              \"foundations/serialization/merkle-update\",\n              \"foundations/serialization/pruned\",\n              \"foundations/serialization/boc\"\n            ]\n          },\n          {\n            \"group\": \"Addresses\",\n            \"pages\": [\n              \"foundations/addresses/overview\",\n              \"foundations/addresses/formats\",\n              \"foundations/addresses/serialize\",\n              \"foundations/addresses/derive\"\n            ]\n          },\n          {\n            \"group\": \"Messages & Transactions\",\n            \"pages\": [\n              \"foundations/messages/overview\",\n              \"foundations/messages/internal\",\n              \"foundations/messages/external-in\",\n              \"foundations/messages/external-out\",\n              \"foundations/messages/deploy\",\n              \"foundations/messages/modes\",\n              \"foundations/messages/ordinary-tx\"\n            ]\n          },\n          {\n            \"group\": \"Actions\",\n            \"pages\": [\n              \"foundations/actions/overview\",\n              \"foundations/actions/send\",\n              \"foundations/actions/reserve\",\n              \"foundations/actions/set-code\",\n              \"foundations/actions/change-library\"\n            ]\n          },\n          {\n            \"group\": \"Consensus\",\n            \"pages\": [\n              \"foundations/consensus/catchain-visualizer\"\n            ]\n          },\n          \"foundations/status\",\n          \"foundations/phases\",\n          \"foundations/fees\",\n          \"foundations/traces\",\n          \"foundations/shards\",\n          \"foundations/limits\",\n          \"foundations/config\",\n          \"foundations/services\",\n          {\n            \"group\": \"Merkle proofs\",\n            \"pages\": [\n              \"foundations/proofs/overview\",\n              \"foundations/proofs/verifying-liteserver-proofs\"\n            ]\n          },\n          \"foundations/system\",\n          \"foundations/precompiled\",\n          {\n            \"group\": \"Whitepapers\",\n            \"pages\": [\n              \"foundations/whitepapers/overview\",\n              \"foundations/whitepapers/tvm\",\n              \"foundations/whitepapers/tblkch\",\n              \"foundations/whitepapers/ton\",\n              \"foundations/whitepapers/catchain\"\n            ]\n          },\n          \"foundations/glossary\"\n        ]\n      },\n      {\n        \"group\": \"Contribute\",\n        \"pages\": [\n          \"contribute/style-guide\",\n          {\n            \"group\": \"Components and snippets\",\n            \"pages\": [\n              \"contribute/snippets/overview\",\n              \"contribute/snippets/aside\",\n              \"contribute/snippets/image\",\n              \"contribute/snippets/filetree\"\n            ]\n          }\n        ]\n      }\n    ]\n  },\n  \"footer\": {\n    \"socials\": {\n      \"github\": \"https://github.com/ton-blockchain\",\n      \"x\": \"https://twitter.com/ton_blockchain\",\n      \"telegram\": \"https://t.me/addlist/1r5Vcb8eljk5Yzcy\"\n    }\n  },\n  \"errors\": {\n    \"404\": {\n      \"redirect\": false,\n      \"title\": \"Page not found\",\n      \"description\": \"Maybe you were looking for one of these pages below?\"\n    }\n  },\n  \"seo\": {\n    \"metatags\": {\n      \"canonical\": \"https://docs.ton.org\"\n    }\n  },\n  \"redirects\": [\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/introduction\",\n      \"destination\": \"/start-here\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/ton-ecosystem/wallet-apps\",\n      \"destination\": \"https://old-docs.ton.org/v3/concepts/dive-into-ton/ton-ecosystem/wallet-apps\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/ton-ecosystem/explorers-in-ton\",\n      \"destination\": \"/ecosystem/explorers/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/participate/explorers\",\n      \"destination\": \"/ecosystem/explorers/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/ton-ecosystem/blockchain-tech\",\n      \"destination\": \"/foundations/services\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/go-from-ethereum/blockchain-services\",\n      \"destination\": \"/foundations/services\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/ton-blockchain/overview\",\n      \"destination\": \"/start-here\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/ton-blockchain/blockchain-of-blockchains\",\n      \"destination\": \"/start-here\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/ton-blockchain/asynchrony\",\n      \"destination\": \"/start-here\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/ton-blockchain/sharding\",\n      \"destination\": \"/start-here\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/ton-blockchain/accounts\",\n      \"destination\": \"/start-here\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/ton-blockchain/addresses\",\n      \"destination\": \"/foundations/addresses/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/ton-blockchain/smart-contract-addresses\",\n      \"destination\": \"/foundations/addresses/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/ton-blockchain/smart-contracts\",\n      \"destination\": \"/start-here\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/ton-blockchain/operations\",\n      \"destination\": \"/start-here\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/ton-blockchain/ton-virtual-machine\",\n      \"destination\": \"/start-here\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/ton-blockchain/cells\",\n      \"destination\": \"/foundations/serialization/cells\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/ton-blockchain/cells-as-data-storage\",\n      \"destination\": \"/foundations/serialization/cells\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/ton-blockchain/nodes\",\n      \"destination\": \"/start-here\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/ton-blockchain/network\",\n      \"destination\": \"/start-here\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/ton-blockchain/ton-networking\",\n      \"destination\": \"/start-here\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/go-from-ethereum/difference-of-blockchains\",\n      \"destination\": \"/from-ethereum\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/go-from-ethereum/solidity-vs-func\",\n      \"destination\": \"/from-ethereum\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/go-from-ethereum/tvm-vs-evm\",\n      \"destination\": \"/from-ethereum\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/go-from-ethereum/blockchain-comparison\",\n      \"destination\": \"/from-ethereum\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/dive-into-ton/ton-blockchain/blockchain-comparison\",\n      \"destination\": \"/from-ethereum\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/security-measures\",\n      \"destination\": \"https://old-docs.ton.org/v3/concepts/security-measures\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/educational-resources\",\n      \"destination\": \"/more-tutorials\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/concepts/glossary\",\n      \"destination\": \"/foundations/glossary\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/introduction\",\n      \"destination\": \"/start-here\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/getting-started\",\n      \"destination\": \"/start-here\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/overview\",\n      \"destination\": \"/contract-dev/first-smart-contract\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/getting-started/javascript\",\n      \"destination\": \"/contract-dev/blueprint/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/getting-started/ide-plugins\",\n      \"destination\": \"/contract-dev/ide/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/getting-started/testnet\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/smart-contracts/getting-started/testnet\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/addresses/address\",\n      \"destination\": \"/foundations/addresses/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/addresses/address-formats\",\n      \"destination\": \"/foundations/addresses/formats\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/addresses/address-states\",\n      \"destination\": \"/foundations/status\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/message-management/messages-and-transactions\",\n      \"destination\": \"/foundations/messages/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/message-management/sending-messages\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/smart-contracts/message-management/sending-messages\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/message-management/internal-messages\",\n      \"destination\": \"/foundations/messages/internal\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/message-management/external-messages\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/smart-contracts/message-management/external-messages\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/message-management/non-bounceable-messages\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/smart-contracts/message-management/non-bounceable-messages\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/message-management/message-modes-cookbook\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/smart-contracts/message-management/message-modes-cookbook\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/message-management/ecosystem-messages-layout\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/smart-contracts/message-management/ecosystem-messages-layout\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/transaction-fees/fees\",\n      \"destination\": \"/contract-dev/gas\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/transaction-fees/fees-low-level\",\n      \"destination\": \"/foundations/fees\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/transaction-fees/accept-message-effects\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/smart-contracts/transaction-fees/accept-message-effects\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/transaction-fees/forward-fees\",\n      \"destination\": \"/foundations/fees#forward-fee\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/shards/shards-intro\",\n      \"destination\": \"/foundations/shards\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/shards/infinity-sharding-paradigm\",\n      \"destination\": \"/foundations/shards\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/limits\",\n      \"destination\": \"/foundations/limits\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/contracts-specs/wallet-contracts\",\n      \"destination\": \"/standard/wallets/comparison\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/contracts-specs/highload-wallet\",\n      \"destination\": \"/standard/wallets/highload/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/contracts-specs/vesting-contract\",\n      \"destination\": \"/standard/vesting\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/contracts-specs/governance\",\n      \"destination\": \"/foundations/system\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/contracts-specs/nominator-pool\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/smart-contracts/contracts-specs/nominator-pool\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/contracts-specs/single-nominator-pool\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/smart-contracts/contracts-specs/single-nominator-pool\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/contracts-specs/precompiled-contracts\",\n      \"destination\": \"/foundations/precompiled\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/contracts-specs/examples\",\n      \"destination\": \"/more-tutorials\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/tolk/overview\",\n      \"destination\": \"/languages/tolk/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/tolk/environment-setup\",\n      \"destination\": \"contract-dev/first-smart-contract\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/tolk/counter-smart-contract\",\n      \"destination\": \"contract-dev/first-smart-contract\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/tolk/language-guide\",\n      \"destination\": \"languages/tolk/basic-syntax\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/tolk/tolk-vs-func/in-short\",\n      \"destination\": \"/languages/tolk/from-func/tolk-vs-func\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/tolk/tolk-vs-func/in-detail\",\n      \"destination\": \"/languages/tolk/from-func/tolk-vs-func\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/tolk/tolk-vs-func/mutability\",\n      \"destination\": \"/languages/tolk/syntax/mutability\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/tolk/tolk-vs-func/stdlib\",\n      \"destination\": \"/languages/tolk/from-func/stdlib-comparison\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/tolk/tolk-vs-func/pack-to-from-cells\",\n      \"destination\": \"languages/tolk/features/auto-serialization\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/tolk/tolk-vs-func/create-message\",\n      \"destination\": \"languages/tolk/features/message-sending\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/tolk/tolk-vs-func/lazy-loading\",\n      \"destination\": \"languages/tolk/features/lazy-loading\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/tolk/changelog\",\n      \"destination\": \"languages/tolk/changelog\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/func/overview\",\n      \"destination\": \"/languages/func/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/func/cookbook\",\n      \"destination\": \"/languages/func/cookbook\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/func/docs/types\",\n      \"destination\": \"/languages/func/types\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/func/docs/comments\",\n      \"destination\": \"/languages/func/comments\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/func/docs/literals_identifiers\",\n      \"destination\": \"/languages/func/literals\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/func/docs/functions\",\n      \"destination\": \"/languages/func/functions\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/func/docs/global_variables\",\n      \"destination\": \"/languages/func/global-variables\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/func/docs/compiler_directives\",\n      \"destination\": \"/languages/func/compiler-directives\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/func/docs/statements\",\n      \"destination\": \"/languages/func/statements\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/func/docs/builtins\",\n      \"destination\": \"/languages/func/built-ins\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/func/docs/dictionaries\",\n      \"destination\": \"/languages/func/dictionaries\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/func/docs/stdlib\",\n      \"destination\": \"/languages/func/stdlib\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/func/libraries\",\n      \"destination\": \"/languages/func/libraries\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/func/changelog\",\n      \"destination\": \"/languages/func/changelog\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/fift/overview\",\n      \"destination\": \"/languages/fift/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/fift/fift-and-tvm-assembly\",\n      \"destination\": \"/languages/fift/fift-and-tvm-assembly\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/fift/fift-deep-dive\",\n      \"destination\": \"/languages/fift/deep-dive\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/tact\",\n      \"destination\": \"/languages/tact\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/dapps/dapps-overview\",\n      \"destination\": \"/\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/dapps/assets/toncoin\",\n      \"destination\": \"/standard/wallets/how-it-works\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/dapps/assets/jetton\",\n      \"destination\": \"/standard/tokens/jettons/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/dapps/assets/nft\",\n      \"destination\": \"/standard/tokens/nft/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/dapps/assets/nft-2.0\",\n      \"destination\": \"/standard/tokens/nft/nft-2.0\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/dapps/assets/usdt\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/dapps/assets/usdt\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/dapps/assets/extra-currencies\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/dapps/assets/extra-currencies\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/dapps/assets/overview\",\n      \"destination\": \"/standard/tokens/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/dapps/defi/nft\",\n      \"destination\": \"/standard/tokens/nft/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/dapps/defi/subscriptions\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/dapps/defi/subscriptions\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/dapps/defi/ton-payments\",\n      \"destination\": \"/foundations/services\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/infra/oracles/overview\",\n      \"destination\": \"/ecosystem/oracles/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/infra/oracles/pyth\",\n      \"destination\": \"/ecosystem/oracles/pyth\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/infra/oracles/redstone\",\n      \"destination\": \"/ecosystem/oracles/redstone\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/nodes/overview\",\n      \"destination\": \"/ecosystem/nodes/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/nodes/validation/collators\",\n      \"destination\": \"/ecosystem/nodes/cpp/mytonctrl/collator\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/nodes/validation/staking-incentives\",\n      \"destination\": \"/ecosystem/nodes/cpp/mytonctrl/liquid-staking\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/dapps/proofs\",\n      \"destination\": \"/foundations/proofs/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/dapps/basic-proofing-concepts\",\n      \"destination\": \"/foundations/proofs/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/nodes/mytonctrl/overview\",\n      \"destination\": \"/ecosystem/nodes/cpp/mytonctrl/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/nodes/mytonctrl/commands\",\n      \"destination\": \"/ecosystem/nodes/cpp/mytonctrl/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/nodes/mytonctrl/status\",\n      \"destination\": \"/ecosystem/nodes/cpp/setup-mytonctrl#verify-services-and-synchronization\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/nodes/mytonctrl/errors\",\n      \"destination\": \"/ecosystem/nodes/cpp/setup-mytonctrl#troubleshooting-imports\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/infra/bridges/toncoin\",\n      \"destination\": \"/ecosystem/bridges\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/infra/bridges/toncoin-addresses\",\n      \"destination\": \"/ecosystem/bridges\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/network/global-config\",\n      \"destination\": \"/ecosystem/nodes/cpp/setup-mytonctrl\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/network/config-params/overview\",\n      \"destination\": \"/foundations/config\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/network/config-params/update\",\n      \"destination\": \"/foundations/system#config\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/network/config-params/extra-currency\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/network/config-params/extra-currency\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/network/protocols/adnl/overview\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/network/protocols/adnl/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/network/protocols/adnl/low-level\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/network/protocols/adnl/low-level\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/learn/overviews/adnl\",\n      \"destination\": \"https://old-docs.ton.org/learn/overviews/adnl\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/network/protocols/adnl/tcp\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/network/protocols/adnl/tcp\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/network/protocols/adnl/udp\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/network/protocols/adnl/udp\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/network/protocols/dht/overview\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/network/protocols/dht/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/network/protocols/dht/deep-dive\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/network/protocols/dht/deep-dive\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/network/protocols/rldp\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/network/protocols/rldp\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/network/protocols/overlay\",\n      \"destination\": \"/ecosystem/nodes/cpp/mytonctrl/custom-overlays\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/tlb/overview\",\n      \"destination\": \"/languages/tl-b/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/tl-b\",\n      \"destination\": \"/languages/tl-b/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/tlb/types\",\n      \"destination\": \"/languages/tl-b/syntax-and-semantics\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/tlb/crc32\",\n      \"destination\": \"https://en.wikipedia.org/wiki/Cyclic_redundancy_check\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/tlb/tools\",\n      \"destination\": \"/languages/tl-b/tooling\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/layout/messages\",\n      \"destination\": \"/foundations/messages/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/layout/transactions\",\n      \"destination\": \"/foundations/phases\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/layout/blocks\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/data-formats/layout/blocks\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/cells/overview\",\n      \"destination\": \"/foundations/serialization/cells\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/cells/exotic\",\n      \"destination\": \"/foundations/serialization/cells#kinds-of-cells\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/cells/library\",\n      \"destination\": \"/foundations/serialization/library\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/cells/serialization\",\n      \"destination\": \"/foundations/serialization/boc\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/tl\",\n      \"destination\": \"https://core.telegram.org/mtproto/TL\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/tvm/overview\",\n      \"destination\": \"/tvm/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/learn/tvm-instructions/tvm_overview\",\n      \"destination\": \"/tvm/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/tvm/initialization\",\n      \"destination\": \"/tvm/initialization\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/tvm/exit-codes\",\n      \"destination\": \"/tvm/exit-codes\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/learn/tvm-instructions/tvm_exit_codes\",\n      \"destination\": \"/tvm/exit-codes\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/tvm/instructions\",\n      \"destination\": \"/tvm/instructions\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/tvm/specification/runvm\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/tvm/specification/runvm\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/tvm/changelog/tvm-upgrade-2025-02\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/tvm/changelog/tvm-upgrade-2025-02\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/tvm/changelog/tvm-upgrade-2024-04\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/tvm/changelog/tvm-upgrade-2024-04\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/tvm/changelog/tvm-upgrade-2023-07\",\n      \"destination\": \"https://old-docs.ton.org/v3/documentation/tvm/changelog/tvm-upgrade-2023-07\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/learn/tvm-instructions/tvm-upgrade\",\n      \"destination\": \"https://old-docs.ton.org/learn/tvm-instructions/tvm-upgrade\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/whitepapers/overview\",\n      \"destination\": \"/foundations/whitepapers/overview#overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/faq\",\n      \"destination\": \"/get-support\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/quick-start/getting-started\",\n      \"destination\": \"/contract-dev/first-smart-contract\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/quick-start/blockchain-interaction/reading-from-network\",\n      \"destination\": \"/contract-dev/first-smart-contract\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/quick-start/blockchain-interaction/writing-to-network\",\n      \"destination\": \"/contract-dev/first-smart-contract\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/quick-start/developing-smart-contracts/setup-environment\",\n      \"destination\": \"/contract-dev/first-smart-contract\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/quick-start/developing-smart-contracts/func-tolk-folder/blueprint-sdk-overview\",\n      \"destination\": \"/contract-dev/first-smart-contract\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/quick-start/developing-smart-contracts/func-tolk-folder/storage-and-get-methods\",\n      \"destination\": \"/contract-dev/first-smart-contract\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/quick-start/developing-smart-contracts/func-tolk-folder/processing-messages\",\n      \"destination\": \"/contract-dev/first-smart-contract\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/quick-start/developing-smart-contracts/func-tolk-folder/deploying-to-network\",\n      \"destination\": \"/contract-dev/first-smart-contract\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/quick-start/developing-smart-contracts/tact-folder/tact-blueprint-sdk-overview\",\n      \"destination\": \"/contract-dev/first-smart-contract\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/quick-start/developing-smart-contracts/tact-folder/tact-storage-and-get-methods\",\n      \"destination\": \"/contract-dev/first-smart-contract\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/quick-start/developing-smart-contracts/tact-folder/tact-deploying-to-network\",\n      \"destination\": \"/contract-dev/first-smart-contract\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/get-started-with-ton\",\n      \"destination\": \"/contract-dev/first-smart-contract\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/onboarding-challenge\",\n      \"destination\": \"/contract-dev/first-smart-contract\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/hello-world\",\n      \"destination\": \"/contract-dev/first-smart-contract\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/smat-contracts-guidelines\",\n      \"destination\": \"/contract-dev/debug\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/guidelines\",\n      \"destination\": \"/contract-dev/debug\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/get-methods\",\n      \"destination\": \"/contract-dev/blueprint/deploy#executing-get-methods\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/fee-calculation\",\n      \"destination\": \"/foundations/fees\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/testing\",\n      \"destination\": \"/contract-dev/testing/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/testing/overview\",\n      \"destination\": \"/contract-dev/testing/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/testing/tonstarter\",\n      \"destination\": \"/contract-dev/testing/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/testing/blueprint-config\",\n      \"destination\": \"/contract-dev/blueprint/config\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/testing/writing-test-examples\",\n      \"destination\": \"/contract-dev/testing/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/testing/collect-contract-gas-metric\",\n      \"destination\": \"/contract-dev/blueprint/benchmarks\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/security-measures\",\n      \"destination\": \"/contract-dev/security\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/security/overview\",\n      \"destination\": \"/contract-dev/security\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/security/common-vulnerabilities\",\n      \"destination\": \"/contract-dev/security\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/security/secure-programming\",\n      \"destination\": \"/contract-dev/security\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/security/things-to-focus\",\n      \"destination\": \"/contract-dev/security\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/security/ton-hack-challenge-1\",\n      \"destination\": \"https://github.com/ton-blockchain/hack-challenge-1\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/security/random-number-generation\",\n      \"destination\": \"/contract-dev/random\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/security/random\",\n      \"destination\": \"/contract-dev/random\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/how-to\",\n      \"destination\": \"/\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/compile-from-sources\",\n      \"destination\": \"https://github.com/ton-blockchain/ton#build-ton-blockchain\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/howto/compile/compilation-instructions\",\n      \"destination\": \"https://github.com/ton-blockchain/ton#build-ton-blockchain\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/howto/compile/instructions-low-memory\",\n      \"destination\": \"https://github.com/ton-blockchain/ton#build-ton-blockchain\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/howto/multisig\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/smart-contracts/howto/multisig\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/howto/multisig-js\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/smart-contracts/howto/multisig-js\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/howto/airdrop-claim-best-practice\",\n      \"destination\": \"/standard/tokens/airdrop\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/howto/shard-optimization\",\n      \"destination\": \"/contract-dev/contract-sharding\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/howto/wallet\",\n      \"destination\": \"/standard/wallets/how-it-works\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/howto/nominator-pool\",\n      \"destination\": \"/ecosystem/nodes/cpp/mytonctrl/pools\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/smart-contracts/howto/single-nominator-pool\",\n      \"destination\": \"/ecosystem/nodes/cpp/mytonctrl/pools\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/dapps\",\n      \"destination\": \"/\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/overview\",\n      \"destination\": \"/\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/cookbook\",\n      \"destination\": \"/\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/transactions/overview\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/dapps/transactions/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/transactions/foundations-of-blockchain\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/dapps/transactions/foundations-of-blockchain\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/transactions/message-driven-execution\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/dapps/transactions/message-driven-execution\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/transactions/hash-based-tracking\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/dapps/transactions/hash-based-tracking\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/transactions/api-based-retrieval\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/dapps/transactions/api-based-retrieval\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/transactions/explore-transactions\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/dapps/transactions/explore-transactions\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/api-sdk\",\n      \"destination\": \"https://old-docs.ton.org/guidelines/api-sdk\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/apis-sdks/overview\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/dapps/apis-sdks/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/apis-sdks/api-types\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/dapps/apis-sdks/api-types\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/apis-sdks/ton-http-apis\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/dapps/apis-sdks/ton-http-apis\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/apis-sdks/sdk\",\n      \"destination\": \"/ecosystem/sdks\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/apis-sdks/ton-adnl-apis\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/dapps/apis-sdks/ton-adnl-apis\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/apis-sdks/analytics-and-data\",\n      \"destination\": \"/ecosystem/analytics#analytics-and-data-providers\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/tutorials-and-examples\",\n      \"destination\": \"https://old-docs.ton.org/guidelines/tutorials-and-examples\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/tutorials/jetton-airdrop\",\n      \"destination\": \"/standard/tokens/airdrop\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/apis-sdks/api-keys\",\n      \"destination\": \"/ecosystem/api/toncenter/get-api-key\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/apis-sdks/getblock-ton-api\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/dapps/apis-sdks/getblock-ton-api\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/tutorials/nft-minting-guide\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/dapps/tutorials/nft-minting-guide\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/tutorials/mint-your-first-token\",\n      \"destination\": \"/standard/tokens/jettons/mint\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/tutorials/zero-knowledge-proofs\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/dapps/tutorials/zero-knowledge-proofs\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/tutorials/web3-game-example\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/dapps/tutorials/web3-game-example\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/tg-bot-examples\",\n      \"destination\": \"https://old-docs.ton.org/guidelines/tg-bot-examples\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/tutorials/telegram-bot-examples/accept-payments-in-a-telegram-bot\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/dapps/tutorials/telegram-bot-examples/accept-payments-in-a-telegram-bot\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/payment-processing/accept-payments-in-a-telegram-bot\",\n      \"destination\": \"https://old-docs.ton.org/develop/dapps/payment-processing/accept-payments-in-a-telegram-bot\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/tutorials/telegram-bot-examples/accept-payments-in-a-telegram-bot-2\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/dapps/tutorials/telegram-bot-examples/accept-payments-in-a-telegram-bot-2\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/payment-processing/accept-payments-in-a-telegram-bot-2\",\n      \"destination\": \"https://old-docs.ton.org/develop/dapps/payment-processing/accept-payments-in-a-telegram-bot-2\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/tutorials/telegram-bot-examples/accept-payments-in-a-telegram-bot-js\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/dapps/tutorials/telegram-bot-examples/accept-payments-in-a-telegram-bot-js\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/tma\",\n      \"destination\": \"/ecosystem/tma/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/tma/overview\",\n      \"destination\": \"/ecosystem/tma/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/tma-guidelines\",\n      \"destination\": \"/ecosystem/tma/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/tma/guidelines/testing-apps\",\n      \"destination\": \"/ecosystem/tma/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/tma/guidelines/publishing\",\n      \"destination\": \"/ecosystem/tma/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/tma/guidelines/monetization\",\n      \"destination\": \"/ecosystem/tma/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/tma/guidelines/tips-and-tricks\",\n      \"destination\": \"/ecosystem/tma/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/tma-tutorials-and-examples\",\n      \"destination\": \"/ecosystem/tma/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/tma/tutorials/step-by-step-guide\",\n      \"destination\": \"/ecosystem/tma/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/tma/tutorials/app-examples\",\n      \"destination\": \"/ecosystem/tma/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/tma/tutorials/design-guidelines\",\n      \"destination\": \"/ecosystem/tma/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/advanced-asset-processing\",\n      \"destination\": \"/payments/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/asset-processing/payments-processing\",\n      \"destination\": \"/payments/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/asset-processing/jettons\",\n      \"destination\": \"/standard/tokens/jettons/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/asset-processing/mintless-jettons\",\n      \"destination\": \"/standard/tokens/jettons/mintless/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/asset-processing/compressed-nfts\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/dapps/asset-processing/compressed-nfts\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/asset-processing/mass-mint-tools\",\n      \"destination\": \"/standard/tokens/nft/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/nft-processing\",\n      \"destination\": \"/standard/tokens/nft/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/asset-processing/nft-processing/nfts\",\n      \"destination\": \"/standard/tokens/nft/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/dapps/asset-processing/nft-processing/metadata-parsing\",\n      \"destination\": \"/standard/tokens/nft/metadata\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/nodes-guidelines\",\n      \"destination\": \"/ecosystem/nodes/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/overview\",\n      \"destination\": \"/ecosystem/nodes/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/running-nodes\",\n      \"destination\": \"/ecosystem/nodes/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/running-nodes/archive-node\",\n      \"destination\": \"/ecosystem/nodes/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/running-nodes/full-node\",\n      \"destination\": \"/ecosystem/nodes/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/running-nodes/liteserver-node\",\n      \"destination\": \"/ecosystem/nodes/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/running-nodes/validator-node\",\n      \"destination\": \"/ecosystem/nodes/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/running-nodes/collators-validators\",\n      \"destination\": \"/ecosystem/nodes/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/running-nodes/staking-with-nominator-pools\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/nodes/running-nodes/staking-with-nominator-pools\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/running-nodes/run-mytonctrl-docker\",\n      \"destination\": \"/ecosystem/nodes/cpp/setup-mytonctrl\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/running-nodes/running-a-local-ton\",\n      \"destination\": \"/ecosystem/nodes/cpp/setup-mylocalton\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/running-nodes/secure-guidelines\",\n      \"destination\": \"/ecosystem/nodes/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/maintenance-guidelines\",\n      \"destination\": \"/ecosystem/nodes/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/maintenance-guidelines/mytonctrl-backup-restore\",\n      \"destination\": \"/ecosystem/nodes/cpp/mytonctrl/backups\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/maintenance-guidelines/mytonctrl-validator-standby\",\n      \"destination\": \"/ecosystem/nodes/cpp/mytonctrl/backups\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/maintenance-guidelines/mytonctrl-private-alerting\",\n      \"destination\": \"/ecosystem/nodes/cpp/mytonctrl/alerting\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/maintenance-guidelines/mytonctrl-prometheus\",\n      \"destination\": \"/ecosystem/nodes/cpp/integrating-with-prometheus\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/maintenance-guidelines/mytonctrl-remote-controller\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/nodes/maintenance-guidelines/mytonctrl-remote-controller\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/custom-overlays\",\n      \"destination\": \"/ecosystem/nodes/cpp/mytonctrl/custom-overlays\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/nodes-troubleshooting\",\n      \"destination\": \"/ecosystem/nodes/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/node-maintenance-and-security\",\n      \"destination\": \"/ecosystem/nodes/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/monitoring/performance-monitoring\",\n      \"destination\": \"/ecosystem/nodes/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/persistent-states\",\n      \"destination\": \"/ecosystem/nodes/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/nodes/faq\",\n      \"destination\": \"/ecosystem/nodes/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/ton-connect\",\n      \"destination\": \"/ecosystem/ton-connect/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/overview\",\n      \"destination\": \"/ecosystem/ton-connect/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/how-ton-connect-works\",\n      \"destination\": \"/ecosystem/ton-connect/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/guidelines/how-ton-connect-works\",\n      \"destination\": \"/ecosystem/ton-connect/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/quick-start\",\n      \"destination\": \"/ecosystem/ton-connect/dapp\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/dapp-guide\",\n      \"destination\": \"/ecosystem/ton-connect/dapp\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/creating-manifest\",\n      \"destination\": \"/ecosystem/ton-connect/manifest\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/install-ton-connect\",\n      \"destination\": \"/ecosystem/ton-connect/dapp\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/frameworks/react\",\n      \"destination\": \"/ecosystem/ton-connect/dapp\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/frameworks/web\",\n      \"destination\": \"/ecosystem/ton-connect/dapp\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/frameworks/python\",\n      \"destination\": \"/ecosystem/ton-connect/dapp\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/verifying-signed-in-users\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/ton-connect/verifying-signed-in-users\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/cookbook\",\n      \"destination\": \"/ecosystem/ton-connect/dapp\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/cookbook/cells\",\n      \"destination\": \"/ecosystem/ton-connect/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/cookbook/ton-transfer\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/ton-connect/cookbook/ton-transfer\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/cookbook/jetton-transfer\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/ton-connect/cookbook/jetton-transfer\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/cookbook/nft-transfer\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/ton-connect/cookbook/nft-transfer\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/guidelines/transaction-by-external-message\",\n      \"destination\": \"/ecosystem/ton-connect/message-lookup\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/wallet\",\n      \"destination\": \"/ecosystem/ton-connect/wallet\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/guidelines/developers\",\n      \"destination\": \"/ecosystem/ton-connect/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/advanced\",\n      \"destination\": \"/ecosystem/ton-connect/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/web3-guidelines\",\n      \"destination\": \"/foundations/services\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/web3/overview\",\n      \"destination\": \"/foundations/services\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/ton-dns\",\n      \"destination\": \"https://old-docs.ton.org/guidelines/ton-dns\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/web3/ton-dns/dns\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/web3/ton-dns/dns\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/web3/ton-dns/subresolvers\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/web3/ton-dns/subresolvers\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/proxy-and-sites\",\n      \"destination\": \"https://old-docs.ton.org/guidelines/proxy-and-sites\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/web3/ton-proxy-sites/how-to-run-ton-site\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/web3/ton-proxy-sites/how-to-run-ton-site\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/web3/ton-proxy-sites/ton-sites-for-applications\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/web3/ton-proxy-sites/ton-sites-for-applications\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/web3/ton-proxy-sites/connect-with-ton-proxy\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/web3/ton-proxy-sites/connect-with-ton-proxy\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/web3/ton-proxy-sites/how-to-open-any-ton-site\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/web3/ton-proxy-sites/how-to-open-any-ton-site\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/web3/ton-proxy-sites/site-and-domain-management\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/web3/ton-proxy-sites/site-and-domain-management\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/web3/ton-proxy-sites/running-your-own-ton-proxy\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/web3/ton-proxy-sites/running-your-own-ton-proxy\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/ton-storage\",\n      \"destination\": \"https://old-docs.ton.org/guidelines/ton-storage\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/web3/ton-storage/storage-daemon\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/web3/ton-storage/storage-daemon\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/web3/ton-storage/storage-provider\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/web3/ton-storage/storage-provider\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/web3/ton-storage/storage-faq\",\n      \"destination\": \"https://old-docs.ton.org/v3/guidelines/web3/ton-storage/storage-faq\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/contribute/README\",\n      \"destination\": \"https://old-docs.ton.org/v3/contribute/README\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/contribute\",\n      \"destination\": \"https://old-docs.ton.org/v3/contribute\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/contribute/style-guide\",\n      \"destination\": \"/contribute/style-guide\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/contribute/content-standardization\",\n      \"destination\": \"https://old-docs.ton.org/v3/contribute/content-standardization\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/contribute/typography\",\n      \"destination\": \"https://old-docs.ton.org/v3/contribute/typography\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/contribute/localization-program/translation-style-guide\",\n      \"destination\": \"https://old-docs.ton.org/v3/contribute/localization-program/translation-style-guide\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/contribute/maintainers\",\n      \"destination\": \"https://old-docs.ton.org/v3/contribute/maintainers\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/participate/nodes/node-types\",\n      \"destination\": \"/v3/documentation/nodes/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/learn/glossary\",\n      \"destination\": \"/v3/concepts/glossary\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/participate/web3/site-management\",\n      \"destination\": \"/v3/guidelines/web3/ton-proxy-sites/site-and-domain-management\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/ethereum-to-ton/difference-of-blockchains\",\n      \"destination\": \"/v3/concepts/dive-into-ton/go-from-ethereum/difference-of-blockchains\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/ethereum-to-ton/solidity-vs-func\",\n      \"destination\": \"/v3/concepts/dive-into-ton/go-from-ethereum/solidity-vs-func\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/ethereum-to-ton/tvm-vs-evm\",\n      \"destination\": \"/v3/concepts/dive-into-ton/go-from-ethereum/tvm-vs-evm\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/learn/academy/academy-overview\",\n      \"destination\": \"/v3/concepts/educational-resources\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/howto/subresolvers\",\n      \"destination\": \"/v3/guidelines/web3/ton-dns/subresolvers\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/ton-connect\",\n      \"destination\": \"/v3/guidelines/ton-connect/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/ton-connect/manifest\",\n      \"destination\": \"/v3/guidelines/ton-connect/creating-manifest\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/ton-connect/transactions\",\n      \"destination\": \"/v3/guidelines/ton-connect/cookbook/ton-transfer\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/ton-connect/sign\",\n      \"destination\": \"/v3/guidelines/ton-connect/verifying-signed-in-users\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/ton-connect/integration\",\n      \"destination\": \"/v3/guidelines/ton-connect/frameworks/react\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/ton-connect/business\",\n      \"destination\": \"/v3/guidelines/ton-connect/overview#why-use-ton-connect\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/ton-connect/security\",\n      \"destination\": \"/v3/guidelines/ton-connect/overview#why-use-ton-connect\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/business/ton-connect-for-business\",\n      \"destination\": \"/v3/guidelines/ton-connect/overview#why-use-ton-connect\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/business/ton-connect-for-security\",\n      \"destination\": \"/v3/guidelines/ton-connect/overview#why-use-ton-connect\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/business/ton-connect-comparison\",\n      \"destination\": \"/v3/guidelines/ton-connect/overview#why-use-ton-connect\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/apis/adnl\",\n      \"destination\": \"/v3/guidelines/dapps/apis-sdks/ton-adnl-apis\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/apis/api-key\",\n      \"destination\": \"/v3/guidelines/dapps/apis-sdks/api-keys\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/tutorials/building-web3-game\",\n      \"destination\": \"/v3/guidelines/dapps/tutorials/web3-game-example\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/tutorials/collection-minting\",\n      \"destination\": \"/v3/guidelines/dapps/tutorials/nft-minting-guide\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/tutorials/jetton-minter\",\n      \"destination\": \"/v3/guidelines/dapps/tutorials/mint-your-first-token\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/tutorials/simple-zk-on-ton\",\n      \"destination\": \"/v3/guidelines/dapps/tutorials/zero-knowledge-proofs\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/tutorials/accept-payments-in-a-telegram-bot\",\n      \"destination\": \"/v3/guidelines/dapps/tutorials/telegram-bot-examples/accept-payments-in-a-telegram-bot\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/tutorials/accept-payments-in-a-telegram-bot-2\",\n      \"destination\": \"/v3/guidelines/dapps/tutorials/telegram-bot-examples/accept-payments-in-a-telegram-bot-2\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/tutorials/accept-payments-in-a-telegram-bot-js\",\n      \"destination\": \"/v3/guidelines/dapps/tutorials/telegram-bot-examples/accept-payments-in-a-telegram-bot-js\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/telegram-apps/testing-apps\",\n      \"destination\": \"/v3/guidelines/dapps/tma/guidelines/testing-apps\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/telegram-apps/publishing\",\n      \"destination\": \"/v3/guidelines/dapps/tma/guidelines/publishing\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/telegram-apps/monetization\",\n      \"destination\": \"/v3/guidelines/dapps/tma/guidelines/monetization\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/telegram-apps/tips-and-tricks\",\n      \"destination\": \"/v3/guidelines/dapps/tma/guidelines/tips-and-tricks\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/telegram-apps/design-guidelines\",\n      \"destination\": \"/v3/guidelines/dapps/tma/tutorials/design-guidelines\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/asset-processing/\",\n      \"destination\": \"/v3/guidelines/dapps/asset-processing/payments-processing\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/asset-processing/mintless-jettons\",\n      \"destination\": \"/v3/guidelines/dapps/asset-processing/mintless-jettons\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/asset-processing/mass-mint-tools\",\n      \"destination\": \"/v3/guidelines/dapps/asset-processing/mass-mint-tools\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/asset-processing/metadata\",\n      \"destination\": \"/v3/guidelines/dapps/asset-processing/nft-processing/metadata-parsing\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/asset-processing/nfts\",\n      \"destination\": \"/v3/guidelines/dapps/asset-processing/nft-processing/nfts\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/guidelines/get-methods\",\n      \"destination\": \"/v3/guidelines/smart-contracts/get-methods\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/security/secure-programming\",\n      \"destination\": \"/v3/guidelines/smart-contracts/security/secure-programming\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/security/random\",\n      \"destination\": \"/v3/guidelines/smart-contracts/security/random\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/security/things-to-focus\",\n      \"destination\": \"/v3/guidelines/smart-contracts/security/things-to-focus\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/security/ton-hack-challenge-1\",\n      \"destination\": \"/v3/guidelines/smart-contracts/security/ton-hack-challenge-1\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/guidelines/random-number-generation\",\n      \"destination\": \"/v3/guidelines/smart-contracts/security/random-number-generation\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/howto/compile\",\n      \"destination\": \"/v3/guidelines/smart-contracts/howto/compile/compilation-instructions\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/howto/compile-swap\",\n      \"destination\": \"/v3/guidelines/smart-contracts/howto/compile/instructions-low-memory\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/tutorials/multisig\",\n      \"destination\": \"/v3/guidelines/smart-contracts/howto/multisig\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/tutorials/multisig-js\",\n      \"destination\": \"/v3/guidelines/smart-contracts/howto/multisig-js\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/tutorials/airdrop-claim-best-practice\",\n      \"destination\": \"/v3/guidelines/smart-contracts/howto/airdrop-claim-best-practice\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/tutorials/shard-optimization\",\n      \"destination\": \"/v3/guidelines/smart-contracts/howto/shard-optimization\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/tutorials/wallet\",\n      \"destination\": \"/v3/guidelines/smart-contracts/howto/wallet\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/howto/faq\",\n      \"destination\": \"/v3/documentation/faq\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/blockchain/sharding-lifecycle\",\n      \"destination\": \"/v3/documentation/smart-contracts/shards/infinity-sharding-paradigm\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/blockchain/shards\",\n      \"destination\": \"/v3/documentation/smart-contracts/shards/shards-intro\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/environment/testnet\",\n      \"destination\": \"/v3/documentation/smart-contracts/getting-started/testnet\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/environment/ide-plugins\",\n      \"destination\": \"/v3/documentation/smart-contracts/getting-started/ide-plugins\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/sdk/javascript\",\n      \"destination\": \"/v3/documentation/smart-contracts/getting-started/javascript\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/guidelines/message-delivery-guarantees\",\n      \"destination\": \"/v3/documentation/smart-contracts/message-management/messages-and-transactions\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/guidelines/ecosystem-messages-layout\",\n      \"destination\": \"/v3/documentation/smart-contracts/message-management/ecosystem-messages-layout\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/messages\",\n      \"destination\": \"/v3/documentation/smart-contracts/message-management/sending-messages\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/guidelines/message-modes-cookbook\",\n      \"destination\": \"/v3/documentation/smart-contracts/message-management/message-modes-cookbook\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/guidelines/external-messages\",\n      \"destination\": \"/v3/documentation/smart-contracts/message-management/external-messages\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/guidelines/internal-messages\",\n      \"destination\": \"/v3/documentation/smart-contracts/message-management/internal-messages\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/guidelines/non-bounceable-messages\",\n      \"destination\": \"/v3/documentation/smart-contracts/message-management/non-bounceable-messages\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/howto/fees-low-level\",\n      \"destination\": \"/v3/documentation/smart-contracts/transaction-fees/fees-low-level\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/guidelines/accept\",\n      \"destination\": \"/v3/documentation/smart-contracts/transaction-fees/accept-message-effects\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/guidelines/processing\",\n      \"destination\": \"/v3/documentation/smart-contracts/transaction-fees/forward-fees\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/governance\",\n      \"destination\": \"/v3/documentation/smart-contracts/contracts-specs/governance\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/core-contracts/precompiled\",\n      \"destination\": \"/v3/documentation/smart-contracts/contracts-specs/precompiled-contracts\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/examples\",\n      \"destination\": \"/v3/documentation/smart-contracts/contracts-specs/examples\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/func/overview\",\n      \"destination\": \"/v3/documentation/smart-contracts/func/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/tolk/overview\",\n      \"destination\": \"/v3/documentation/smart-contracts/tolk/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/func/cookbook\",\n      \"destination\": \"/v3/documentation/smart-contracts/func/cookbook\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/libraries\",\n      \"destination\": \"/v3/documentation/smart-contracts/func/libraries\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/func/types\",\n      \"destination\": \"/v3/documentation/smart-contracts/func/docs/types\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/func/stdlib\",\n      \"destination\": \"/v3/documentation/smart-contracts/func/docs/stdlib\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/func/statements\",\n      \"destination\": \"/v3/documentation/smart-contracts/func/docs/statements\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/func/literals_identifiers\",\n      \"destination\": \"/v3/documentation/smart-contracts/func/docs/literals_identifiers\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/func/global_variables\",\n      \"destination\": \"/v3/documentation/smart-contracts/func/docs/global_variables\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/func/functions\",\n      \"destination\": \"/v3/documentation/smart-contracts/func/docs/functions\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/func/dictionaries\",\n      \"destination\": \"/v3/documentation/smart-contracts/func/docs/dictionaries\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/func/compiler_directives\",\n      \"destination\": \"/v3/documentation/smart-contracts/func/docs/compiler_directives\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/func/comments\",\n      \"destination\": \"/v3/documentation/smart-contracts/func/docs/comments\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/func/builtins\",\n      \"destination\": \"/v3/documentation/smart-contracts/func/docs/builtins\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/fift/fift-and-tvm-assembly\",\n      \"destination\": \"/v3/documentation/smart-contracts/fift/fift-and-tvm-assembly\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/fift/fift-deep-dive\",\n      \"destination\": \"/v3/documentation/smart-contracts/fift/fift-deep-dive\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/fift/overview\",\n      \"destination\": \"/v3/documentation/smart-contracts/fift/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/defi/nft\",\n      \"destination\": \"/v3/documentation/dapps/defi/nft\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/defi/subscriptions\",\n      \"destination\": \"/v3/documentation/dapps/defi/subscriptions\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/defi/ton-payments\",\n      \"destination\": \"/v3/documentation/dapps/defi/ton-payments\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/asset-processing/overview\",\n      \"destination\": \"/v3/documentation/dapps/assets/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/asset-processing/usdt\",\n      \"destination\": \"/v3/documentation/dapps/assets/usdt\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/oracles/about_blockchain_oracles\",\n      \"destination\": \"/v3/documentation/infra/oracles/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/oracles/red_stone\",\n      \"destination\": \"/v3/documentation/infra/oracles/redstone\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/research-and-development/minter-flow\",\n      \"destination\": \"/v3/documentation/network/config-params/extra-currency\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/howto/network-configs\",\n      \"destination\": \"/v3/documentation/network/global-config\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/howto/config-params\",\n      \"destination\": \"/v3/documentation/network/config-params/update\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/howto/blockchain-configs\",\n      \"destination\": \"/v3/documentation/network/config-params/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/learn/networking/adnl\",\n      \"destination\": \"/v3/documentation/network/protocols/adnl/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/learn/networking/low-level-adnl\",\n      \"destination\": \"/v3/documentation/network/protocols/adnl/low-level\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/network/adnl-tcp\",\n      \"destination\": \"/v3/documentation/network/protocols/adnl/tcp\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/network/adnl-udp\",\n      \"destination\": \"/v3/documentation/network/protocols/adnl/udp\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/learn/networking/ton-dht\",\n      \"destination\": \"/v3/documentation/network/protocols/dht/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/network/dht\",\n      \"destination\": \"/v3/documentation/network/protocols/dht/deep-dive\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/network/overlay\",\n      \"destination\": \"/v3/documentation/network/protocols/overlay\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/network/rldp\",\n      \"destination\": \"/v3/documentation/network/protocols/rldp\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/data-formats/tl-b-language\",\n      \"destination\": \"/v3/documentation/data-formats/tlb/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/data-formats/tl-b-types\",\n      \"destination\": \"/v3/documentation/data-formats/tlb/types\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/data-formats/tlb-ide\",\n      \"destination\": \"/v3/documentation/smart-contracts/getting-started/ide-plugins\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/tlb/tlb-ide\",\n      \"destination\": \"/v3/documentation/smart-contracts/getting-started/ide-plugins\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/data-formats/tlb-tools\",\n      \"destination\": \"/v3/documentation/data-formats/tlb/tools\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/data-formats/block-layout\",\n      \"destination\": \"/v3/documentation/data-formats/layout/blocks\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/data-formats/cell-boc\",\n      \"destination\": \"/v3/documentation/data-formats/cells/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/data-formats/crc32\",\n      \"destination\": \"/v3/documentation/data-formats/tlb/crc32\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/data-formats/exotic-cells\",\n      \"destination\": \"/v3/documentation/data-formats/cells/exotic\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/data-formats/library-cells\",\n      \"destination\": \"/v3/documentation/data-formats/cells/library\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/data-formats/msg-tlb\",\n      \"destination\": \"/v3/documentation/data-formats/layout/messages\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/data-formats/proofs\",\n      \"destination\": \"/v3/documentation/dapps/proofs\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/data-formats/transaction-layout\",\n      \"destination\": \"/v3/documentation/data-formats/layout/transactions\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/data-formats/tl\",\n      \"destination\": \"/v3/documentation/data-formats/tl\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/research-and-development/boc\",\n      \"destination\": \"/v3/documentation/data-formats/cells/serialization\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/learn/tvm-instructions/tvm-overview\",\n      \"destination\": \"/v3/documentation/tvm/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/learn/tvm-instructions/tvm-initialization\",\n      \"destination\": \"/v3/documentation/tvm/initialization\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/learn/tvm-instructions/tvm-exit-codes\",\n      \"destination\": \"/v3/documentation/tvm/exit-codes\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/learn/tvm-instructions/tvm-upgrade-2023-07\",\n      \"destination\": \"/v3/documentation/tvm/changelog/tvm-upgrade-2023-07\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/learn/tvm-instructions/fee-calculation-instructions\",\n      \"destination\": \"/v3/documentation/tvm/changelog/tvm-upgrade-2024-04\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/learn/tvm-instructions/instructions\",\n      \"destination\": \"/v3/documentation/tvm/instructions\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/learn/docs\",\n      \"destination\": \"/v3/documentation/whitepapers/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/contribute/localization-program/translation-style-guide\",\n      \"destination\": \"/v3/contribute/localization-program/translation-style-guide\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/contribute/maintainers\",\n      \"destination\": \"/v3/contribute/maintainers\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/contribute/participate\",\n      \"destination\": \"/v3/contribute/participate\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/contribute/participate\",\n      \"destination\": \"https://old-docs.ton.org/v3/contribute/participate\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/contribute\",\n      \"destination\": \"/v3/contribute\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/apis/getblock-ton-api\",\n      \"destination\": \"/v3/guidelines/dapps/apis-sdks/getblock-ton-api\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/func/changelog\",\n      \"destination\": \"/v3/documentation/smart-contracts/func/changelog\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/fee-calculation\",\n      \"destination\": \"/v3/guidelines/smart-contracts/fee-calculation\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/testing/writing-test-examples\",\n      \"destination\": \"/v3/guidelines/smart-contracts/testing/writing-test-examples\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/testing/overview\",\n      \"destination\": \"/v3/guidelines/smart-contracts/testing/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/guidelines\",\n      \"destination\": \"/v3/guidelines/smart-contracts/guidelines\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/security/README\",\n      \"destination\": \"/v3/guidelines/smart-contracts/security/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/README\",\n      \"destination\": \"/v3/documentation/smart-contracts/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/README\",\n      \"destination\": \"/v3/guidelines/dapps/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/infra/nodes/mytonctrl/mytonctrl-alerting\",\n      \"destination\": \"/v3/guidelines/nodes/maintenance-guidelines/mytonctrl-private-alerting\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/asset-processing/jettons\",\n      \"destination\": \"/v3/guidelines/dapps/asset-processing/jettons\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/apis/sdk\",\n      \"destination\": \"/v3/guidelines/dapps/apis-sdks/sdk\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/cookbook\",\n      \"destination\": \"/v3/guidelines/dapps/cookbook\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/telegram-apps/README\",\n      \"destination\": \"/v3/guidelines/dapps/tma/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/telegram-apps/app-examples\",\n      \"destination\": \"/v3/guidelines/dapps/tma/tutorials/app-examples\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/telegram-apps/step-by-step-guide\",\n      \"destination\": \"/v3/guidelines/dapps/tma/tutorials/step-by-step-guide\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/ton-connect/developers\",\n      \"destination\": \"/v3/guidelines/ton-connect/guidelines/developers\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/ton-connect/overview\",\n      \"destination\": \"/v3/guidelines/ton-connect/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/ton-connect/react\",\n      \"destination\": \"/v3/guidelines/ton-connect/frameworks/react\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/ton-connect/wallet\",\n      \"destination\": \"/v3/guidelines/ton-connect/wallet\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/ton-connect/web\",\n      \"destination\": \"/v3/guidelines/ton-connect/frameworks/web\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/tutorials/how-to-run-ton-site\",\n      \"destination\": \"/v3/guidelines/web3/ton-proxy-sites/how-to-run-ton-site\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/get-started-with-ton\",\n      \"destination\": \"/v3/guidelines/get-started-with-ton\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/smart-contracts/fees\",\n      \"destination\": \"/v3/documentation/smart-contracts/transaction-fees/fees\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/guidelines/integration-with-javascript-sdk\",\n      \"destination\": \"/v3/guidelines/ton-connect/frameworks/web\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/guidelines/preparing-messages\",\n      \"destination\": \"/v3/guidelines/ton-connect/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/integrate-dapp\",\n      \"destination\": \"/guidelines/dapp-guide\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/guidelines/integrate-with-ton\",\n      \"destination\": \"/guidelines/ton-connect\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/guidelines/ton-connect/guidelines/sending-messages\",\n      \"destination\": \"/v3/guidelines/ton-connect/cookbook/ton-transfer\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/develop/dapps/apis/toncenter\",\n      \"destination\": \"/v3/guidelines/dapps/apis-sdks/api-types\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/tvm/tvm-overview\",\n      \"destination\": \"/v3/documentation/tvm/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/tvm/tvm-initialization\",\n      \"destination\": \"/v3/documentation/tvm/initialization\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/tvm/tvm-exit-codes\",\n      \"destination\": \"/v3/documentation/tvm/exit-codes\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/tlb/cell-boc\",\n      \"destination\": \"/v3/documentation/data-formats/cells/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/tlb/exotic-cells\",\n      \"destination\": \"/v3/documentation/data-formats/cells/exotic\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/tlb/library-cells\",\n      \"destination\": \"/v3/documentation/data-formats/cells/library\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/tlb/canonical-cell-serialization\",\n      \"destination\": \"/v3/documentation/data-formats/cells/serialization\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/tlb/msg-tlb\",\n      \"destination\": \"/v3/documentation/data-formats/layout/messages\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/tlb/transaction-layout\",\n      \"destination\": \"/v3/documentation/data-formats/layout/transactions\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/tlb/block-layout\",\n      \"destination\": \"/v3/documentation/data-formats/layout/blocks\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/tlb/tl-b-language\",\n      \"destination\": \"/v3/documentation/data-formats/tlb/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/tlb/tl-b-types\",\n      \"destination\": \"/v3/documentation/data-formats/tlb/types\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/tlb/tlb-tools\",\n      \"destination\": \"/v3/documentation/data-formats/tlb/tools\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/network/protocols/dht/ton-dht\",\n      \"destination\": \"/v3/documentation/network/protocols/dht/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/network/protocols/dht/dht-deep-dive\",\n      \"destination\": \"/v3/documentation/network/protocols/dht/deep-dive\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/network/protocols/adnl/low-level-adnl\",\n      \"destination\": \"/v3/documentation/network/protocols/adnl/low-level\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/network/protocols/adnl/adnl-tcp\",\n      \"destination\": \"/v3/documentation/network/protocols/adnl/tcp\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/network/protocols/adnl/adnl-udp\",\n      \"destination\": \"/v3/documentation/network/protocols/adnl/udp\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/network/configs/blockchain-configs\",\n      \"destination\": \"/v3/documentation/network/config-params/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/network/configs/config-params\",\n      \"destination\": \"/v3/documentation/network/config-params/update\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/infra/minter-flow\",\n      \"destination\": \"/v3/documentation/network/config-params/extra-currency\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/network/configs/network-configs\",\n      \"destination\": \"/v3/documentation/network/global-config\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/dapps/oracles/about_blockchain_oracles\",\n      \"destination\": \"/v3/documentation/infra/oracles/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/dapps/oracles/pyth\",\n      \"destination\": \"/v3/documentation/infra/oracles/pyth\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/dapps/oracles/red_stone\",\n      \"destination\": \"/v3/documentation/infra/oracles/redstone\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/infra/crosschain/overview\",\n      \"destination\": \"/v3/documentation/infra/bridges/toncoin\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/infra/crosschain/bridge-addresses\",\n      \"destination\": \"/v3/documentation/infra/bridges/toncoin-addresses\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/infra/nodes/mytonctrl/mytonctrl-overview\",\n      \"destination\": \"/v3/documentation/nodes/mytonctrl/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/infra/nodes/node-commands\",\n      \"destination\": \"/v3/documentation/nodes/mytonctrl/commands\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/infra/nodes/mytonctrl/mytonctrl-status\",\n      \"destination\": \"/v3/documentation/nodes/mytonctrl/status\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/infra/nodes/mytonctrl/mytonctrl-errors\",\n      \"destination\": \"/v3/documentation/nodes/mytonctrl/errors\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/infra/nodes/node-types\",\n      \"destination\": \"/v3/documentation/nodes/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/infra/nodes/validation/staking-incentives\",\n      \"destination\": \"/v3/documentation/nodes/validation/staking-incentives\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/infra/nodes/validation/collators\",\n      \"destination\": \"/v3/documentation/nodes/validation/collators\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/tlb/proofs\",\n      \"destination\": \"/v3/documentation/dapps/proofs\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/data-formats/tlb/basic-proofing-concepts\",\n      \"destination\": \"/v3/documentation/dapps/basic-proofing-concepts\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/ton-documentation\",\n      \"destination\": \"/v3/documentation/introduction\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/v3/documentation/smart-contracts/addresses\",\n      \"destination\": \"/v3/documentation/smart-contracts/addresses/address\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/participate/network-maintenance/staking-incentives\",\n      \"destination\": \"/v3/documentation/nodes/validation/staking-incentives\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/participate/run-nodes/full-node\",\n      \"destination\": \"/v3/guidelines/nodes/running-nodes/full-node\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/contract-dev/using-onchain-libraries\",\n      \"destination\": \"/contract-dev/using-on-chain-libraries\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/languages/tolk/from-func/in-short\",\n      \"destination\": \"/languages/tolk/from-func/tolk-vs-func\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/languages/tolk/from-func/in-detail\",\n      \"destination\": \"/languages/tolk/from-func/tolk-vs-func\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/languages/tolk/from-func/tolk-vs-tlb\",\n      \"destination\": \"https://blog.ton.org/tolk-vs-tl-b\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/languages/tolk/from-func/mutability\",\n      \"destination\": \"/languages/tolk/syntax/mutability\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/languages/tolk/from-func/stdlib\",\n      \"destination\": \"/languages/tolk/from-func/stdlib-comparison\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/languages/tolk/from-func/stdlib-fc\",\n      \"destination\": \"/languages/tolk/from-func/stdlib-comparison\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/languages/tolk/from-func/create-message\",\n      \"destination\": \"/languages/tolk/features/message-sending\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/languages/tolk/from-func/lazy-loading\",\n      \"destination\": \"/languages/tolk/features/lazy-loading\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/languages/tolk/from-func/pack\",\n      \"destination\": \"/languages/tolk/features/auto-serialization\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/languages/tolk/environment-setup\",\n      \"destination\": \"/languages/tolk/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/languages/tolk/counter-smart-contract\",\n      \"destination\": \"/languages/tolk/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/languages/tolk/language-guide\",\n      \"destination\": \"/languages/tolk/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/ecosystem/node/mytonctrl/integrating-with-prometheus\",\n      \"destination\": \"/ecosystem/nodes/cpp/integrating-with-prometheus\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/participate/wallets/contracts\",\n      \"destination\": \"/standard/wallets/comparison\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/ecosystem/node/overview\",\n      \"destination\": \"/ecosystem/nodes/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/ecosystem/node/setup-mytonctrl\",\n      \"destination\": \"/ecosystem/nodes/cpp/setup-mytonctrl\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/ecosystem/node/run-validator\",\n      \"destination\": \"/ecosystem/nodes/cpp/run-validator\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/ecosystem/node/integrating-with-prometheus\",\n      \"destination\": \"/ecosystem/nodes/cpp/integrating-with-prometheus\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/ecosystem/node/setup-mylocalton\",\n      \"destination\": \"/ecosystem/nodes/cpp/setup-mylocalton\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/ecosystem/node/mytonctrl/:slug*\",\n      \"destination\": \"/ecosystem/nodes/cpp/mytonctrl/:slug*\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/ecosystem/ton-connect/appkit/:slug*\",\n      \"destination\": \"/ecosystem/appkit/:slug*\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/ecosystem/ton-connect/walletkit/:slug*\",\n      \"destination\": \"/ecosystem/walletkit/:slug*\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/ecosystem/tma/mate/telegram-apps-mate\",\n      \"destination\": \"/ecosystem/tma/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/ecosystem/tma/mate/getting-started\",\n      \"destination\": \"/ecosystem/tma/overview\",\n      \"permanent\": true\n    },\n    {\n      \"source\": \"/ecosystem/tma/mate/hosting\",\n      \"destination\": \"/ecosystem/tma/overview\",\n      \"permanent\": true\n    }\n  ]\n}\n"
  },
  {
    "path": "ecosystem/ai/mcp.mdx",
    "content": "---\ntitle: \"MCP servers\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n[Model Context Protocol](https://modelcontextprotocol.io/) (MCP) is an open-source standard for connecting AI applications to external systems, tools, and data sources. MCP servers expose specific capabilities to AI applications through standardized protocol interfaces.\n\n<Aside\n  type=\"caution\"\n>\n  Code generation with the MCP server may result in financial loss. Never trust the responses completely. Always validate in local testing environments.\n</Aside>\n\n## Search documentation\n\nDocumentation generates and exposes a remote MCP server as a search tool for AI applications to query. Access it at `https://docs.ton.org/mcp`.\n\n<Aside type=\"note\">\n  To avoid context overlapping and prevent misuse, use either this server or `@ton/mcp`, not both.\n</Aside>\n\nUse the contextual menu at the top of this page to copy the MCP server URL or follow a deep link to connect from Cursor or VS Code directly.\n\nFor Claude Code, run the following command:\n\n```shell\nclaude mcp add --transport http TonDocs https://docs.ton.org/mcp\n```\n\nFor [OpenCode](https://opencode.ai/docs/config/#mcp-servers), use the following configuration:\n\n```json title=\"opencode.json\"\n{\n  \"$schema\": \"https://opencode.ai/config.json\",\n  \"mcp\": {\n    \"ton-docs\": {\n      \"type\": \"remote\",\n      \"url\": \"https://docs.ton.org/mcp\",\n      \"enabled\": true\n    }\n  }\n}\n```\n\n## Perform blockchain operations with `@ton/mcp`\n\n<Aside type=\"note\">\n  To avoid context overlapping and prevent misuse, use either this server or the [documentation search one](#search-documentation), not both.\n</Aside>\n\nThe [`@ton/mcp` server](https://github.com/ton-connect/kit/tree/main/packages/mcp) enables agents to operate with TON wallets and perform many common blockchain operations. It manages dangerous parts like private keys and signing, allowing agents to handle intents and confirmation flows safely. The server is built on top of [WalletKit](/ecosystem/walletkit/overview).\n\nThe latest alpha release is available on [npm](https://www.npmjs.com/package/@ton/mcp/v/0.1.15-alpha.0). Run it locally with the following command, passing CLI flags as needed.\n\n```shell\n# Latest alpha version\nnpx @ton/mcp@alpha\n```\n\n<Aside\n  type=\"caution\"\n>\n  The `@ton/mcp` is currently in a public <Badge size=\"xs\">alpha</Badge> version. Some behaviors and APIs might change in the future.\n</Aside>\n\n### Features\n\n- Balance queries: check Toncoin and jetton (token) balances, view transaction history\n- Transfers: send Toncoin, jettons, and NFTs to any TON address\n- Assets: list, inspect, and manage popular jettons or NFTs\n- Swaps: get quotes for token swaps via DEX aggregators\n- DNS: resolve TON DNS-compatible domains and perform reverse-lookup for addresses\n- Work with multiple stored wallets, active wallet selection, and local config-backed management tools\n- Agentic sub-wallet deployments: deploy additional agentic wallets from a root wallet\n- Multiple transports: standard I/O (default), multi-session HTTP server, and serverless\n\n### Quick start\n\nThe `@ton/mcp` supports two runtime modes. If neither `MNEMONIC` nor `PRIVATE_KEY` environment variables are set, the server starts in the **registry mode**, reading from a local config registry found at `~/.config/ton/config.json` or at `TON_CONFIG_PATH`, if available. Otherwise, server starts with one in-memory wallet in the **single-wallet** mode.\n\n```shell\n# Run as stdio MCP server in registry mode\n# MNEMONIC and PRIVATE_KEY are both unset\nnpx @ton/mcp@alpha\n\n# Run in registry mode with a custom config path\nTON_CONFIG_PATH=/path/to/config.json npx @ton/mcp@alpha\n\n# Run as stdio MCP server with mnemonic\nMNEMONIC=\"word1 word2 ...\" npx @ton/mcp@alpha\n\n# Run as HTTP server (port 3000)\nnpx @ton/mcp@alpha --http\n\n# Run as HTTP server on custom port\nnpx @ton/mcp@alpha --http 8080\n\n# Run with custom agentic wallet contract\nPRIVATE_KEY=\"0x.._YOUR_PRIVATE_KEY\" \\\nWALLET_VERSION=\"agentic\" \\\nAGENTIC_WALLET_ADDRESS=\"EQ.._WALLET_ADDRESS\" \\\nnpx @ton/mcp@alpha\n```\n\n### Usage with MCP clients\n\nFor Claude or Cursor, add:\n\n<CodeGroup>\n  ```json title=\"Registry mode\"\n  {\n    \"mcpServers\": {\n      \"ton\": {\n        \"command\": \"npx\",\n        \"args\": [\"-y\", \"@ton/mcp@alpha\"],\n        \"env\": {\n          \"TON_CONFIG_PATH\": \"/absolute/path/to/config.json\"\n        }\n      }\n    }\n  }\n  ```\n\n  ```json title=\"Single-wallet mode\"\n  {\n    \"mcpServers\": {\n      \"ton\": {\n        \"command\": \"npx\",\n        \"args\": [\"-y\", \"@ton/mcp@alpha\"],\n        \"env\": {\n          \"MNEMONIC\": \"word1 word2 word3 ...\",\n          \"PRIVATE_KEY\": \"0x.._YOUR_PRIVATE_KEY_HERE (optional, alternative to MNEMONIC)\"\n        }\n      }\n    }\n  }\n  ```\n</CodeGroup>\n\nFor HTTP mode, start the server and point the MCP client to the endpoint:\n\n```shell\nnpx @ton/mcp@alpha --http 3000\n# MCP endpoint: http://localhost:3000/mcp\n```\n\nHTTP mode keeps a separate MCP session (transport) per client session ID, so multiple clients can initialize and reconnect independently.\n\n### Environment variables\n\n| Variable                     | Default                                            | Description                                                                                                                                  |\n| ---------------------------- | :------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |\n| `NETWORK`                    | `mainnet`                                          | TON network and default env override target for `TONCENTER_API_KEY`. Use `mainnet` for production and `testnet` for development and testing. |\n| `MNEMONIC`                   |                                                    | Space-separated 24-word mnemonic phrase for single-wallet mode                                                                               |\n| `PRIVATE_KEY`                |                                                    | Hex-encoded private key: 32-byte seed or 64-byte (private + public key), alternative to mnemonic                                             |\n| `WALLET_VERSION`             | `v5r1`                                             | Wallet version to use in single-wallet mode (`v5r1`, `v4r2`, or `agentic`)                                                                   |\n| `AGENTIC_WALLET_ADDRESS`     |                                                    | Agentic wallet address (required for `WALLET_VERSION=agentic`, unless derived from init params)                                              |\n| `AGENTIC_WALLET_NFT_INDEX`   |                                                    | Agentic wallet NFT index or subwallet ID (`uint256`, optional)                                                                               |\n| `AGENTIC_COLLECTION_ADDRESS` | `EQByQ19qvWxW7VibSbGEgZiYMqilHY5y1a_eeSL2VaXhfy07` | Agentic collection address override for single-wallet mode                                                                                   |\n| `TONCENTER_API_KEY`          |                                                    | API key for TON Center (optional, for higher rate limits)                                                                                    |\n| `TON_CONFIG_PATH`            | `~/.config/ton/config.json`                        | Config path for registry mode                                                                                                                |\n| `AGENTIC_CALLBACK_BASE_URL`  |                                                    | Optional public base URL for agentic onboarding callbacks                                                                                    |\n| `AGENTIC_CALLBACK_HOST`      | `127.0.0.1`                                        | Host for the local callback server in stdio mode                                                                                             |\n| `AGENTIC_CALLBACK_PORT`      | random free port                                   | Port for the local callback server in stdio mode                                                                                             |\n"
  },
  {
    "path": "ecosystem/analytics.mdx",
    "content": "---\ntitle: \"Analytics and data providers\"\nsidebarTitle: \"Analytics\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nDevelopers often need to run analytical queries on top of on-chain data — for example, to track historical changes and aggregate data from multiple accounts.\n\nSince blockchains are not designed for analytical workloads, you need to build an indexing pipeline and run off-chain analytical queries.\n\nCreating such pipelines from scratch can be resource-consuming, so we recommend using one of the tools mentioned on this page.\n\n## Dune analytics\n\n[Dune analytics](https://dune.com/) is one of the leading platforms for running analytical queries and building dashboards. It comes with 100+ blockchain integrations, and TON is among them. Basically, one needs to be familiar with SQL language to write queries, but the [Dune AI](https://docs.dune.com/learning/how-tos/dune-ai-prompt-engineering) prompt engine allows users to start working with data even without SQL knowledge.\n\n### Raw and decoded tables\n\nDune analytics consumes data from the public [TON Data Lake](#public-data-lake) (see below) and comes with a variety of raw and decoded tables.\n\nThe [raw tables](https://dune.com/queries?category=canonical\\&namespace=ton) include:\n\n- [Blocks](https://docs.dune.com/data-catalog/ton/blocks)\n- [Transactions](https://docs.dune.com/data-catalog/ton/transactions)\n- [Messages](https://docs.dune.com/data-catalog/ton/messages) — includes raw body and `StateInit` data.\n- [Balances history](https://docs.dune.com/data-catalog/ton/balances_history) — allows you to get a precise point-in-time balance for any account.\n- [Jetton events](https://docs.dune.com/data-catalog/ton/jetton_events) — comes with transfers, burns, and mints.\n\n<Aside>\n  Since mints are not covered by the [TEP-74](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md) standard, it is not possible to reconstruct balances based solely on jetton events, so the balance history should be used.\n</Aside>\n\nApart from raw tables, there are decoded tables that allow you to work with high-level structures in a unified manner:\n\n- [NFT events](https://dune.com/queries?category=canonical\\&namespace=ton\\&id=ton.nft_events) — comprehensive source of NFT-related data, including\n  sales, transfers, and mints.\n- [DEX trades](https://docs.dune.com/data-catalog/ton/dex_trades) — includes a unified data model for DEX trades. The full list of\n  supported DEXs is available [here](https://github.com/ton-studio/ton-etl/blob/main/datalake/README.md#dex-trades).\n- [DEX pools](https://docs.dune.com/data-catalog/ton/dex_pools) — comes with the full history of DEX pool balances and TVL estimations.\n\nFinally, two tables with off-chain metadata are available:\n\n- [Jetton metadata](https://docs.dune.com/data-catalog/ton/jetton_metadata)\n- [NFT metadata](https://dune.com/queries?category=canonical\\&namespace=ton\\&id=ton.nft_metadata).\n\n### Bespoke data marts\n\nDune analytics allows projects to build bespoke data marts for each protocol — it is widely used for EVMs with the help of ABIs.\n\n#### Decoding raw data\n\nSince TON handles complex [data structures](/foundations/serialization/cells/) and doesn't have ABIs, a [special decoding framework](https://github.com/duneanalytics/spellbook/blob/main/dbt_subprojects/daily_spellbook/macros/project/ton/README.md) was created. It works on top of the [Spellbook](https://github.com/duneanalytics/spellbook) — a powerful tool for building custom tables with [`dbt`](https://github.com/dbt-labs/dbt-core) and Jinja macros. It helps decode important information from raw protocol message payloads.\n\nThe following protocols are decoded using this framework and serve as examples:\n\n- [EVAA](https://dune.com/queries?category=abstraction\\&namespace=evaa) ([implementation](https://github.com/duneanalytics/spellbook/tree/main/dbt_subprojects/daily_spellbook/models/evaa/ton))\n- [Affluent](https://dune.com/queries?category=abstraction\\&namespace=affluent) ([implementation](https://github.com/duneanalytics/spellbook/tree/main/dbt_subprojects/daily_spellbook/models/affluent/ton))\n- [StormTrade](https://dune.com/queries?category=abstraction\\&namespace=stormtrade) ([implementation](https://github.com/duneanalytics/spellbook/tree/main/dbt_subprojects/daily_spellbook/models/stormtrade/ton))\n- [TON DNS](https://dune.com/queries?category=abstraction\\&namespace=dns_ton) ([implementation](https://github.com/duneanalytics/spellbook/tree/main/dbt_subprojects/daily_spellbook/models/ton/dns))\n\n#### Custom views\n\nIn addition to decoding raw data, the Spellbook allows building custom materialized views. Some of them are widely used and maintained to be up to date:\n\n- [ton.prices\\_daily](https://dune.com/queries?category=abstraction\\&namespace=ton\\&id=ton.prices_daily) — prices calculated based on all other tables. The prices include jettons traded on DEXs, LP tokens for DEXs, perpetuals, tsUSDe, and other core assets. It is recommended to use this table if you need to build an estimation of assets denominated in TON or USD.\n- [ton.accounts](https://dune.com/queries?category=abstraction\\&namespace=ton\\&id=ton.accounts) — materialized view with information about all accounts. It comes with the latest TON balance, interface (if any), funding information, and other fields.\n- [ton.latest\\_balances](https://dune.com/queries?category=abstraction\\&namespace=ton\\&id=ton.latest_balances) — helper table to get the latest balances for TON and Jettons.\n\n<Aside>All tables mentioned above are updated daily.</Aside>\n\n### Getting started with Dune\n\nIf you're just starting to explore TON data on Dune, we recommend checking these articles first:\n\n<Columns cols={2}>\n  <Card\n    title=\"TON data quick start\"\n    arrow\n    href=\"https://dune.com/ton_foundation/ton-quick-start\"\n  />\n\n  <Card\n    title=\"TON on-chain data analysis: quickstart on Dune\"\n    arrow\n    href=\"https://blog.ton.org/ton-on-chain-data-analysis-dune\"\n  />\n\n  <Card\n    title=\"How to Analyze TON Users and Token Flows on Dune: A Practical Guide\"\n    arrow\n    href=\"https://blog.ton.org/how-to-analyze-ton-users-and-token-flows-on-dune\"\n  />\n</Columns>\n\nFor inspiration to build your own dashboards, check out these examples:\n\n<Columns cols={2}>\n  <Card\n    title=\"Application Activity\"\n    arrow\n    href=\"https://dune.com/ton_foundation/application-activity\"\n  />\n\n  <Card\n    title=\"TON & Ethena Boost Rewards Campaign\"\n    arrow\n    href=\"https://dune.com/ton_foundation/tonandethena-staking-rewards-campaign\"\n  />\n\n  <Card\n    title=\"Telegram Gifts Dashboard\"\n    arrow\n    href=\"https://dune.com/rdmcd/telegram-gifts\"\n  />\n</Columns>\n\n## Public Data Lake\n\nDune integration runs on the public data lake from the [TON-ETL](https://github.com/re-doubt/ton-etl/blob/main/datalake/README.md) project.\n\n[TON-ETL](https://github.com/re-doubt/ton-etl/blob/main/datalake/README.md) is built on top of [TON Center](https://github.com/toncenter) indexer and allows extraction of data from TON Node into data formats suitable for MPP (Massively Parallel Processing) engines: Presto, Apache Spark, etc.\n\n<Aside>\n  You can deploy it on your own infrastructure or use publicly available data from the S3 bucket: `s3://aws-public-blockchain/v1.1/ton/`. This dataset is part of the [AWS Public Blockchain Data](https://registry.opendata.aws/aws-public-blockchain/) project and is optimized for use within the AWS big data stack.\n\n  Examples of AWS Athena and AWS Bedrock integration can be found in this [article](https://repost.aws/articles/AR3ABC81yvTPW2ktfHiHPWIA/new-dataset-added-to-the-aws-public-blockchain-data-ton-the-open-network).\n</Aside>\n\nThe TON-ETL extracts raw data and performs decoding to create a unified view of high-level on-chain activity. The most important part is decoding DEX activity.\n\nThe decoding implementation must solve the following tasks:\n\n- Decoding of swap events. The code must check the authenticity of the swap. For example, you cannot rely on the opcode alone since anyone can generate messages with your opcode.\n- Extracting all swap-related fields: tokens sold and bought, amounts, query IDs, trader, router (if any), and pool.\n- Fetching pool reserves and LP token supply, if applicable.\n\nTo add support for a new DEX and decode its activity, you need to prepare a relevant PR on GitHub [to TON-ETL's repo](https://github.com/ton-studio/ton-etl). Use those past PRs as a reference: [BidAsk](https://github.com/ton-studio/ton-etl/pull/186), [CoffeeSwap](https://github.com/ton-studio/ton-etl/pull/171/files), [MemesLab](https://github.com/ton-studio/ton-etl/pull/144).\n\n## Real-time streams\n\nIn addition to bulk data export, TON-ETL provides real-time data streaming via Kafka. A [public endpoint](https://github.com/ton-studio/ton-etl/blob/main/datalake/README.md#near-real-time--data-streaming-via-pulic-kafka-topics) is available free of charge for non-profit projects.\n\nFor projects that don't meet the non-profit criteria or require an in-house solution, you can deploy the infrastructure yourself by:\n\n1. Running your own [TON node](/ecosystem/nodes/overview)\n1. Launching [ton-etl](https://github.com/re-doubt/ton-etl/blob/main/README.md)\n1. Setting up [ton-index-worker](https://github.com/ton-studio/ton-index-worker)\n\n## TON Labels\n\nWhile data availability and integrations are essential, building insightful dashboards requires enriching data with address labels.\n\nThe [TON Labels](https://github.com/ton-studio/ton-labels) project simplifies this process by providing a comprehensive taxonomy of addresses in TON Ecosystem. It covers active addresses across various categories, including centralized exchanges (CEXs), decentralized applications (dApps), and DeFi protocols.\n\nYou can access the latest labels either directly from [the build branch](https://github.com/ton-studio/ton-labels/blob/build/assets.json) or through Dune analytics using the [`dune.ton_foundation.dataset_labels`](https://dune.com/queries?category=uploaded_data\\&id=dune.ton_foundation.dataset_labels) table.\n\n## Other platforms\n\n- [Chainbase](https://docs.chainbase.com/catalog/Ton/Overview) offers a set of raw and decoded tables with TON data. It allows you to run SQL queries and fetch results via API.\n- [TON Console](https://docs.tonconsole.com/tonconsole/analytics) provides analysts with Analytics Service.\n- [TokenTerminal](https://tokenterminal.com/explorer/projects/the-open-network) comes with high-level metrics across TON Ecosystem.\n- [Artemis](https://app.artemisanalytics.com/project/ton?from=projects) contains key metrics for TON and allows you to build customized charts.\n- [Spice harvester](https://github.com/txsociety/spice-harvester) supports high-load transaction monitoring and asset tracking on TON through a self-hosted API with access to invoice states and metadata.\n"
  },
  {
    "path": "ecosystem/api/overview.mdx",
    "content": "---\ntitle: \"Overview\"\nmode: \"wide\"\n---\n\nAccess TON data via public liteservers, hosted APIs (TON Center v2/v3, TonAPI, dTON), or self-hosted options.\n\n## Comparison table\n\n| Feature                   | Public liteservers                                                                  | TON Center v2                                       | TON Center v3                                      | TonAPI                                                                                   | dTON                                       |\n| ------------------------- | ----------------------------------------------------------------------------------- | --------------------------------------------------- | -------------------------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------ |\n| **Can be self-hosted?**   | ✅                                                                                  | ✅                                                  | ✅                                                 | ❌                                                                                       | ❌                                         |\n| **Open-source**           | ✅                                                                                  | ✅                                                  | ✅                                                 | 🟡 Limited<sup>1</sup>                                                                   | ❌                                         |\n| **Indexer**<sup>2</sup>   | ❌                                                                                  | ❌                                                  | ✅                                                 | ✅                                                                                       | ✅                                         |\n| **Archival**<sup>3</sup>  | 🟡 Varies                                                                           | 🟡 Depends on liteserver                            | ✅                                                 | ✅                                                                                       | ✅                                         |\n| **Proofs**<sup>4</sup>    | ✅                                                                                  | ❌                                                  | ❌                                                 | ❌                                                                                       | ❌                                         |\n| **Mainnet endpoint**      | [Config](https://ton-blockchain.github.io/global.config.json)                       | [Endpoint](https://toncenter.com/api/v2)            | [Endpoint](https://toncenter.com/api/v3)           | [Endpoint](https://tonapi.io/v2)                                                         | [GraphQL](https://dton.io/graphql)         |\n| **Testnet endpoint**      | [Config](https://ton-blockchain.github.io/testnet-global.config.json)               | [Endpoint](https://testnet.toncenter.com/api/v2)    | [Endpoint](https://testnet.toncenter.com/api/v3)   | [Endpoint](https://testnet.tonapi.io/v2)                                                 | [GraphQL](https://testnet.dton.io/graphql) |\n| **Source / Deploy guide** | [Run node / liteserver](/ecosystem/nodes/cpp/setup-mytonctrl#liteserver-quickstart) | [Deploy](https://github.com/toncenter/ton-http-api) | [Source](https://github.com/toncenter/ton-indexer) | [OpenTonAPI](https://github.com/tonkeeper/opentonapi)<sup>1</sup>                        | —                                          |\n| **Documentation**         | [Guide](/ecosystem/nodes/overview#interacting-with-ton-nodes)                       | [Docs](/ecosystem/api/toncenter/v2/overview)        | [Docs](/ecosystem/api/toncenter/v3/overview)       | [REST](https://docs.tonconsole.com/tonapi/rest-api), [Swagger](https://tonapi.io/api-v2) | [Site](https://docs.dton.io/)              |\n\n<sup>1</sup> TonAPI's full indexer is not open-source; [OpenTonAPI](https://github.com/tonkeeper/opentonapi) is a limited open-source version.\n\n<sup>2</sup> **Indexer** means the service maintains its own database derived from blockchain data for richer queries (traces, jettons, NFTs, etc.), beyond raw liteserver RPC.\n\n<sup>3</sup> **Archival** indicates historical data retention. For liteservers, this depends on the node's archival configuration; hosted indexers typically keep full history, but exact retention policies are service-specific.\n\n<sup>4</sup> **Proofs** denote responses that can be verified without trust using cryptographic proofs from the network (liteserver/tonlib-based). HTTP indexers typically do not return proof bundles in their REST/GraphQL responses.\n\n## References\n\n- [TON node and liteserver source](https://github.com/ton-blockchain/ton)\n- [Mainnet liteserver config](https://ton-blockchain.github.io/global.config.json), [testnet config](https://ton-blockchain.github.io/testnet-global.config.json)\n- [TON Center landing page](https://toncenter.com)\n- [TON Center v2 (Python, older) source and deploy instructions](https://github.com/toncenter/ton-http-api)\n- [TON Center v2 (C++, newer) source and deploy instructions](https://github.com/toncenter/ton-http-api-cpp)\n- [TON Center v3 source and deploy instructions](https://github.com/toncenter/ton-indexer)\n- [TonAPI site](https://tonapi.io), [REST docs](https://docs.tonconsole.com/tonapi/rest-api), [Swagger](https://tonapi.io/api-v2)\n- [OpenTonAPI (limited open-source)](https://github.com/tonkeeper/opentonapi)\n- [dTON GraphQL](https://dton.io/graphql)\n"
  },
  {
    "path": "ecosystem/api/price.mdx",
    "content": "---\ntitle: \"Jetton prices API\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nIn this article, we will discuss different ways to retrieve Jetton's historical prices on Decentralized Exchanges, DEXes.\n\nEach swap operation, whether between a native asset (Toncoin) and Jetton or between two distinct Jettons, has its price, a fixed exchange rate of one asset to another. This price is calculated by the internal DEX math algorithm, called [AMM](https://www.coinbase.com/learn/advanced-trading/what-is-an-automated-market-maker-amm). Some services require information about previous swaps on the blockchain to use it in their internal business logic or to simply show statistics to users.\n\n## Off-chain API\n\nThe most common use case for the price API is to fetch Jetton info on the web2 backend and use aggregated data inside the service. There are several historical Jetton price providers in TON:\n\n- [dTON](https://docs.dton.io/about-pnl)\n- [CoinGecko](https://www.coingecko.com/en/api/ton)\n- [Dyor.io](https://dyor.io/tonapi)\n\nYou can find detailed information about API usage and technical details in the provider docs.\n\nThere is no established solution for real-time jetton swap market data; however, one can explore [CoinGecko websocket API](https://docs.coingecko.com/websocket).\n\n## On-chain API\n\nCurrently, it is not possible to retrieve **historical** jetton prices on-chain - since TON contracts [are limited by storage](/from-ethereum#limited-contract-storage), it is quite hard to implement such an API fully on-chain. However, it is possible to retrieve **current** prices via the Request-Response pattern on some DEXes; refer to the specific service documentation to learn more about it.\n\n<Aside>\n  Since the TON [execution model is asynchronous](/from-ethereum#execution-model), the jetton price might change between the moment of the response from the price provider and the moment the contract processes the response. Consider this factor in smart contract logic.\n</Aside>\n\nFor example, on the [DeDust](https://dedust.io) DEX, it is possible to retrieve pool information on-chain using an internal message with the following [TL-B](/languages/tl-b/overview) schema:\n\n```tlb\nprovide_pool_state#6e24728d query_id:uint64 include_assets:Bool = InMsgBody;\n\ntake_pool_state#bddd4954 query_id:uint64 reserve0:Coins reserve1:Coins total_supply:Coins\n                         assets:(Maybe ^[ asset0:Asset asset1:Asset ]) = InMsgBody;\n```\n\nHere is a smart contract snippet in [Tolk](/languages/tolk) illustrating how you can send the 'provide' message:\n\n```tolk title=\"Tolk\"\nstruct (0x6e24728d) ProvideDeDustPool {\n    queryId: uint64\n    doIncludeAssets: bool\n}\n\nfun main() {\n    val requestDeDustPoolInfoMsg = createMessage({\n        body: ProvideDeDustPool { queryId: 1, doIncludeAssets: true },\n        bounce: true,\n        dest: dedustPoolAddress,\n        value: 0,\n    });\n\n    requestDeDustPoolInfoMsg.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE);\n}\n```\n"
  },
  {
    "path": "ecosystem/api/toncenter/get-api-key.mdx",
    "content": "---\ntitle: \"Get your TON Center API key\"\nsidebarTitle: \"Get API key\"\n---\n\nimport { Image } from '/snippets/image.jsx';\n\nTo interact with TON Center's API at higher rate limits, you'll need to generate an API key via the official [Telegram bot](https://t.me/toncenter).\n\n## Open the TON Center bot\n\nOpen the [`@toncenter`](https://t.me/toncenter) bot in Telegram. Click **Start** to begin the setup.\n\n<Image\n  src=\"/resources/images/ton-center/api-key/start-bot.png\"\n  darkSrc=\"/resources/images/ton-center/api-key/start-bot.png\"\n  alt=\"Start Bot\"\n/>\n\n## Open the API keys manager\n\nOnce the bot greets you, press **Manage API Keys**.\n\n<Image\n  src=\"/resources/images/ton-center/api-key/manage-api-keys.png\"\n  darkSrc=\"/resources/images/ton-center/api-key/manage-api-keys.png\"\n  alt=\"Manage API Keys\"\n/>\n\n## Choose a subscription plan\n\nClick **Manage** to open your current subscription details. The default API subscription is the free one.\n\n<Image\n  src=\"/resources/images/ton-center/api-key/subscriptions.png\"\n  darkSrc=\"/resources/images/ton-center/api-key/subscriptions.png\"\n  alt=\"Subscriptions\"\n/>\n\n<Image\n  src=\"/resources/images/ton-center/api-key/subscriptions2.png\"\n  darkSrc=\"/resources/images/ton-center/api-key/subscriptions2.png\"\n  alt=\"Subscriptions\"\n/>\n\nYou'll see different tiers available:\n\n- **Free** – 10 requests/sec, 1 token per network\n- **Plus** – 25 requests/sec, 3 tokens per network (2.5 TON/month)\n- **Advanced** – 100 requests/sec, 10 tokens per network (25 TON/month)\n- **Enterprise** – Tailored rate limits, priority support\n\n<Tabs>\n  <Tab\n    title=\"Free\"\n  >\n    <Image\n      src=\"/resources/images/ton-center/api-key/plan-free.png\"\n      darkSrc=\"/resources/images/ton-center/api-key/plan-free.png\"\n      alt=\"Free Plan\"\n    />\n  </Tab>\n\n  <Tab\n    title=\"Plus\"\n  >\n    <Image\n      src=\"/resources/images/ton-center/api-key/plan-plus.png\"\n      darkSrc=\"/resources/images/ton-center/api-key/plan-plus.png\"\n      alt=\"Plus Plan\"\n    />\n  </Tab>\n\n  <Tab\n    title=\"Advanced\"\n  >\n    <Image\n      src=\"/resources/images/ton-center/api-key/plan-advanced.png\"\n      darkSrc=\"/resources/images/ton-center/api-key/plan-advanced.png\"\n      alt=\"Advanced Plan\"\n    />\n  </Tab>\n\n  <Tab\n    title=\"Enterprise\"\n  >\n    <Image\n      src=\"/resources/images/ton-center/api-key/plan-enterprise.png\"\n      darkSrc=\"/resources/images/ton-center/api-key/plan-enterprise.png\"\n      alt=\"Enterprise Plan\"\n    />\n  </Tab>\n</Tabs>\n\n## (optional) Upgrade your plan\n\nTo upgrade:\n\n- Select your desired plan in the bot interface and click **Purchase Subscription**.\n\n- You'll be shown payment instructions like the following:\n\n  <Image\n    src=\"/resources/images/ton-center/api-key/payment.png\"\n    darkSrc=\"/resources/images/ton-center/api-key/payment.png\"\n    alt=\"Payment\"\n  />\n\n- Send the **exact amount** of TON to the address provided.\n\n- Your subscription will upgrade automatically once the transaction is confirmed.\n\n## Create your API key\n\nAfter subscribing (or staying on Free), click **Create API Key** to generate your key.\n\nOnce created, your token will appear in the list and can be used in all authenticated requests.\n\n<Image\n  src=\"/resources/images/ton-center/api-key/create-key.png\"\n  darkSrc=\"/resources/images/ton-center/api-key/create-key.png\"\n  alt=\"Create API Key\"\n/>\n\n<Image\n  src=\"/resources/images/ton-center/api-key/create-key2.png\"\n  darkSrc=\"/resources/images/ton-center/api-key/create-key2.png\"\n  alt=\"Create API Key\"\n/>\n\n<Image\n  src=\"/resources/images/ton-center/api-key/create-key3.png\"\n  darkSrc=\"/resources/images/ton-center/api-key/create-key3.png\"\n  alt=\"Create API Key\"\n/>\n\n<Image\n  src=\"/resources/images/ton-center/api-key/create-key4.png\"\n  darkSrc=\"/resources/images/ton-center/api-key/create-key4.png\"\n  alt=\"Create API Key\"\n/>\n\n## Get help\n\n- General help: [`@toncenter_help_bot`](https://t.me/toncenter_help_bot)\n- Support for enterprise and custom plans: [`@toncenter_support`](https://t.me/toncenter_support)\n"
  },
  {
    "path": "ecosystem/api/toncenter/introduction.mdx",
    "content": "---\ntitle: Introduction\n---\n\nTON Center HTTP APIs: read blockchain data, query smart contracts, send transactions.\n\n<Columns cols={2}>\n  <Card\n    title=\"API v2\"\n    icon=\"bolt\"\n    href=\"/ecosystem/api/toncenter/v2/overview\"\n  >\n    Direct liteserver for balances, sending transactions, contract queries.\n  </Card>\n\n  <Card\n    title=\"API v3\"\n    icon=\"database\"\n    href=\"/ecosystem/api/toncenter/v3/overview\"\n  >\n    Indexed database for traces, Jettons, NFTs, and historical queries.\n  </Card>\n</Columns>\n"
  },
  {
    "path": "ecosystem/api/toncenter/rate-limit.mdx",
    "content": "---\ntitle: \"Rate limits\"\n---\n\nimport {Aside} from \"/snippets/aside.jsx\";\n\nTo ensure stability and fair access, TON Center applies rate limits to all API requests.\\\nIf an application exceeds these limits, the API returns a `429` response.\n\nIncrease limits by [requesting an API key](/ecosystem/api/toncenter/get-api-key) and selecting a higher subscription plan. Without any API key, the default rate limit is 1 request per second.\n\n## Default limits\n\n| Plan       | Tokens per network | Requests per second | Notes                                                                                                      |\n| ---------- | ------------------ | ------------------- | ---------------------------------------------------------------------------------------------------------- |\n| Free       | 1                  | 10                  | Shared liteservers suitable for low-volume testing and small projects.                                     |\n| Plus       | 3                  | 25                  | Private liteservers that reduce contention compared to shared access.                                      |\n| Advanced   | 10                 | 100                 | Private infrastructure with capacity for higher request rates.                                             |\n| Enterprise | Custom             | Custom              | Custom throughput and support. Contact [`@toncenter_support`](https://t.me/toncenter_support) for details. |\n\nRate limits apply to all API keys in total separately for every TON network, including mainnet and testnet. For example, the Plus plan users can create three API keys for the mainnet. The total limit for these three keys will be 25 requests per second.\n\n<Aside>\n  Each token represents an individual API key used to authenticate requests. Plans differ by how many tokens can be generated per network (mainnet and testnet). For example, the Free plan allows 1 key per network, while higher plans provide multiple keys for separate apps or environments.\n</Aside>\n\n## Rate limit exceeded\n\nWhen requests are sent faster than the allowed rate limit, the TON Center API temporarily blocks new ones. A JSON response indicates the rate limit is exceeded:\n\n```json\n{\n  \"ok\": false,\n  \"result\": \"Ratelimit exceed\",\n  \"code\": 429\n}\n```\n\nWhen this occurs:\n\n- Stop sending new requests and wait a few seconds before retrying.\n- Implement exponential backoff to avoid repeated rate-limit violations.\n\n## Troubleshooting\n\nIf a paid plan is active but the rate remains 1 RPS:\n\n- Check that the API key is included correctly in the requests. Requests without a valid API key are limited to 1 RPS, even if a subscription is active.\n\n- Verify the correct key is used for the intended environment (mainnet or testnet). Each network requires its own key.\n\nWait up to 10 minutes after upgrading the plan or changing the API key.\nSubscription and key updates can take several minutes to propagate across TON Center’s rate-limiting system.\n"
  },
  {
    "path": "ecosystem/api/toncenter/smc-index/get-nominator-bookings-method.mdx",
    "content": "---\nopenapi: get /getNominatorBookings\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/smc-index/get-nominator-earnings-method.mdx",
    "content": "---\nopenapi: get /getNominatorEarnings\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/smc-index/get-nominator-method.mdx",
    "content": "---\nopenapi: get /getNominator\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/smc-index/get-pool-bookings-method.mdx",
    "content": "---\nopenapi: get /getPoolBookings\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/smc-index/get-pool-method.mdx",
    "content": "---\nopenapi: get /getPool\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/smc-index/lifecheck-method.mdx",
    "content": "---\nopenapi: get /lifecheck\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/smc-index.json",
    "content": "{\n    \"openapi\": \"3.1.0\",\n    \"info\": {\n        \"title\": \"TON SC Indexer V2\",\n        \"description\": \"TON Smart Contracts Indexer. Nominator pools, V2.\",\n        \"version\": \"0.0.2\"\n    },\n    \"servers\": [\n        {\n            \"url\": \"https://toncenter.com/api/smc-index\"\n        },\n        {\n            \"url\": \"https://testnet.toncenter.com/api/smc-index\"\n        }\n    ],\n    \"paths\": {\n        \"/lifecheck\": {\n            \"get\": {\n                \"summary\": \"Lifecheck Method\",\n                \"description\": \"Check if there are any bookings in the last 19 hours.\\nReturns status \\\"ok\\\" if bookings exist, \\\"dead\\\" otherwise.\",\n                \"operationId\": \"lifecheck_method_api_smc_index_lifecheck_get\",\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Successful Response\",\n                        \"content\": {\n                            \"application/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#/components/schemas/LifecheckModel\"\n                                }\n                            }\n                        }\n                    }\n                },\n                \"security\": [\n                    {\n                        \"APIKeyHeader\": []\n                    },\n                    {\n                        \"APIKeyQuery\": []\n                    }\n                ]\n            }\n        },\n        \"/getNominator\": {\n            \"get\": {\n                \"summary\": \"Get Nominator Method\",\n                \"description\": \"Get nominator data in given pool (the only in list) or, if pool is not specified, in all pools where nominator stakes.\",\n                \"operationId\": \"get_nominator_method_api_smc_index_getNominator_get\",\n                \"security\": [\n                    {\n                        \"APIKeyHeader\": []\n                    },\n                    {\n                        \"APIKeyQuery\": []\n                    }\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"nominator\",\n                        \"in\": \"query\",\n                        \"required\": true,\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"description\": \"The nominator address.\",\n                            \"title\": \"Nominator\"\n                        },\n                        \"description\": \"The nominator address.\"\n                    },\n                    {\n                        \"name\": \"pool\",\n                        \"in\": \"query\",\n                        \"required\": false,\n                        \"schema\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"The pool address in which nominator stakes coins. If not specified, returns nominator from all his pools.\",\n                            \"title\": \"Pool\"\n                        },\n                        \"description\": \"The pool address in which nominator stakes coins. If not specified, returns nominator from all his pools.\"\n                    }\n                ],\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Successful Response\",\n                        \"content\": {\n                            \"application/json\": {\n                                \"schema\": {\n                                    \"type\": \"array\",\n                                    \"items\": {\n                                        \"$ref\": \"#/components/schemas/NominatorModel\"\n                                    },\n                                    \"title\": \"Response Get Nominator Method Api Smc Index Getnominator Get\"\n                                }\n                            }\n                        }\n                    },\n                    \"422\": {\n                        \"description\": \"Validation Error\",\n                        \"content\": {\n                            \"application/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#/components/schemas/HTTPValidationError\"\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        },\n        \"/getPool\": {\n            \"get\": {\n                \"summary\": \"Get Pool Method\",\n                \"description\": \"Get pool data with all its nominators.\",\n                \"operationId\": \"get_pool_method_api_smc_index_getPool_get\",\n                \"security\": [\n                    {\n                        \"APIKeyHeader\": []\n                    },\n                    {\n                        \"APIKeyQuery\": []\n                    }\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"pool\",\n                        \"in\": \"query\",\n                        \"required\": true,\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"description\": \"The pool address. Can be sent in hex, base64 or base64url form.\",\n                            \"title\": \"Pool\"\n                        },\n                        \"description\": \"The pool address. Can be sent in hex, base64 or base64url form.\"\n                    }\n                ],\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Successful Response\",\n                        \"content\": {\n                            \"application/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#/components/schemas/NominatorPoolModel\"\n                                }\n                            }\n                        }\n                    },\n                    \"422\": {\n                        \"description\": \"Validation Error\",\n                        \"content\": {\n                            \"application/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#/components/schemas/HTTPValidationError\"\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        },\n        \"/getNominatorBookings\": {\n            \"get\": {\n                \"summary\": \"Get Nominator Bookings Method\",\n                \"description\": \"Get nominator bookings (debits and credits) in specified pool.\",\n                \"operationId\": \"get_nominator_bookings_method_api_smc_index_getNominatorBookings_get\",\n                \"security\": [\n                    {\n                        \"APIKeyHeader\": []\n                    },\n                    {\n                        \"APIKeyQuery\": []\n                    }\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"nominator\",\n                        \"in\": \"query\",\n                        \"required\": true,\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"description\": \"The nominator address.\",\n                            \"title\": \"Nominator\"\n                        },\n                        \"description\": \"The nominator address.\"\n                    },\n                    {\n                        \"name\": \"pool\",\n                        \"in\": \"query\",\n                        \"required\": true,\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"description\": \"Pool address to get bookings in.\",\n                            \"title\": \"Pool\"\n                        },\n                        \"description\": \"Pool address to get bookings in.\"\n                    },\n                    {\n                        \"name\": \"limit\",\n                        \"in\": \"query\",\n                        \"required\": false,\n                        \"schema\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"integer\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"Limit from bottom.\",\n                            \"default\": 100,\n                            \"title\": \"Limit\"\n                        },\n                        \"description\": \"Limit from bottom.\"\n                    },\n                    {\n                        \"name\": \"from_time\",\n                        \"in\": \"query\",\n                        \"required\": false,\n                        \"schema\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"integer\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"Unixtime of the first booking.\",\n                            \"title\": \"From Time\"\n                        },\n                        \"description\": \"Unixtime of the first booking.\"\n                    },\n                    {\n                        \"name\": \"to_time\",\n                        \"in\": \"query\",\n                        \"required\": false,\n                        \"schema\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"integer\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"Unixtime of the last booking.\",\n                            \"title\": \"To Time\"\n                        },\n                        \"description\": \"Unixtime of the last booking.\"\n                    }\n                ],\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Successful Response\",\n                        \"content\": {\n                            \"application/json\": {\n                                \"schema\": {\n                                    \"type\": \"array\",\n                                    \"items\": {\n                                        \"$ref\": \"#/components/schemas/BookingMinimalModel\"\n                                    },\n                                    \"title\": \"Response Get Nominator Bookings Method Api Smc Index Getnominatorbookings Get\"\n                                }\n                            }\n                        }\n                    },\n                    \"422\": {\n                        \"description\": \"Validation Error\",\n                        \"content\": {\n                            \"application/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#/components/schemas/HTTPValidationError\"\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        },\n        \"/getNominatorEarnings\": {\n            \"get\": {\n                \"summary\": \"Get Nominator Earnings Method\",\n                \"description\": \"Get nominator income in specified pool with his stake on each timepoint.\",\n                \"operationId\": \"get_nominator_earnings_method_api_smc_index_getNominatorEarnings_get\",\n                \"security\": [\n                    {\n                        \"APIKeyHeader\": []\n                    },\n                    {\n                        \"APIKeyQuery\": []\n                    }\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"nominator\",\n                        \"in\": \"query\",\n                        \"required\": true,\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"description\": \"The nominator address.\",\n                            \"title\": \"Nominator\"\n                        },\n                        \"description\": \"The nominator address.\"\n                    },\n                    {\n                        \"name\": \"pool\",\n                        \"in\": \"query\",\n                        \"required\": true,\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"description\": \"Pool address to get earnings in.\",\n                            \"title\": \"Pool\"\n                        },\n                        \"description\": \"Pool address to get earnings in.\"\n                    },\n                    {\n                        \"name\": \"limit\",\n                        \"in\": \"query\",\n                        \"required\": false,\n                        \"schema\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"integer\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"Limit from bottom.\",\n                            \"default\": 100,\n                            \"title\": \"Limit\"\n                        },\n                        \"description\": \"Limit from bottom.\"\n                    },\n                    {\n                        \"name\": \"from_time\",\n                        \"in\": \"query\",\n                        \"required\": false,\n                        \"schema\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"integer\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"Unixtime of the first booking.\",\n                            \"title\": \"From Time\"\n                        },\n                        \"description\": \"Unixtime of the first booking.\"\n                    },\n                    {\n                        \"name\": \"to_time\",\n                        \"in\": \"query\",\n                        \"required\": false,\n                        \"schema\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"integer\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"Unixtime of the last booking.\",\n                            \"title\": \"To Time\"\n                        },\n                        \"description\": \"Unixtime of the last booking.\"\n                    }\n                ],\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Successful Response\",\n                        \"content\": {\n                            \"application/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#/components/schemas/EarningsModel\"\n                                }\n                            }\n                        }\n                    },\n                    \"422\": {\n                        \"description\": \"Validation Error\",\n                        \"content\": {\n                            \"application/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#/components/schemas/HTTPValidationError\"\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        },\n        \"/getPoolBookings\": {\n            \"get\": {\n                \"summary\": \"Get Pool Bookings Method\",\n                \"description\": \"Get all the bookings (debits and credits) in specified pool.\",\n                \"operationId\": \"get_pool_bookings_method_api_smc_index_getPoolBookings_get\",\n                \"security\": [\n                    {\n                        \"APIKeyHeader\": []\n                    },\n                    {\n                        \"APIKeyQuery\": []\n                    }\n                ],\n                \"parameters\": [\n                    {\n                        \"name\": \"pool\",\n                        \"in\": \"query\",\n                        \"required\": true,\n                        \"schema\": {\n                            \"type\": \"string\",\n                            \"description\": \"Pool address to get bookings in.\",\n                            \"title\": \"Pool\"\n                        },\n                        \"description\": \"Pool address to get bookings in.\"\n                    },\n                    {\n                        \"name\": \"limit\",\n                        \"in\": \"query\",\n                        \"required\": false,\n                        \"schema\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"integer\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"Limit from bottom.\",\n                            \"default\": 100,\n                            \"title\": \"Limit\"\n                        },\n                        \"description\": \"Limit from bottom.\"\n                    },\n                    {\n                        \"name\": \"from_time\",\n                        \"in\": \"query\",\n                        \"required\": false,\n                        \"schema\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"integer\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"Unixtime of the first booking.\",\n                            \"title\": \"From Time\"\n                        },\n                        \"description\": \"Unixtime of the first booking.\"\n                    },\n                    {\n                        \"name\": \"to_time\",\n                        \"in\": \"query\",\n                        \"required\": false,\n                        \"schema\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"integer\"\n                                },\n                                {\n                                    \"type\": \"null\"\n                                }\n                            ],\n                            \"description\": \"Unixtime of the last booking.\",\n                            \"title\": \"To Time\"\n                        },\n                        \"description\": \"Unixtime of the last booking.\"\n                    }\n                ],\n                \"responses\": {\n                    \"200\": {\n                        \"description\": \"Successful Response\",\n                        \"content\": {\n                            \"application/json\": {\n                                \"schema\": {\n                                    \"type\": \"array\",\n                                    \"items\": {\n                                        \"$ref\": \"#/components/schemas/BookingModel\"\n                                    },\n                                    \"title\": \"Response Get Pool Bookings Method Api Smc Index Getpoolbookings Get\"\n                                }\n                            }\n                        }\n                    },\n                    \"422\": {\n                        \"description\": \"Validation Error\",\n                        \"content\": {\n                            \"application/json\": {\n                                \"schema\": {\n                                    \"$ref\": \"#/components/schemas/HTTPValidationError\"\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    },\n    \"components\": {\n        \"schemas\": {\n            \"ActiveNominatorModel\": {\n                \"properties\": {\n                    \"address\": {\n                        \"type\": \"string\",\n                        \"title\": \"Address\"\n                    },\n                    \"balance\": {\n                        \"type\": \"integer\",\n                        \"title\": \"Balance\"\n                    },\n                    \"pending_balance\": {\n                        \"type\": \"integer\",\n                        \"title\": \"Pending Balance\"\n                    }\n                },\n                \"type\": \"object\",\n                \"required\": [\n                    \"address\",\n                    \"balance\",\n                    \"pending_balance\"\n                ],\n                \"title\": \"ActiveNominatorModel\"\n            },\n            \"BookingMinimalModel\": {\n                \"properties\": {\n                    \"utime\": {\n                        \"type\": \"integer\",\n                        \"title\": \"Utime\"\n                    },\n                    \"booking_type\": {\n                        \"type\": \"string\",\n                        \"title\": \"Booking Type\"\n                    },\n                    \"debit\": {\n                        \"type\": \"integer\",\n                        \"title\": \"Debit\"\n                    },\n                    \"credit\": {\n                        \"type\": \"integer\",\n                        \"title\": \"Credit\"\n                    }\n                },\n                \"type\": \"object\",\n                \"required\": [\n                    \"utime\",\n                    \"booking_type\",\n                    \"debit\",\n                    \"credit\"\n                ],\n                \"title\": \"BookingMinimalModel\"\n            },\n            \"BookingModel\": {\n                \"properties\": {\n                    \"nominator_address\": {\n                        \"type\": \"string\",\n                        \"title\": \"Nominator Address\"\n                    },\n                    \"utime\": {\n                        \"type\": \"integer\",\n                        \"title\": \"Utime\"\n                    },\n                    \"booking_type\": {\n                        \"type\": \"string\",\n                        \"title\": \"Booking Type\"\n                    },\n                    \"debit\": {\n                        \"type\": \"integer\",\n                        \"title\": \"Debit\"\n                    },\n                    \"credit\": {\n                        \"type\": \"integer\",\n                        \"title\": \"Credit\"\n                    }\n                },\n                \"type\": \"object\",\n                \"required\": [\n                    \"nominator_address\",\n                    \"utime\",\n                    \"booking_type\",\n                    \"debit\",\n                    \"credit\"\n                ],\n                \"title\": \"BookingModel\"\n            },\n            \"EarningModel\": {\n                \"properties\": {\n                    \"utime\": {\n                        \"type\": \"integer\",\n                        \"title\": \"Utime\"\n                    },\n                    \"income\": {\n                        \"type\": \"integer\",\n                        \"title\": \"Income\"\n                    },\n                    \"stake_before\": {\n                        \"type\": \"integer\",\n                        \"title\": \"Stake Before\"\n                    }\n                },\n                \"type\": \"object\",\n                \"required\": [\n                    \"utime\",\n                    \"income\",\n                    \"stake_before\"\n                ],\n                \"title\": \"EarningModel\"\n            },\n            \"EarningsModel\": {\n                \"properties\": {\n                    \"total_on_period\": {\n                        \"type\": \"integer\",\n                        \"title\": \"Total On Period\"\n                    },\n                    \"earnings\": {\n                        \"items\": {\n                            \"$ref\": \"#/components/schemas/EarningModel\"\n                        },\n                        \"type\": \"array\",\n                        \"title\": \"Earnings\"\n                    }\n                },\n                \"type\": \"object\",\n                \"required\": [\n                    \"total_on_period\",\n                    \"earnings\"\n                ],\n                \"title\": \"EarningsModel\"\n            },\n            \"HTTPValidationError\": {\n                \"properties\": {\n                    \"detail\": {\n                        \"items\": {\n                            \"$ref\": \"#/components/schemas/ValidationError\"\n                        },\n                        \"type\": \"array\",\n                        \"title\": \"Detail\"\n                    }\n                },\n                \"type\": \"object\",\n                \"title\": \"HTTPValidationError\"\n            },\n            \"LifecheckModel\": {\n                \"properties\": {\n                    \"status\": {\n                        \"type\": \"string\",\n                        \"title\": \"Status\"\n                    },\n                    \"last_booking_time\": {\n                        \"type\": \"integer\",\n                        \"title\": \"Last Booking Time\"\n                    }\n                },\n                \"type\": \"object\",\n                \"required\": [\n                    \"status\",\n                    \"last_booking_time\"\n                ],\n                \"title\": \"LifecheckModel\"\n            },\n            \"NominatorModel\": {\n                \"properties\": {\n                    \"pool_address\": {\n                        \"type\": \"string\",\n                        \"title\": \"Pool Address\"\n                    },\n                    \"balance\": {\n                        \"type\": \"integer\",\n                        \"title\": \"Balance\"\n                    },\n                    \"pending_balance\": {\n                        \"type\": \"integer\",\n                        \"title\": \"Pending Balance\"\n                    }\n                },\n                \"type\": \"object\",\n                \"required\": [\n                    \"pool_address\",\n                    \"balance\",\n                    \"pending_balance\"\n                ],\n                \"title\": \"NominatorModel\"\n            },\n            \"NominatorPoolModel\": {\n                \"properties\": {\n                    \"stake_amount_sent\": {\n                        \"type\": \"integer\",\n                        \"title\": \"Stake Amount Sent\"\n                    },\n                    \"validator_amount\": {\n                        \"type\": \"integer\",\n                        \"title\": \"Validator Amount\"\n                    },\n                    \"nominators_count\": {\n                        \"type\": \"integer\",\n                        \"title\": \"Nominators Count\"\n                    },\n                    \"active_nominators\": {\n                        \"items\": {\n                            \"$ref\": \"#/components/schemas/ActiveNominatorModel\"\n                        },\n                        \"type\": \"array\",\n                        \"title\": \"Active Nominators\"\n                    },\n                    \"inactive_nominators\": {\n                        \"items\": {\n                            \"type\": \"string\"\n                        },\n                        \"type\": \"array\",\n                        \"title\": \"Inactive Nominators\"\n                    }\n                },\n                \"type\": \"object\",\n                \"required\": [\n                    \"stake_amount_sent\",\n                    \"validator_amount\",\n                    \"nominators_count\",\n                    \"active_nominators\",\n                    \"inactive_nominators\"\n                ],\n                \"title\": \"NominatorPoolModel\"\n            },\n            \"ValidationError\": {\n                \"properties\": {\n                    \"loc\": {\n                        \"items\": {\n                            \"anyOf\": [\n                                {\n                                    \"type\": \"string\"\n                                },\n                                {\n                                    \"type\": \"integer\"\n                                }\n                            ]\n                        },\n                        \"type\": \"array\",\n                        \"title\": \"Location\"\n                    },\n                    \"msg\": {\n                        \"type\": \"string\",\n                        \"title\": \"Message\"\n                    },\n                    \"type\": {\n                        \"type\": \"string\",\n                        \"title\": \"Error Type\"\n                    }\n                },\n                \"type\": \"object\",\n                \"required\": [\n                    \"loc\",\n                    \"msg\",\n                    \"type\"\n                ],\n                \"title\": \"ValidationError\"\n            }\n        },\n        \"securitySchemes\": {\n            \"APIKeyHeader\": {\n                \"type\": \"apiKey\",\n                \"in\": \"header\",\n                \"name\": \"X-API-Key\"\n            },\n            \"APIKeyQuery\": {\n                \"type\": \"apiKey\",\n                \"in\": \"query\",\n                \"name\": \"api_key\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "ecosystem/api/toncenter/v2/accounts/convert-raw-address-to-user-friendly-format.mdx",
    "content": "---\nopenapi: get /packAddress\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/accounts/convert-user-friendly-address-to-raw-format.mdx",
    "content": "---\nopenapi: get /unpackAddress\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/accounts/detect-all-address-formats.mdx",
    "content": "---\nopenapi: get /detectAddress\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/accounts/get-account-balance-only.mdx",
    "content": "---\nopenapi: get /getAddressBalance\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/accounts/get-account-lifecycle-state.mdx",
    "content": "---\nopenapi: get /getAddressState\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/accounts/get-account-state-and-balance.mdx",
    "content": "---\nopenapi: get /getAddressInformation\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/accounts/get-detailed-account-state-extended.mdx",
    "content": "---\nopenapi: get /getExtendedAddressInformation\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/accounts/get-nft-or-jetton-metadata.mdx",
    "content": "---\nopenapi: get /getTokenData\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/accounts/get-wallet-information.mdx",
    "content": "---\nopenapi: get /getWalletInformation\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/accounts/list-account-transactions.mdx",
    "content": "---\nopenapi: get /getTransactions\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/blocks/get-block-header-metadata.mdx",
    "content": "---\nopenapi: get /getBlockHeader\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/blocks/get-latest-consensus-block.mdx",
    "content": "---\nopenapi: get /getConsensusBlock\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/blocks/get-latest-masterchain-info.mdx",
    "content": "---\nopenapi: get /getMasterchainInfo\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/blocks/get-masterchain-block-signatures.mdx",
    "content": "---\nopenapi: get /getMasterchainBlockSignatures\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/blocks/get-outgoing-message-queue-sizes.mdx",
    "content": "---\nopenapi: get /getOutMsgQueueSizes\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/blocks/get-shard-block-proof.mdx",
    "content": "---\nopenapi: get /getShardBlockProof\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/blocks/get-shards-at-masterchain-seqno.mdx",
    "content": "---\nopenapi: get /shards\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/blocks/get-smart-contract-libraries.mdx",
    "content": "---\nopenapi: get /getLibraries\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v2/blocks/list-block-transactions-extended-details.mdx",
    "content": "---\nopenapi: get /getBlockTransactionsExt\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/blocks/list-block-transactions.mdx",
    "content": "---\nopenapi: get /getBlockTransactions\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/blocks/look-up-block-by-height-lt-or-timestamp.mdx",
    "content": "---\nopenapi: get /lookupBlock\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/config/get-all-config-parameters.mdx",
    "content": "---\nopenapi: get /getConfigAll\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/config/get-single-config-parameter.mdx",
    "content": "---\nopenapi: get /getConfigParam\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/json-rpc/json-rpc-handler.mdx",
    "content": "---\nopenapi: post /jsonRPC\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/messages-and-transactions/estimate-transaction-fees.mdx",
    "content": "---\nopenapi: post /estimateFee\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/messages-and-transactions/send-external-message-and-return-hash.mdx",
    "content": "---\nopenapi: post /sendBocReturnHash\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/messages-and-transactions/send-external-message-boc.mdx",
    "content": "---\nopenapi: post /sendBoc\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/messages-and-transactions/send-unpacked-external-query.mdx",
    "content": "---\nopenapi: post /sendQuery\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/overview.mdx",
    "content": "---\ntitle: Overview\n---\n\nThe TON Center API v2 provides developer access to the TON blockchain through \n[REST](https://en.wikipedia.org/wiki/REST) and [JSON-RPC](https://en.wikipedia.org/wiki/JSON-RPC) endpoints.\nIt allows applications to read blockchain data, run smart contract methods, and send transactions.\n\nAPI v2 serves as a non-indexed access layer.  \n\nApplications interact with the TON blockchain by connecting to a TON node.  \nSince nodes communicate through the binary ADNL protocol, an intermediate layer\nis needed for web-based access. API v2 provides this bridge by using [`tonlib`](https://github.com/ton-blockchain/ton/tree/master/tonlib/tonlib)\nto query data from liteservers and exposes it through a standard REST interface.\n\n## Base URLs\n\n| API        | Mainnet                        | Testnet                                |\n| ---------- | ------------------------------ | -------------------------------------- |\n| **API v2** | `https://toncenter.com/api/v2` | `https://testnet.toncenter.com/api/v2` |\n\n## Versioning\n\nAPI v2 uses semantic versioning in the format `a.b.c` (for example, `2.1.1`):\n\n| Segment | Example | Meaning |\n| ------- | ------- | ------- |\n| **Major** | `2.x.x` | Fixed at `2` to avoid confusion (\"API v2 v3.x.x\"). Will not change. |\n| **Minor** | `2.1.x` | Implementation variant: `0` = Python version, `1` = C++ version. |\n| **Patch** | `2.1.1` | Bumped with every release on GitHub. |\n\n## Typical use cases\n\n- Query account balances and state  \n- Run get-methods on smart contracts  \n- Send or broadcast messages  \n- Retrieve latest transactions and block information  \n\n## Endpoints\n\n{/* BEGIN_AUTO_GENERATED: API_V2_ENDPOINTS */}\n| Category | Method | Description |\n| -------- | ------ | ----------- |\n| **Accounts** | [`GET /getAddressInformation`](/ecosystem/api/toncenter/v2/accounts/get-account-state-and-balance) | Get account state and balance |\n| **Accounts** | [`GET /getExtendedAddressInformation`](/ecosystem/api/toncenter/v2/accounts/get-detailed-account-state-extended) | Get detailed account state (extended) |\n| **Accounts** | [`GET /getWalletInformation`](/ecosystem/api/toncenter/v2/accounts/get-wallet-information) | Get wallet information |\n| **Accounts** | [`GET /getTransactions`](/ecosystem/api/toncenter/v2/accounts/list-account-transactions) | List account transactions |\n| **Accounts** | [`GET /getAddressBalance`](/ecosystem/api/toncenter/v2/accounts/get-account-balance-only) | Get account balance only |\n| **Accounts** | [`GET /getAddressState`](/ecosystem/api/toncenter/v2/accounts/get-account-lifecycle-state) | Get account lifecycle state |\n| **Accounts** | [`GET /packAddress`](/ecosystem/api/toncenter/v2/accounts/convert-raw-address-to-user-friendly-format) | Convert raw address to user-friendly format |\n| **Accounts** | [`GET /unpackAddress`](/ecosystem/api/toncenter/v2/accounts/convert-user-friendly-address-to-raw-format) | Convert user-friendly address to raw format |\n| **Accounts** | [`GET /getTokenData`](/ecosystem/api/toncenter/v2/accounts/get-nft-or-jetton-metadata) | Get NFT or Jetton metadata |\n| **Accounts** | [`GET /detectAddress`](/ecosystem/api/toncenter/v2/accounts/detect-all-address-formats) | Detect all address formats |\n| **Blocks** | [`GET /getMasterchainInfo`](/ecosystem/api/toncenter/v2/blocks/get-latest-masterchain-info) | Get latest masterchain info |\n| **Blocks** | [`GET /getMasterchainBlockSignatures`](/ecosystem/api/toncenter/v2/blocks/get-masterchain-block-signatures) | Get masterchain block signatures |\n| **Blocks** | [`GET /getShardBlockProof`](/ecosystem/api/toncenter/v2/blocks/get-shard-block-proof) | Get shard block proof |\n| **Blocks** | [`GET /getConsensusBlock`](/ecosystem/api/toncenter/v2/blocks/get-latest-consensus-block) | Get latest consensus block |\n| **Blocks** | [`GET /lookupBlock`](/ecosystem/api/toncenter/v2/blocks/look-up-block-by-height-lt-or-timestamp) | Look up block by height, LT, or timestamp |\n| **Blocks** | [`GET /shards`](/ecosystem/api/toncenter/v2/blocks/get-shards-at-masterchain-seqno) | Get shards at masterchain seqno |\n| **Blocks** | [`GET /getBlockTransactions`](/ecosystem/api/toncenter/v2/blocks/list-block-transactions) | List block transactions |\n| **Blocks** | [`GET /getBlockTransactionsExt`](/ecosystem/api/toncenter/v2/blocks/list-block-transactions-extended-details) | List block transactions (extended details) |\n| **Blocks** | [`GET /getBlockHeader`](/ecosystem/api/toncenter/v2/blocks/get-block-header-metadata) | Get block header metadata |\n| **Blocks** | [`GET /getLibraries`](/ecosystem/api/toncenter/v2/blocks/get-smart-contract-libraries) | Get smart contract libraries |\n| **Blocks** | [`GET /getOutMsgQueueSizes`](/ecosystem/api/toncenter/v2/blocks/get-outgoing-message-queue-sizes) | Get outgoing message queue sizes |\n| **Transactions** | [`GET /tryLocateTx`](/ecosystem/api/toncenter/v2/transactions/locate-transaction-by-incoming-message) | Locate transaction by incoming message |\n| **Transactions** | [`GET /tryLocateResultTx`](/ecosystem/api/toncenter/v2/transactions/locate-result-transaction-by-incoming-message) | Locate result transaction by incoming message |\n| **Transactions** | [`GET /tryLocateSourceTx`](/ecosystem/api/toncenter/v2/transactions/locate-source-transaction-by-outgoing-message) | Locate source transaction by outgoing message |\n| **JSON-RPC** | [`POST /jsonRPC`](/ecosystem/api/toncenter/v2/json-rpc/json-rpc-handler) | JSON-RPC handler |\n| **Config** | [`GET /getConfigParam`](/ecosystem/api/toncenter/v2/config/get-single-config-parameter) | Get single config parameter |\n| **Config** | [`GET /getConfigAll`](/ecosystem/api/toncenter/v2/config/get-all-config-parameters) | Get all config parameters |\n| **Messages and transactions** | [`POST /sendBoc`](/ecosystem/api/toncenter/v2/messages-and-transactions/send-external-message-boc) | Send external message (BoC) |\n| **Messages and transactions** | [`POST /sendBocReturnHash`](/ecosystem/api/toncenter/v2/messages-and-transactions/send-external-message-and-return-hash) | Send external message and return hash |\n| **Messages and transactions** | [`POST /sendQuery`](/ecosystem/api/toncenter/v2/messages-and-transactions/send-unpacked-external-query) | Send unpacked external query |\n| **Messages and transactions** | [`POST /estimateFee`](/ecosystem/api/toncenter/v2/messages-and-transactions/estimate-transaction-fees) | Estimate transaction fees |\n| **Smart contracts** | [`POST /runGetMethod`](/ecosystem/api/toncenter/v2/smart-contracts/run-get-method-on-contract) | Run get-method on contract |\n{/* END_AUTO_GENERATED: API_V2_ENDPOINTS */}\n\n## How to access the API\n\nDevelopers can access API v2 either through hosted infrastructure managed by TON Center or by running a self-hosted instance.\n\n### Managed service\n\nHosted access uses TON Center’s managed infrastructure instead of running a personal node. This approach enables\nimmediate network access without setup or maintenance.\n\nRequests without an API key are limited to a default rate of 1 request per second.\n\nTo increase this limit or access private liteservers, generate an [API key](/ecosystem/api/toncenter/get-api-key) and [choose a plan](/ecosystem/api/toncenter/rate-limit).\n\n### Self-hosted service\n\nRun a self-hosted TON Center API v2 infrastructure for full control over performance and data retention. \nSee the [API v2](https://github.com/toncenter/ton-http-api) repository for setup instructions.\n"
  },
  {
    "path": "ecosystem/api/toncenter/v2/smart-contracts/run-get-method-on-contract.mdx",
    "content": "---\nopenapi: post /runGetMethod\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/transactions/locate-result-transaction-by-incoming-message.mdx",
    "content": "---\nopenapi: get /tryLocateResultTx\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/transactions/locate-source-transaction-by-outgoing-message.mdx",
    "content": "---\nopenapi: get /tryLocateSourceTx\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2/transactions/locate-transaction-by-incoming-message.mdx",
    "content": "---\nopenapi: get /tryLocateTx\n---"
  },
  {
    "path": "ecosystem/api/toncenter/v2-authentication.mdx",
    "content": "---\ntitle: \"API authentication\"\nsidebarTitle: \"Authentication\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\n\n## Overview\n\nThe API v2 accepts an API key for all methods, including the JSON-RPC endpoint. Requests without an API key are limited to one request per second. To make more than one request per second, please include an API key.\n\nThe key can be sent either in an HTTP header or as a query parameter. Only one of these is needed per request.\n\nTo obtain an API key, see the [TON Center API key guide](/ecosystem/api/toncenter/get-api-key).\n\n| Method  | Location | Name        |\n| ------- | -------- | ----------- |\n| API key | Header   | `X-API-Key` |\n| API key | Query    | `api_key`   |\n\n<Aside\n  type=\"caution\"\n>\n  Never expose the API key in client-side code or public repositories. Store keys in a secrets manager or environment variables, rotate them periodically, and generate a new key immediately if one is compromised.\n</Aside>\n\n## Public hosts\n\n| Network | Host                                   |\n| ------- | -------------------------------------- |\n| Testnet | `https://testnet.toncenter.com/api/v2` |\n| Mainnet | `https://toncenter.com/api/v2`         |\n\n## REST endpoint authentication\n\n### Header authentication\n\nSend the API key in the `X-API-Key` header:\n\n```bash\ncurl \"https://testnet.toncenter.com/api/v2/getMasterchainInfo\" \\\n  -H \"X-API-Key: <API_KEY>\"\n```\n\n### Query parameter authentication\n\nPass the key as a query parameter named `api_key`:\n\n```bash\ncurl \"https://testnet.toncenter.com/api/v2/getMasterchainInfo?api_key=<API_KEY>\"\n```\n\nBoth forms are equivalent.\n\n## JSON-RPC endpoint authentication\n\n**Endpoint:** `POST /api/v2/jsonRPC`\n\nThe same API key rules apply. Example using header authentication:\n\n```bash\ncurl \"https://testnet.toncenter.com/api/v2/jsonRPC\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"X-API-Key: <API_KEY>\" \\\n  -d '{\n    \"jsonrpc\": \"2.0\",\n    \"id\": 1,\n    \"method\": \"getMasterchainInfo\",\n    \"params\": {}\n  }'\n```\n\nOr using the query parameter:\n\n```bash\ncurl \"https://testnet.toncenter.com/api/v2/jsonRPC?api_key=<API_KEY>\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"jsonrpc\": \"2.0\",\n    \"id\": 1,\n    \"method\": \"getMasterchainInfo\",\n    \"params\": {}\n  }'\n```\n\n## API key error codes\n\n| Status | Error                    | Meaning                                                                                                           |\n| -----: | ------------------------ | ----------------------------------------------------------------------------------------------------------------- |\n|  `401` | `API key does not exist` | The provided key is invalid. Check for typos or generate a new key.                                               |\n|  `403` | `Network not allowed`    | The key was issued for a different network (e.g., testnet key on mainnet). Use a key matching the target network. |\n|  `429` | `Ratelimit exceeded`     | Too many requests. Back off and retry, or use an API key for higher limits.                                       |\n"
  },
  {
    "path": "ecosystem/api/toncenter/v2-errors.mdx",
    "content": "---\ntitle: \"API error codes\"\nsidebarTitle: \"Error codes\"\n---\n\nAll TON Center API v2 methods use a standard set of HTTP status codes to indicate the result of a request.\n\n| Status code                 | Description                                                                                 |\n| --------------------------- | ------------------------------------------------------------------------------------------- |\n| `404 Not Found`             | The requested resource does not exist in storage.                                           |\n| `405 Method Not Allowed`    | The endpoint was called with an unsupported HTTP method. Use GET or POST.                   |\n| `409 Conflict`              | The resource was found but does not match the expected type for this method.                |\n| `422 Unprocessable Content` | The request parameters failed validation (e.g., missing, malformed, or conflicting values). |\n| `429 Too Many Requests`     | Too many requests. Back off and retry.                                                      |\n| `500 Internal Server Error` | An internal error occurred. Retry or contact support if it persists.                        |\n| `504 Gateway Timeout`       | The liteserver did not respond in time. Retry the request.                                  |\n| `542 Server Error`          | A liteserver error or an unsupported TVM stack type was encountered.                        |\n\nFor method-specific error messages and troubleshooting details, refer to the documentation for the relevant endpoint.\n"
  },
  {
    "path": "ecosystem/api/toncenter/v2-tonlib-types.mdx",
    "content": "---\ntitle: \"Tonlib type identifiers\"\n---\n\nEvery object returned by API v2 includes a `@type` field that identifies the object's structure. These values originate from two sources:\n\n1. Tonlib types such as `raw.fullAccountState` and `tvm.cell` come from the [tonlib TL schema](https://github.com/ton-blockchain/ton/blob/a31025f39ed0dae5f6799280133624dc3a23cefb/tl/generate/scheme/tonlib_api.tl), the type definition language used by the C++ library powering this API.\n1. Extended types, which are prefixed with `ext.`, are added by TON Center to provide parsed representations with additional decoded fields that are not available in the base tonlib schema.\n\nThe `@type` field acts as a **discriminator**: when a response can return different object shapes, the `@type` value indicates which fields to expect. This pattern is useful for type-safe deserialization in statically typed languages.\n\n```json\n{\n  \"@type\": \"raw.fullAccountState\",\n  \"balance\": \"1000000000\",\n  \"code\": \"te6cc...\",\n  \"data\": \"te6cc...\",\n  \"last_transaction_id\": {\n    \"@type\": \"internal.transactionId\",\n    \"lt\": \"12345678\",\n    \"hash\": \"abc...\"\n  }\n}\n```\n\n## TL primitive types\n\nThe TL schema maps to JSON types as follows:\n\n| TL type     | JSON type | Notes                                                          |\n| :---------- | :-------- | :------------------------------------------------------------- |\n| `int32`     | number    | 32-bit signed integer                                          |\n| `int53`     | number    | 53-bit signed integer; safe for JavaScript `Number`            |\n| `int64`     | string    | 64-bit signed integer as decimal string; exceeds JS safe range |\n| `int256`    | string    | 256-bit integer as decimal or hex string                       |\n| `bytes`     | string    | Binary data, base64-encoded                                    |\n| `string`    | string    | UTF-8 text                                                     |\n| `Bool`      | boolean   | `true` or `false`                                              |\n| `vector<T>` | array     | Ordered list of elements of type `T`                           |\n\n## Account state\n\nWhen querying account information, the `account_state` field uses `@type` to indicate which kind of contract is deployed. The TL schema defines these as variants of `AccountState`:\n\n```tl\nraw.accountState code:bytes data:bytes frozen_hash:bytes = AccountState;\nwallet.v3.accountState wallet_id:int64 seqno:int32 = AccountState;\nwallet.v4.accountState wallet_id:int64 seqno:int32 = AccountState;\nwallet.highload.v1.accountState wallet_id:int64 seqno:int32 = AccountState;\nwallet.highload.v2.accountState wallet_id:int64 = AccountState;\ndns.accountState wallet_id:int64 = AccountState;\nrwallet.accountState wallet_id:int64 seqno:int32 unlocked_balance:int64 config:rwallet.config = AccountState;\npchan.accountState config:pchan.config state:pchan.State description:string = AccountState;\nuninited.accountState frozen_hash:bytes = AccountState;\n```\n\n| `@type` value                     | API schema                     | TL fields                                          |\n| :-------------------------------- | :----------------------------- | :------------------------------------------------- |\n| `raw.accountState`                | `AccountStateRaw`              | `code`, `data`, `frozen_hash`                      |\n| `wallet.v3.accountState`          | `AccountStateWalletV3`         | `wallet_id`, `seqno`                               |\n| `wallet.v4.accountState`          | `AccountStateWalletV4`         | `wallet_id`, `seqno`                               |\n| `wallet.highload.v1.accountState` | `AccountStateWalletHighloadV1` | `wallet_id`, `seqno`                               |\n| `wallet.highload.v2.accountState` | `AccountStateWalletHighloadV2` | `wallet_id`                                        |\n| `dns.accountState`                | `AccountStateDns`              | `wallet_id`                                        |\n| `rwallet.accountState`            | `AccountStateRWallet`          | `wallet_id`, `seqno`, `unlocked_balance`, `config` |\n| `pchan.accountState`              | `AccountStatePChan`            | `config`, `state`, `description`                   |\n| `uninited.accountState`           | `AccountStateUninited`         | `frozen_hash`                                      |\n\n## Account information\n\nFull account queries return one of these top-level types:\n\n```tl\nraw.fullAccountState balance:int64 extra_currencies:vector<extraCurrency> code:bytes data:bytes\n    last_transaction_id:internal.transactionId block_id:ton.blockIdExt frozen_hash:bytes sync_utime:int53\n    = raw.FullAccountState;\n\nfullAccountState address:accountAddress balance:int64 extra_currencies:vector<extraCurrency>\n    last_transaction_id:internal.transactionId block_id:ton.blockIdExt sync_utime:int53\n    account_state:AccountState revision:int32\n    = FullAccountState;\n```\n\n| `@type` value                    | API schema                   | Description                                                          |\n| :------------------------------- | :--------------------------- | :------------------------------------------------------------------- |\n| `raw.fullAccountState`           | `AddressInformation`         | Raw state with balance, code, data, and frozen hash.                 |\n| `fullAccountState`               | `ExtendedAddressInformation` | Parsed state with identified contract type.                          |\n| `ext.accounts.walletInformation` | `WalletInformation`          | Wallet-specific: `type`, `seqno`, `wallet_id`; TON Center extension. |\n\n## Address types\n\n```tl\naccountAddress account_address:string = AccountAddress;\n```\n\n| `@type` value    | API schema       | TL fields         |\n| :--------------- | :--------------- | :---------------- |\n| `accountAddress` | `AccountAddress` | `account_address` |\n| `addr_std`       | `SmcAddr`        | `workchain`, `id` |\n\n## Block identifiers\n\n```tl\nton.blockIdExt workchain:int32 shard:int64 seqno:int32 root_hash:bytes file_hash:bytes = ton.BlockIdExt;\n```\n\n| `@type` value    | API schema      | TL fields                                               |\n| :--------------- | :-------------- | :------------------------------------------------------ |\n| `ton.blockIdExt` | `TonBlockIdExt` | `workchain`, `shard`, `seqno`, `root_hash`, `file_hash` |\n\n## Block data\n\nThese types are returned by block query endpoints. The TL definitions:\n\n```tl\nblocks.masterchainInfo last:ton.BlockIdExt state_root_hash:bytes init:ton.BlockIdExt = blocks.MasterchainInfo;\nblocks.shards shards:vector<ton.BlockIdExt> = blocks.Shards;\nblocks.header id:ton.blockIdExt global_id:int32 version:int32 flags:# after_merge:Bool after_split:Bool\n    before_split:Bool want_merge:Bool want_split:Bool validator_list_hash_short:int32 catchain_seqno:int32\n    min_ref_mc_seqno:int32 is_key_block:Bool prev_key_block_seqno:int32 start_lt:int64 end_lt:int64\n    gen_utime:int53 vert_seqno:# prev_blocks:vector<ton.blockIdExt> = blocks.Header;\nblocks.transactions id:ton.blockIdExt req_count:int32 incomplete:Bool\n    transactions:vector<blocks.shortTxId> = blocks.Transactions;\nblocks.transactionsExt id:ton.blockIdExt req_count:int32 incomplete:Bool\n    transactions:vector<raw.transaction> = blocks.TransactionsExt;\nblocks.blockSignatures id:ton.blockIdExt signatures:(vector blocks.signature) = blocks.BlockSignatures;\nblocks.shardBlockProof from:ton.blockIdExt mc_id:ton.blockIdExt\n    links:(vector blocks.shardBlockLink) mc_proof:(vector blocks.blockLinkBack) = blocks.ShardBlockProof;\nblocks.outMsgQueueSizes shards:(vector blocks.outMsgQueueSize)\n    ext_msg_queue_size_limit:int32 = blocks.OutMsgQueueSizes;\n```\n\n| `@type` value               | API schema                   | Description                                   |\n| :-------------------------- | :--------------------------- | :-------------------------------------------- |\n| `blocks.masterchainInfo`    | `MasterchainInfo`            | Latest and genesis block references.          |\n| `blocks.shards`             | `Shards`                     | Active shard block identifiers.               |\n| `blocks.header`             | `BlockHeader`                | Block metadata, merge or split flags, timing. |\n| `blocks.transactions`       | `BlockTransactions`          | Short transaction IDs within a block.         |\n| `blocks.transactionsExt`    | `BlockTransactionsExt`       | Full transactions within a block.             |\n| `blocks.shortTxId`          | `ShortTxId`                  | Compact reference: account, lt, hash.         |\n| `blocks.blockSignatures`    | `MasterchainBlockSignatures` | Validator signatures for a block.             |\n| `blocks.signature`          | `BlockSignature`             | Single validator signature.                   |\n| `blocks.shardBlockProof`    | `ShardBlockProof`            | Merkle proof chain to masterchain.            |\n| `blocks.shardBlockLink`     | `ShardBlockLink`             | Single link in a proof chain.                 |\n| `blocks.blockLinkBack`      | `BlockLinkBack`              | Backward proof link between blocks.           |\n| `blocks.outMsgQueueSize`    | `OutMsgQueueSize`            | Per-shard queue size.                         |\n| `blocks.outMsgQueueSizes`   | `OutMsgQueueSizes`           | Queue sizes across all shards.                |\n| `ext.blocks.consensusBlock` | `ConsensusBlock`             | Latest finalized block; TON Center extension. |\n\n## Transactions and messages\n\n```tl\nraw.transaction address:accountAddress utime:int53 data:bytes transaction_id:internal.transactionId\n    fee:int64 storage_fee:int64 other_fee:int64 in_msg:raw.message\n    out_msgs:vector<raw.message> = raw.Transaction;\nraw.transactions transactions:vector<raw.transaction>\n    previous_transaction_id:internal.transactionId = raw.Transactions;\nraw.message hash:bytes source:accountAddress destination:accountAddress value:int64\n    extra_currencies:vector<extraCurrency> fwd_fee:int64 ihr_fee:int64 created_lt:int64\n    body_hash:bytes msg_data:msg.Data = raw.Message;\nraw.extMessageInfo hash:bytes hash_norm:bytes = raw.ExtMessageInfo;\ninternal.transactionId lt:int64 hash:bytes = internal.TransactionId;\n```\n\n| `@type` value            | API schema              | Description                                               |\n| :----------------------- | :---------------------- | :-------------------------------------------------------- |\n| `raw.transaction`        | `TransactionStd`        | Raw transaction with messages and fees.                   |\n| `raw.transactions`       | `TransactionsStd`       | Paginated transaction list with cursor.                   |\n| `raw.message`            | `MessageStd`            | Raw message with sender, recipient, value.                |\n| `raw.extMessageInfo`     | `ExtMessageInfo`        | External message hash after broadcast.                    |\n| `internal.transactionId` | `InternalTransactionId` | Transaction reference: lt + hash.                         |\n| `ext.transaction`        | `Transaction`           | Transaction with decoded comments; TON Center extension.  |\n| `ext.message`            | `Message`               | Message with decoded text comments; TON Center extension. |\n\n### Message body types\n\nThe `msg_data` field on messages uses `@type` to indicate how to interpret the body:\n\n```tl\nmsg.dataRaw body:bytes init_state:bytes = msg.Data;\nmsg.dataText text:bytes = msg.Data;\nmsg.dataDecryptedText text:bytes = msg.Data;\nmsg.dataEncryptedText text:bytes = msg.Data;\n```\n\n| `@type` value           | API schema             | Description                               |\n| :---------------------- | :--------------------- | :---------------------------------------- |\n| `msg.dataRaw`           | `MsgDataRaw`           | Raw binary body + optional init state.    |\n| `msg.dataText`          | `MsgDataText`          | Plain text comment; base64-encoded UTF-8. |\n| `msg.dataEncryptedText` | `MsgDataEncryptedText` | Encrypted message body.                   |\n| `msg.dataDecryptedText` | `MsgDataDecryptedText` | Decrypted message body.                   |\n\n## TVM types\n\nUsed as input and output for smart contract get methods: `runGetMethod`, `runGetMethodStd`.\n\n### Stack entries\n\nEach stack entry wraps a value with a type tag:\n\n```tl\ntvm.stackEntryNumber number:tvm.Number = tvm.StackEntry;\ntvm.stackEntryCell cell:tvm.cell = tvm.StackEntry;\ntvm.stackEntrySlice slice:tvm.slice = tvm.StackEntry;\ntvm.stackEntryTuple tuple:tvm.Tuple = tvm.StackEntry;\ntvm.stackEntryList list:tvm.List = tvm.StackEntry;\ntvm.stackEntryUnsupported = tvm.StackEntry;\n```\n\n| `@type` value               | API schema                 | Value field                                       |\n| :-------------------------- | :------------------------- | :------------------------------------------------ |\n| `tvm.stackEntryNumber`      | `TvmStackEntryNumber`      | `number` (decimal string via `tvm.numberDecimal`) |\n| `tvm.stackEntryCell`        | `TvmStackEntryCell`        | `cell` (base64 BoC via `tvm.cell`)                |\n| `tvm.stackEntrySlice`       | `TvmStackEntrySlice`       | `slice` (base64 BoC via `tvm.slice`)              |\n| `tvm.stackEntryTuple`       | `TvmStackEntryTuple`       | `tuple` (nested stack entries)                    |\n| `tvm.stackEntryList`        | `TvmStackEntryList`        | `list` (nested stack entries)                     |\n| `tvm.stackEntryUnsupported` | `TvmStackEntryUnsupported` | No value (type not representable)                 |\n\n### Value types\n\n```tl\ntvm.cell bytes:bytes = tvm.Cell;\ntvm.slice bytes:bytes = tvm.Slice;\ntvm.numberDecimal number:string = tvm.Number;\ntvm.tuple elements:vector<tvm.StackEntry> = tvm.Tuple;\ntvm.list elements:vector<tvm.StackEntry> = tvm.List;\n```\n\n| `@type` value       | API schema         | TL fields                  |\n| :------------------ | :----------------- | :------------------------- |\n| `tvm.cell`          | `TvmCell`          | `bytes` (base64 BoC)       |\n| `tvm.slice`         | `TvmSlice`         | `bytes` (base64 BoC)       |\n| `tvm.numberDecimal` | `TvmNumberDecimal` | `number` (decimal string)  |\n| `tvm.tuple`         | `TvmTuple`         | `elements` (stack entries) |\n| `tvm.list`          | `TvmList`          | `elements` (stack entries) |\n\n### Get method result\n\n```tl\nsmc.runResult gas_used:int53 stack:vector<tvm.StackEntry> exit_code:int32 = smc.RunResult;\n```\n\n| `@type` value   | API schema              | TL fields                        |\n| :-------------- | :---------------------- | :------------------------------- |\n| `smc.runResult` | `RunGetMethodResult`    | `gas_used`, `stack`, `exit_code` |\n| `smc.runResult` | `RunGetMethodStdResult` | Same fields, typed stack entries |\n\n## Fees\n\n```tl\nfees in_fwd_fee:int53 storage_fee:int53 gas_fee:int53 fwd_fee:int53 = Fees;\nquery.fees source_fees:fees destination_fees:vector<fees> = query.Fees;\n```\n\n| `@type` value | API schema  | TL fields                                         |\n| :------------ | :---------- | :------------------------------------------------ |\n| `fees`        | `Fees`      | `in_fwd_fee`, `storage_fee`, `gas_fee`, `fwd_fee` |\n| `query.fees`  | `QueryFees` | `source_fees`, `destination_fees`                 |\n\n## Configuration\n\n```tl\nconfigInfo config:tvm.cell = ConfigInfo;\n```\n\n| `@type` value | API schema   | TL fields                         |\n| :------------ | :----------- | :-------------------------------- |\n| `configInfo`  | `ConfigInfo` | `config` TVM cell with parameters |\n\n## Libraries\n\n```tl\nsmc.libraryEntry hash:int256 data:bytes = smc.LibraryEntry;\nsmc.libraryResult result:(vector smc.libraryEntry) = smc.LibraryResult;\n```\n\n| `@type` value       | API schema      | TL fields          |\n| :------------------ | :-------------- | :----------------- |\n| `smc.libraryEntry`  | `LibraryEntry`  | `hash`, `data`     |\n| `smc.libraryResult` | `LibraryResult` | `result` (entries) |\n\n## Token types (TON Center extensions)\n\nThese types are not in the base tonlib TL schema. They are added by TON Center to provide parsed Jetton and NFT data via the `getTokenData` endpoint.\n\n| `@type` value                  | API schema          | Description                                      |\n| :----------------------------- | :------------------ | :----------------------------------------------- |\n| `ext.tokens.jettonMasterData`  | `JettonMasterData`  | Jetton master: total supply, admin, metadata.    |\n| `ext.tokens.jettonWalletData`  | `JettonWalletData`  | Jetton wallet: balance, owner, master reference. |\n| `ext.tokens.nftCollectionData` | `NftCollectionData` | NFT collection: item count, owner, metadata.     |\n| `ext.tokens.nftItemData`       | `NftItemData`       | NFT item: index, owner, collection reference.    |\n\n## DNS record types\n\nDNS entries use `@type` to indicate the record type stored at a domain:\n\n```tl\ndns.entryDataNextResolver resolver:AccountAddress = dns.EntryData;\ndns.entryDataSmcAddress smc_address:AccountAddress = dns.EntryData;\ndns.entryDataAdnlAddress adnl_address:AdnlAddress = dns.EntryData;\ndns.entryDataStorageAddress bag_id:int256 = dns.EntryData;\n```\n\n| `@type` value                  | API schema                | TL fields               |\n| :----------------------------- | :------------------------ | :---------------------- |\n| `dns.entryDataNextResolver`    | `DnsRecordNextResolver`   | `resolver` (address)    |\n| `dns.entryDataSmcAddress`      | `DnsRecordSmcAddress`     | `smc_address` (address) |\n| `dns.entryDataAdnlAddress `    | `DnsRecordAdnlAddress`    | `adnl_address`          |\n| `dns.entryDataStorageAddress ` | `DnsRecordStorageAddress` | `bag_id` (int256)       |\n\n## Payment channel types\n\n```tl\npchan.config alice_public_key:string alice_address:accountAddress bob_public_key:string\n    bob_address:accountAddress init_timeout:int32 close_timeout:int32 channel_id:int64 = pchan.Config;\npchan.stateInit signed_A:Bool signed_B:Bool min_A:int64 min_B:int64\n    expire_at:int53 A:int64 B:int64 = pchan.State;\npchan.stateClose signed_A:Bool signed_B:Bool min_A:int64 min_B:int64\n    expire_at:int53 A:int64 B:int64 = pchan.State;\npchan.statePayout A:int64 B:int64 = pchan.State;\n```\n\n| `@type` value       | API schema         | Description                    |\n| :------------------ | :----------------- | :----------------------------- |\n| `pchan.config`      | `PChanConfig`      | Channel parties, timeouts, ID  |\n| `pchan.stateInit`   | `PChanStateInit`   | Initialization phase (signing) |\n| `pchan.stateClose`  | `PChanStateClose`  | Closing phase (signing)        |\n| `pchan.statePayout` | `PChanStatePayout` | Payout phase (final balances)  |\n\n## Restricted wallet types\n\n```tl\nrwallet.limit seconds:int32 value:int64 = rwallet.Limit;\nrwallet.config start_at:int53 limits:vector<rwallet.limit> = rwallet.Config;\n```\n\n| `@type` value    | API schema      | TL fields            |\n| :--------------- | :-------------- | :------------------- |\n| `rwallet.config` | `RWalletConfig` | `start_at`, `limits` |\n| `rwallet.limit`  | `RWalletLimit`  | `seconds`, `value`   |\n\n## Utility types\n\nTON Center extensions.\n\n| `@type` value                      | API schema                   | Description                     |\n| :--------------------------------- | :--------------------------- | :------------------------------ |\n| `ext.utils.detectedAddress`        | `DetectAddress`              | Address in all encoding formats |\n| `ext.utils.detectedAddressVariant` | `DetectAddressBase64Variant` | Base64 and URL-safe base64 pair |\n| `ext.utils.detectedHash`           | `DetectHash`                 | Hash in hex, base64, URL-safe   |\n| `extraCurrency`                    | `ExtraCurrencyBalance`       | Non-TON currency ID and balance |\n| `ok`                               | `ResultOk`                   | Success with no return data     |\n\n## Reference\n\nFor background on the TL-B format used across the TON ecosystem, see the [TL-B overview](/languages/tl-b/overview).\n\nTypes prefixed with `ext.` are TON Center extensions not present in the upstream TL schema.\n"
  },
  {
    "path": "ecosystem/api/toncenter/v2.json",
    "content": "{\n  \"openapi\": \"3.1.0\",\n  \"info\": {\n    \"title\": \"TON HTTP API\",\n    \"description\": \"\\nThis API enables HTTP access to TON blockchain - getting accounts and wallets information, looking up blocks and transactions, sending messages to the blockchain, calling get methods of smart contracts, and more.\\n\\nIn addition to REST API, all methods are available through [JSON-RPC endpoint](#json%20rpc)  with `method` equal to method name and `params` passed as a dictionary.\\n\\nThe response contains a JSON object, which always has a boolean field `ok` and either `error` or `result`. If `ok` equals true, the request was successful and the result of the query can be found in the `result` field. In case of an unsuccessful request, `ok` equals false and the error is explained in the `error`.\\n\\nAPI Key should be sent either as `api_key` query parameter or `X-API-Key` header.\\n\",\n    \"version\": \"2.0.0\"\n  },\n  \"servers\": [\n    {\n      \"url\": \"https://toncenter.com/api/v2\"\n    },\n    {\n      \"url\": \"https://testnet.toncenter.com/api/v2\"\n    }\n  ],\n  \"paths\": {\n    \"/getAddressInformation\": {\n      \"get\": {\n        \"tags\": [\n          \"Accounts\"\n        ],\n        \"summary\": \"Get account state and balance\",\n        \"description\": \"Get basic information about the address: balance, code, data, last_transaction_id.\",\n        \"operationId\": \"get_address_information_getAddressInformation_get\",\n        \"parameters\": [\n          {\n            \"description\": \"Identifier of target TON account in any form.\",\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"Address\",\n              \"description\": \"Identifier of target TON account in any form.\"\n            },\n            \"name\": \"address\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/GetAddressInformationResponse\"\n                },\n                \"examples\": {\n                  \"sample\": {\n                    \"summary\": \"Example\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"@type\": \"raw.fullAccountState\",\n                        \"balance\": \"1592521995920473\",\n                        \"extra_currencies\": [],\n                        \"code\": \"te6cckEBAQEAcQAA3v8AIN0gggFMl7ohggEznLqxn3Gw7UTQ0x/THzHXC//jBOCk8mCDCNcYINMf0x/TH/gjE7vyY+1E0NMf0x/T/9FRMrryoVFEuvKiBPkBVBBV+RDyo/gAkyDXSpbTB9QC+wDo0QGkyMsfyx/L/8ntVBC9ba0=\",\n                        \"data\": \"te6cckEBAQEAKgAAUAAAAVUpqaMXcsnta2Km4uuhSpO5BGLno2d3e+uKOPsVufM4RNIs4v+Z1A2U\",\n                        \"last_transaction_id\": {\n                          \"@type\": \"internal.transactionId\",\n                          \"lt\": \"60294179000005\",\n                          \"hash\": \"opzfb6lX3inMMTbyvp8Z/FmrrdgZ4D/NPZvDZOkjd0E=\"\n                        },\n                        \"block_id\": {\n                          \"@type\": \"ton.blockIdExt\",\n                          \"workchain\": -1,\n                          \"shard\": \"-9223372036854775808\",\n                          \"seqno\": 50940162,\n                          \"root_hash\": \"S3S4Otb/vX2ZZDsOAB2a3Deqf3+K3aerm7qodto/nt8=\",\n                          \"file_hash\": \"h/bCahzQzEMzwRwnDBpzmN1m1/wjyA0BUy/HTtBbirs=\"\n                        },\n                        \"frozen_hash\": \"\",\n                        \"sync_utime\": 1755281542,\n                        \"@extra\": \"1755281559.4317498:12:0.19337888420712945\",\n                        \"state\": \"active\"\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/getExtendedAddressInformation\": {\n      \"get\": {\n        \"tags\": [\n          \"Accounts\"\n        ],\n        \"summary\": \"Get detailed account state (extended)\",\n        \"description\": \"Similar to previous one but tries to parse additional information for known contract types. This method is based on tonlib's function *getAccountState*. For detecting wallets we recommend to use *getWalletInformation*.\",\n        \"operationId\": \"get_extended_address_information_getExtendedAddressInformation_get\",\n        \"parameters\": [\n          {\n            \"description\": \"Identifier of target TON account in any form.\",\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"Address\",\n              \"description\": \"Identifier of target TON account in any form.\"\n            },\n            \"name\": \"address\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/GetExtendedAddressInformationResponse\"\n                },\n                \"examples\": {\n                  \"sample\": {\n                    \"summary\": \"Example\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"@type\": \"fullAccountState\",\n                        \"address\": {\n                          \"@type\": \"accountAddress\",\n                          \"account_address\": \"EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N\"\n                        },\n                        \"balance\": \"1592521995920473\",\n                        \"extra_currencies\": [],\n                        \"last_transaction_id\": {\n                          \"@type\": \"internal.transactionId\",\n                          \"lt\": \"60294179000005\",\n                          \"hash\": \"opzfb6lX3inMMTbyvp8Z/FmrrdgZ4D/NPZvDZOkjd0E=\"\n                        },\n                        \"block_id\": {\n                          \"@type\": \"ton.blockIdExt\",\n                          \"workchain\": -1,\n                          \"shard\": \"-9223372036854775808\",\n                          \"seqno\": 50940791,\n                          \"root_hash\": \"8Zcn3qPdpJY5nBOIOG5h/v3ABrPRQoahCOgbSmmICS0=\",\n                          \"file_hash\": \"BLvAHAZGs/Zoozhdsn5VvADALGQc+CoaQBSUqj1tKWo=\"\n                        },\n                        \"sync_utime\": 1755283118,\n                        \"account_state\": {\n                          \"@type\": \"wallet.v3.accountState\",\n                          \"wallet_id\": \"698983191\",\n                          \"seqno\": 341\n                        },\n                        \"revision\": 2,\n                        \"@extra\": \"1755283135.0102983:6:0.11795169251963\"\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/getWalletInformation\": {\n      \"get\": {\n        \"tags\": [\n          \"Accounts\"\n        ],\n        \"summary\": \"Get wallet information\",\n        \"description\": \"Retrieve wallet information. This method parses contract state and currently supports more wallet types than getExtendedAddressInformation: simple wallet, standard wallet, v3 wallet, v4 wallet.\",\n        \"operationId\": \"get_wallet_information_getWalletInformation_get\",\n        \"parameters\": [\n          {\n            \"description\": \"Identifier of target TON account in any form.\",\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"Address\",\n              \"description\": \"Identifier of target TON account in any form.\"\n            },\n            \"name\": \"address\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/GetWalletInformationResponse\"\n                },\n                \"examples\": {\n                  \"sample\": {\n                    \"summary\": \"Example\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"wallet\": true,\n                        \"balance\": \"1592521995920473\",\n                        \"extra_currencies\": [],\n                        \"account_state\": \"active\",\n                        \"wallet_type\": \"v3\",\n                        \"seqno\": 341,\n                        \"last_transaction_id\": {\n                          \"lt\": \"60294179000005\",\n                          \"hash\": \"opzfb6lX3inMMTbyvp8Z/FmrrdgZ4D/NPZvDZOkjd0E=\"\n                        },\n                        \"wallet_id\": \"698983191\",\n                        \"public_key\": \"0x...\"\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/getTransactions\": {\n      \"get\": {\n        \"tags\": [\n          \"Accounts\",\n          \"Transactions\"\n        ],\n        \"summary\": \"List account transactions\",\n        \"description\": \"Get transaction history of a given address.\",\n        \"operationId\": \"get_transactions_getTransactions_get\",\n        \"parameters\": [\n          {\n            \"description\": \"Identifier of target TON account in any form.\",\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"Address\",\n              \"description\": \"Identifier of target TON account in any form.\"\n            },\n            \"name\": \"address\",\n            \"in\": \"query\"\n          },\n          {\n            \"description\": \"Maximum number of transactions in response.\",\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"maximum\": 100,\n              \"exclusiveMinimum\": 0,\n              \"title\": \"Limit\",\n              \"description\": \"Maximum number of transactions in response.\",\n              \"default\": 10\n            },\n            \"name\": \"limit\",\n            \"in\": \"query\"\n          },\n          {\n            \"description\": \"Logical time of transaction to start with, must be sent with *hash*.\",\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Lt\",\n              \"description\": \"Logical time of transaction to start with, must be sent with *hash*.\"\n            },\n            \"name\": \"lt\",\n            \"in\": \"query\"\n          },\n          {\n            \"description\": \"Hash of transaction to start with, in *base64* or *hex* encoding , must be sent with *lt*.\",\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"Hash\",\n              \"description\": \"Hash of transaction to start with, in *base64* or *hex* encoding , must be sent with *lt*.\"\n            },\n            \"name\": \"hash\",\n            \"in\": \"query\"\n          },\n          {\n            \"description\": \"Logical time of transaction to finish with (to get tx from *lt* to *to_lt*).\",\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"To Lt\",\n              \"description\": \"Logical time of transaction to finish with (to get tx from *lt* to *to_lt*).\",\n              \"default\": 0\n            },\n            \"name\": \"to_lt\",\n            \"in\": \"query\"\n          },\n          {\n            \"description\": \"By default getTransaction request is processed by any available liteserver. If *archival=true* only liteservers with full history are used.\",\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"boolean\",\n              \"title\": \"Archival\",\n              \"description\": \"By default getTransaction request is processed by any available liteserver. If *archival=true* only liteservers with full history are used.\",\n              \"default\": false\n            },\n            \"name\": \"archival\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/TonResponse\"\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/getAddressBalance\": {\n      \"get\": {\n        \"tags\": [\n          \"Accounts\"\n        ],\n        \"summary\": \"Get account balance only\",\n        \"description\": \"Get balance (in nanotons) of a given address.\",\n        \"operationId\": \"get_address_balance_getAddressBalance_get\",\n        \"parameters\": [\n          {\n            \"description\": \"Identifier of target TON account in any form.\",\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"Address\",\n              \"description\": \"Identifier of target TON account in any form.\"\n            },\n            \"name\": \"address\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/StringResultResponse\"\n                },\n                \"examples\": {\n                  \"sample\": {\n                    \"summary\": \"Example\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": \"1592521995920473\"\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/getAddressState\": {\n      \"get\": {\n        \"tags\": [\n          \"Accounts\"\n        ],\n        \"summary\": \"Get account lifecycle state\",\n        \"description\": \"Get state of a given address. State can be either *unitialized*, *active* or *frozen*.\",\n        \"operationId\": \"get_address_getAddressState_get\",\n        \"parameters\": [\n          {\n            \"description\": \"Identifier of target TON account in any form.\",\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"Address\",\n              \"description\": \"Identifier of target TON account in any form.\"\n            },\n            \"name\": \"address\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/AddressStateResponse\"\n                },\n                \"examples\": {\n                  \"sample\": {\n                    \"summary\": \"Example\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": \"active\"\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/packAddress\": {\n      \"get\": {\n        \"tags\": [\n          \"Accounts\"\n        ],\n        \"summary\": \"Convert raw address to user-friendly format\",\n        \"description\": \"Convert an address from raw to human-readable format.\",\n        \"operationId\": \"pack_address_packAddress_get\",\n        \"parameters\": [\n          {\n            \"description\": \"Identifier of target TON account in raw form.\",\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"Address\",\n              \"description\": \"Identifier of target TON account in raw form.\"\n            },\n            \"example\": \"0:83DFD552E63729B472FCBCC8C45EBCC6691702558B68EC7527E1BA403A0F31A8\",\n            \"name\": \"address\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/StringResultResponse\"\n                },\n                \"examples\": {\n                  \"sample\": {\n                    \"summary\": \"Example\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": \"EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N\"\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/unpackAddress\": {\n      \"get\": {\n        \"tags\": [\n          \"Accounts\"\n        ],\n        \"summary\": \"Convert user-friendly address to raw format\",\n        \"description\": \"Convert an address from human-readable to raw format.\",\n        \"operationId\": \"unpack_address_unpackAddress_get\",\n        \"parameters\": [\n          {\n            \"description\": \"Identifier of target TON account in user-friendly form\",\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"Address\",\n              \"description\": \"Identifier of target TON account in user-friendly form\"\n            },\n            \"example\": \"EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N\",\n            \"name\": \"address\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/StringResultResponse\"\n                },\n                \"examples\": {\n                  \"sample\": {\n                    \"summary\": \"Example\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": \"0:83DFD552E63729B472FCBCC8C45EBCC6691702558B68EC7527E1BA403A0F31A8\"\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/getMasterchainInfo\": {\n      \"get\": {\n        \"tags\": [\n          \"Blocks\"\n        ],\n        \"summary\": \"Get latest masterchain info\",\n        \"description\": \"Get up-to-date masterchain state.\",\n        \"operationId\": \"get_masterchain_info_getMasterchainInfo_get\",\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/GetMasterchainInfoResponse\"\n                },\n                \"examples\": {\n                  \"sample1\": {\n                    \"summary\": \"Example 1\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"@type\": \"blocks.masterchainInfo\",\n                        \"last\": {\n                          \"@type\": \"ton.blockIdExt\",\n                          \"workchain\": -1,\n                          \"shard\": \"-9223372036854775808\",\n                          \"seqno\": 51148696,\n                          \"root_hash\": \"pdEYB4jzhoEFdOMdCgfXJ0z4vylDW27ETqVaSJEDyqs=\",\n                          \"file_hash\": \"l3sF5XbGapYGFnma+6dIk0fuZYdJYO4yAkNsjDkyxcc=\"\n                        },\n                        \"state_root_hash\": \"qJ2FQ7fySAnOvgIKI9laL5Mgk8rQWT+Tc/O2xUFzwWs=\",\n                        \"init\": {\n                          \"@type\": \"ton.blockIdExt\",\n                          \"workchain\": -1,\n                          \"shard\": \"0\",\n                          \"seqno\": 0,\n                          \"root_hash\": \"F6OpKZKqvqeFp6CQmFomXNMfMj2EnaUSOXN+Mh+wVWk=\",\n                          \"file_hash\": \"XplPz01CXAps5qeSWUtxcyBfdAo5zVb1N979KLSKD24=\"\n                        },\n                        \"@extra\": \"1755812855.1928415:3:0.47373957740114636\"\n                      }\n                    }\n                  },\n                  \"sample2\": {\n                    \"summary\": \"Example 2\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"@type\": \"blocks.masterchainInfo\",\n                        \"last\": {\n                          \"@type\": \"ton.blockIdExt\",\n                          \"workchain\": -1,\n                          \"shard\": \"-9223372036854775808\",\n                          \"seqno\": 34539805,\n                          \"root_hash\": \"z1gmtb/KbcNwHDVLOHphfDcYMfDtRyW5sTDLuNbPd2E=\",\n                          \"file_hash\": \"/3zsB+Lr0mONcRGZ+tx2jNC1VkOHCXfmjJ9Wai2iUlQ=\"\n                        },\n                        \"state_root_hash\": \"/WR0k35BrgggvPUVglES3I4wt3SrHvU39T5YQQ0Dd2w=\",\n                        \"init\": {\n                          \"@type\": \"ton.blockIdExt\",\n                          \"workchain\": -1,\n                          \"shard\": \"0\",\n                          \"seqno\": 0,\n                          \"root_hash\": \"gj+B8wb/AmlPk1z1AhVI484rhrUpgSr2oSFIh56VoSg=\",\n                          \"file_hash\": \"Z+IKwYS54DmmJmesw/nAD5DzWadnOCMzee+kdgSYDOg=\"\n                        }\n                      },\n                      \"@extra\": \"1755812953:0:0.712\"\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/getMasterchainBlockSignatures\": {\n      \"get\": {\n        \"tags\": [\n          \"Blocks\"\n        ],\n        \"summary\": \"Get masterchain block signatures\",\n        \"description\": \"Get up-to-date masterchain state.\",\n        \"operationId\": \"get_masterchain_block_signatures_getMasterchainBlockSignatures_get\",\n        \"parameters\": [\n          {\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Seqno\"\n            },\n            \"name\": \"seqno\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/GetMasterchainBlockSignaturesResponse\"\n                },\n                \"examples\": {\n                  \"sample\": {\n                    \"summary\": \"Block signatures example (truncated)\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"@type\": \"blocks.blockSignatures\",\n                        \"id\": {\n                          \"@type\": \"ton.blockIdExt\",\n                          \"workchain\": -1,\n                          \"shard\": \"-9223372036854775808\",\n                          \"seqno\": 51148806,\n                          \"root_hash\": \"I/+MoS7TB7Zuw+g5QH3bPBFMcM5Wf4h1Coig3g2osFQ=\",\n                          \"file_hash\": \"BhPAjDTVPDqH8z6DLq9jAjZiZiiIUQW/f667jJgfoyw=\"\n                        },\n                        \"signatures\": [\n                          {\n                            \"@type\": \"blocks.signature\",\n                            \"node_id_short\": \"axRYlEuV/4Fo94EbDtfpEnqJukpAsNNgmZqQz7e01ew=\",\n                            \"signature\": \"xTBbMLBnJau/VxzOln6jW2zwIMx4WY/+hO3IWwqklNnAAzvYY2X/pqutkJNj5E1f4BjKp84sukuTErS0fFZUAA==\"\n                          }\n                        ],\n                        \"@extra\": \"1755813145.584844:11:0.877388442408124\"\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/getShardBlockProof\": {\n      \"get\": {\n        \"tags\": [\n          \"Blocks\"\n        ],\n        \"summary\": \"Get shard block proof\",\n        \"description\": \"Get merkle proof of shardchain block.\",\n        \"operationId\": \"get_shard_block_proof_getShardBlockProof_get\",\n        \"parameters\": [\n          {\n            \"description\": \"Block workchain id\",\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Workchain\",\n              \"description\": \"Block workchain id\"\n            },\n            \"name\": \"workchain\",\n            \"in\": \"query\"\n          },\n          {\n            \"description\": \"Block shard id\",\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Shard\",\n              \"description\": \"Block shard id\"\n            },\n            \"name\": \"shard\",\n            \"in\": \"query\"\n          },\n          {\n            \"description\": \"Block seqno\",\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Seqno\",\n              \"description\": \"Block seqno\"\n            },\n            \"name\": \"seqno\",\n            \"in\": \"query\"\n          },\n          {\n            \"description\": \"Seqno of masterchain block starting from which proof is required. If not specified latest masterchain block is used.\",\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"From Seqno\",\n              \"description\": \"Seqno of masterchain block starting from which proof is required. If not specified latest masterchain block is used.\"\n            },\n            \"name\": \"from_seqno\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/GetShardBlockProofResponse\"\n                },\n                \"examples\": {\n                  \"sample\": {\n                    \"summary\": \"Shard block proof example\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"@type\": \"blocks.shardBlockProof\",\n                        \"from\": {\n                          \"@type\": \"ton.blockIdExt\",\n                          \"workchain\": -1,\n                          \"shard\": \"-9223372036854775808\",\n                          \"seqno\": 51148869,\n                          \"root_hash\": \"HxogBiV2YA+KrC9cJa5llfvDGNk2hwCqsaCSYo40V00=\",\n                          \"file_hash\": \"h7LOaX0cTqc8qKecsNYi32SVu0McCito3P2qzynvdqk=\"\n                        },\n                        \"mc_id\": {\n                          \"@type\": \"ton.blockIdExt\",\n                          \"workchain\": -1,\n                          \"shard\": \"-9223372036854775808\",\n                          \"seqno\": 51148869,\n                          \"root_hash\": \"HxogBiV2YA+KrC9cJa5llfvDGNk2hwCqsaCSYo40V00=\",\n                          \"file_hash\": \"h7LOaX0cTqc8qKecsNYi32SVu0McCito3P2qzynvdqk=\"\n                        },\n                        \"links\": [],\n                        \"mc_proof\": [],\n                        \"@extra\": \"1755813789.6827312:12:0.9450183392434569\"\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/getConsensusBlock\": {\n      \"get\": {\n        \"tags\": [\n          \"Blocks\"\n        ],\n        \"summary\": \"Get latest consensus block\",\n        \"description\": \"Get consensus block and its update timestamp.\",\n        \"operationId\": \"get_consensus_block_getConsensusBlock_get\",\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/GetConsensusBlockResponse\"\n                },\n                \"examples\": {\n                  \"sample1\": {\n                    \"summary\": \"Consensus block example 1\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"@type\": \"blocks.masterchainInfo\",\n                        \"last\": {\n                          \"@type\": \"ton.blockIdExt\",\n                          \"workchain\": -1,\n                          \"shard\": \"-9223372036854775808\",\n                          \"seqno\": 51148869,\n                          \"root_hash\": \"HxogBiV2YA+KrC9cJa5llfvDGNk2hwCqsaCSYo40V00=\",\n                          \"file_hash\": \"h7LOaX0cTqc8qKecsNYi32SVu0McCito3P2qzynvdqk=\"\n                        },\n                        \"state_root_hash\": \"SU9xlvY1tnXd/E06/9Ls8DOjNcCNpqf4wtJhC0+viok=\",\n                        \"init\": {\n                          \"@type\": \"ton.blockIdExt\",\n                          \"workchain\": -1,\n                          \"shard\": \"0\",\n                          \"seqno\": 0,\n                          \"root_hash\": \"F6OpKZKqvqeFp6CQmFomXNMfMj2EnaUSOXN+Mh+wVWk=\",\n                          \"file_hash\": \"XplPz01CXAps5qeSWUtxcyBfdAo5zVb1N979KLSKD24=\"\n                        },\n                        \"@extra\": \"1755813293.2727234:6:0.6121521629223031\"\n                      }\n                    }\n                  },\n                  \"sample2\": {\n                    \"summary\": \"Consensus block example 2\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"@type\": \"blocks.masterchainInfo\",\n                        \"last\": {\n                          \"@type\": \"ton.blockIdExt\",\n                          \"workchain\": -1,\n                          \"shard\": \"-9223372036854775808\",\n                          \"seqno\": 34540013,\n                          \"root_hash\": \"uX5uaK8EVq90YRy3hTgdMzM2bjnXkcqcKOZJPAFv+Dk=\",\n                          \"file_hash\": \"68Zd55gJrmESJD6MAqua4yADxYUg6zOhh8BFzl3GRrA=\"\n                        },\n                        \"state_root_hash\": \"FVv5b6iHA/9IBdUtGGCAOWthmqJpwikz4J2UdcbLjEk=\",\n                        \"init\": {\n                          \"@type\": \"ton.blockIdExt\",\n                          \"workchain\": -1,\n                          \"shard\": \"0\",\n                          \"seqno\": 0,\n                          \"root_hash\": \"gj+B8wb/AmlPk1z1AhVI484rhrUpgSr2oSFIh56VoSg=\",\n                          \"file_hash\": \"Z+IKwYS54DmmJmesw/nAD5DzWadnOCMzee+kdgSYDOg=\"\n                        }\n                      },\n                      \"@extra\": \"1755813463:11:25.756\"\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/lookupBlock\": {\n      \"get\": {\n        \"tags\": [\n          \"Blocks\"\n        ],\n        \"summary\": \"Look up block by height, LT, or timestamp\",\n        \"description\": \"Look up block by either *seqno*, *lt* or *unixtime*.\",\n        \"operationId\": \"lookup_block_lookupBlock_get\",\n        \"parameters\": [\n          {\n            \"description\": \"Workchain id to look up block in\",\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Workchain\",\n              \"description\": \"Workchain id to look up block in\"\n            },\n            \"name\": \"workchain\",\n            \"in\": \"query\"\n          },\n          {\n            \"description\": \"Shard id to look up block in\",\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Shard\",\n              \"description\": \"Shard id to look up block in\"\n            },\n            \"name\": \"shard\",\n            \"in\": \"query\"\n          },\n          {\n            \"description\": \"Block's height\",\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Seqno\",\n              \"description\": \"Block's height\"\n            },\n            \"name\": \"seqno\",\n            \"in\": \"query\"\n          },\n          {\n            \"description\": \"Block's logical time\",\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Lt\",\n              \"description\": \"Block's logical time\"\n            },\n            \"name\": \"lt\",\n            \"in\": \"query\"\n          },\n          {\n            \"description\": \"Block's unixtime\",\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Unixtime\",\n              \"description\": \"Block's unixtime\"\n            },\n            \"name\": \"unixtime\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/LookupBlockResponse\"\n                },\n                \"examples\": {\n                  \"sample\": {\n                    \"summary\": \"Lookup block example\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"@type\": \"ton.blockIdExt\",\n                        \"workchain\": -1,\n                        \"shard\": \"-9223372036854775808\",\n                        \"seqno\": 51148869,\n                        \"root_hash\": \"HxogBiV2YA+KrC9cJa5llfvDGNk2hwCqsaCSYo40V00=\",\n                        \"file_hash\": \"h7LOaX0cTqc8qKecsNYi32SVu0McCito3P2qzynvdqk=\",\n                        \"@extra\": \"1755814026.5747118:7:0.2443600480097572\"\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/shards\": {\n      \"get\": {\n        \"tags\": [\n          \"Blocks\"\n        ],\n        \"summary\": \"Get shards at masterchain seqno\",\n        \"description\": \"Get shards information.\",\n        \"operationId\": \"get_shards_shards_get\",\n        \"parameters\": [\n          {\n            \"description\": \"Masterchain seqno to fetch shards of.\",\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Seqno\",\n              \"description\": \"Masterchain seqno to fetch shards of.\"\n            },\n            \"name\": \"seqno\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/ShardsResponse\"\n                },\n                \"examples\": {\n                  \"sample\": {\n                    \"summary\": \"Shards example\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"@type\": \"blocks.shards\",\n                        \"shards\": [\n                          {\n                            \"@type\": \"ton.blockIdExt\",\n                            \"workchain\": 0,\n                            \"shard\": \"-9223372036854775808\",\n                            \"seqno\": 56262735,\n                            \"root_hash\": \"02rdYNPA1GWvph+2udLPvddNDvtP/nglA7Q8HR82KMk=\",\n                            \"file_hash\": \"Ae/QaLnzAhzr2TCHJWFMb+yAg64roTKDq6qLAA7Pt58=\"\n                          }\n                        ],\n                        \"@extra\": \"1755814149.1458454:3:0.786727927934394\"\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/getBlockTransactions\": {\n      \"get\": {\n        \"tags\": [\n          \"Blocks\",\n          \"Transactions\"\n        ],\n        \"summary\": \"List block transactions\",\n        \"description\": \"Get transactions of the given block.\",\n        \"operationId\": \"get_block_transactions_getBlockTransactions_get\",\n        \"parameters\": [\n          {\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Workchain\"\n            },\n            \"name\": \"workchain\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Shard\"\n            },\n            \"name\": \"shard\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Seqno\"\n            },\n            \"name\": \"seqno\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"Root Hash\"\n            },\n            \"name\": \"root_hash\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"File Hash\"\n            },\n            \"name\": \"file_hash\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"After Lt\"\n            },\n            \"name\": \"after_lt\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"After Hash\"\n            },\n            \"name\": \"after_hash\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Count\",\n              \"default\": 40\n            },\n            \"name\": \"count\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/GetBlockTransactionsResponse\"\n                },\n                \"examples\": {\n                  \"sample\": {\n                    \"summary\": \"Block transactions example (truncated)\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"@type\": \"blocks.transactions\",\n                        \"id\": {\n                          \"@type\": \"ton.blockIdExt\",\n                          \"workchain\": -1,\n                          \"shard\": \"-9223372036854775808\",\n                          \"seqno\": 2,\n                          \"root_hash\": \"4bzgnFItQjTVEMYL9c/VHshMJttG9gDIXCzsMQdjKSU=\",\n                          \"file_hash\": \"2gOSTo8fuMWgA18snVD1RUtTfpU5LvCQWOOQ16Z7w5Y=\"\n                        },\n                        \"req_count\": 40,\n                        \"incomplete\": false,\n                        \"transactions\": [\n                          {\n                            \"@type\": \"blocks.shortTxId\",\n                            \"mode\": 135,\n                            \"account\": \"-1:0000000000000000000000000000000000000000000000000000000000000000\",\n                            \"lt\": \"2000001\",\n                            \"hash\": \"LdAqBYfzsG3XSu0fYdYNXqkWCGZ495u/9KGf7BUQTxY=\"\n                          }\n                        ],\n                        \"@extra\": \"1755814400.2039871:0:0.4571250134343233\"\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/getBlockTransactionsExt\": {\n      \"get\": {\n        \"tags\": [\n          \"Blocks\",\n          \"Transactions\"\n        ],\n        \"summary\": \"List block transactions (extended details)\",\n        \"description\": \"Get transactions of the given block.\",\n        \"operationId\": \"get_block_transactions_ext_getBlockTransactionsExt_get\",\n        \"parameters\": [\n          {\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Workchain\"\n            },\n            \"name\": \"workchain\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Shard\"\n            },\n            \"name\": \"shard\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Seqno\"\n            },\n            \"name\": \"seqno\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"Root Hash\"\n            },\n            \"name\": \"root_hash\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"File Hash\"\n            },\n            \"name\": \"file_hash\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"After Lt\"\n            },\n            \"name\": \"after_lt\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"After Hash\"\n            },\n            \"name\": \"after_hash\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Count\",\n              \"default\": 40\n            },\n            \"name\": \"count\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/GetBlockTransactionsExtResponse\"\n                },\n                \"examples\": {\n                  \"sample\": {\n                    \"summary\": \"Extended block transactions example (truncated)\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"@type\": \"blocks.transactionsExt\",\n                        \"id\": {\n                          \"@type\": \"ton.blockIdExt\",\n                          \"workchain\": -1,\n                          \"shard\": \"-9223372036854775808\",\n                          \"seqno\": 1,\n                          \"root_hash\": \"8GYhhrigd8CwZGrRT59iulLDcgiTYuvOAzFJxugc0Ts=\",\n                          \"file_hash\": \"V+XzykEwun4yePZhAEPZk77RbMfMOgS/S4GiJkSKY6s=\"\n                        },\n                        \"req_count\": 40,\n                        \"incomplete\": false,\n                        \"transactions\": [\n                          {\n                            \"@type\": \"raw.transaction\",\n                            \"address\": {\n                              \"@type\": \"accountAddress\",\n                              \"account_address\": \"Ef8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAU\"\n                            },\n                            \"utime\": 1573822385,\n                            \"data\": \"te6cckECCAEAASUAA69w...\",\n                            \"transaction_id\": {\n                              \"@type\": \"internal.transactionId\",\n                              \"lt\": \"1000001\",\n                              \"hash\": \"50ctdvRx74CQ4/JW5ziragzoKzYhgxCTjPtrtjD61TU=\"\n                            },\n                            \"fee\": \"0\",\n                            \"storage_fee\": \"0\",\n                            \"other_fee\": \"0\",\n                            \"in_msg\": {\n                              \"@type\": \"raw.message\",\n                              \"hash\": \"5sUeIdwmkqF4ye2/w904xrE2H+Kcg66mZZqT0Dlab8o=\",\n                              \"source\": {\n                                \"@type\": \"accountAddress\",\n                                \"account_address\": \"Ef8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAU\"\n                              },\n                              \"destination\": {\n                                \"@type\": \"accountAddress\",\n                                \"account_address\": \"Ef8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAU\"\n                              },\n                              \"value\": \"0\",\n                              \"extra_currencies\": [\n                                {\n                                  \"@type\": \"extraCurrency\",\n                                  \"id\": 239,\n                                  \"amount\": \"666666666666\"\n                                },\n                                {\n                                  \"@type\": \"extraCurrency\",\n                                  \"id\": -17,\n                                  \"amount\": \"1000000000000\"\n                                }\n                              ],\n                              \"fwd_fee\": \"0\",\n                              \"ihr_fee\": \"0\",\n                              \"created_lt\": \"1000000\",\n                              \"body_hash\": \"lqKW0iTyhcZ77pPDD4owkVfw2qNdxbh+QQt4YwoJz8c=\",\n                              \"msg_data\": {\n                                \"@type\": \"msg.dataRaw\",\n                                \"body\": \"te6cckEBAQEAAgAAAEysuc0=\",\n                                \"init_state\": \"\"\n                              }\n                            },\n                            \"out_msgs\": [],\n                            \"account\": \"-1:0000000000000000000000000000000000000000000000000000000000000000\"\n                          }\n                        ],\n                        \"@extra\": \"1755814593.0613906:1:0.8158701007745434\"\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/getBlockHeader\": {\n      \"get\": {\n        \"tags\": [\n          \"Blocks\"\n        ],\n        \"summary\": \"Get block header metadata\",\n        \"description\": \"Get metadata of a given block.\",\n        \"operationId\": \"get_block_header_getBlockHeader_get\",\n        \"parameters\": [\n          {\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Workchain\"\n            },\n            \"name\": \"workchain\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Shard\"\n            },\n            \"name\": \"shard\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Seqno\"\n            },\n            \"name\": \"seqno\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"Root Hash\"\n            },\n            \"name\": \"root_hash\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"File Hash\"\n            },\n            \"name\": \"file_hash\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/GetBlockHeaderResponse\"\n                },\n                \"examples\": {\n                  \"sample\": {\n                    \"summary\": \"Block header example\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"@type\": \"blocks.header\",\n                        \"id\": {\n                          \"@type\": \"ton.blockIdExt\",\n                          \"workchain\": -1,\n                          \"shard\": \"-9223372036854775808\",\n                          \"seqno\": 1,\n                          \"root_hash\": \"8GYhhrigd8CwZGrRT59iulLDcgiTYuvOAzFJxugc0Ts=\",\n                          \"file_hash\": \"V+XzykEwun4yePZhAEPZk77RbMfMOgS/S4GiJkSKY6s=\"\n                        },\n                        \"global_id\": -239,\n                        \"version\": 0,\n                        \"after_merge\": false,\n                        \"after_split\": false,\n                        \"before_split\": false,\n                        \"want_merge\": false,\n                        \"want_split\": false,\n                        \"validator_list_hash_short\": -1447544682,\n                        \"catchain_seqno\": 0,\n                        \"min_ref_mc_seqno\": 1,\n                        \"is_key_block\": false,\n                        \"prev_key_block_seqno\": 0,\n                        \"start_lt\": \"1000000\",\n                        \"end_lt\": \"1000012\",\n                        \"gen_utime\": 1573822385,\n                        \"prev_blocks\": [\n                          {\n                            \"@type\": \"ton.blockIdExt\",\n                            \"workchain\": -1,\n                            \"shard\": \"-9223372036854775808\",\n                            \"seqno\": 0,\n                            \"root_hash\": \"F6OpKZKqvqeFp6CQmFomXNMfMj2EnaUSOXN+Mh+wVWk=\",\n                            \"file_hash\": \"XplPz01CXAps5qeSWUtxcyBfdAo5zVb1N979KLSKD24=\"\n                          }\n                        ],\n                        \"@extra\": \"1755814930.1088252:0:0.1467032130574265\"\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/getConfigParam\": {\n      \"get\": {\n        \"tags\": [\n          \"Config\"\n        ],\n        \"summary\": \"Get single config parameter\",\n        \"description\": \"Get config by id.\",\n        \"operationId\": \"get_config_param_getConfigParam_get\",\n        \"parameters\": [\n          {\n            \"description\": \"Config id\",\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Config Id\",\n              \"description\": \"Config id\"\n            },\n            \"name\": \"config_id\",\n            \"in\": \"query\"\n          },\n          {\n            \"description\": \"Masterchain seqno. If not specified, latest blockchain state will be used.\",\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Seqno\",\n              \"description\": \"Masterchain seqno. If not specified, latest blockchain state will be used.\"\n            },\n            \"name\": \"seqno\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/GetConfigParamResponse\"\n                },\n                \"examples\": {\n                  \"sample1\": {\n                    \"summary\": \"Config param example 1\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"@type\": \"configInfo\",\n                        \"config\": {\n                          \"@type\": \"tvm.cell\",\n                          \"bytes\": \"te6cckEBAQEAIgAAQFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV+A4W5w==\"\n                        },\n                        \"@extra\": \"1755815155.2328486:7:0.49669713612622723\"\n                      }\n                    }\n                  },\n                  \"sample2\": {\n                    \"summary\": \"Config param example 2\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"@type\": \"configInfo\",\n                        \"config\": {\n                          \"@type\": \"tvm.cell\",\n                          \"bytes\": \"te6cckEBAQEAHgAAN3ARDZMW7AAHI4byb8EAAIAQp0GkYngAAAAwAAhFxfKI\"\n                        },\n                        \"@extra\": \"1755815171.7872128:2:0.12302096281892438\"\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/getConfigAll\": {\n      \"get\": {\n        \"tags\": [\n          \"Config\"\n        ],\n        \"summary\": \"Get all config parameters\",\n        \"description\": \"Get cell with full config.\",\n        \"operationId\": \"get_config_all_getConfigAll_get\",\n        \"parameters\": [\n          {\n            \"description\": \"Masterchain seqno. If not specified, latest blockchain state will be used.\",\n            \"required\": false,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Seqno\",\n              \"description\": \"Masterchain seqno. If not specified, latest blockchain state will be used.\"\n            },\n            \"name\": \"seqno\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/GetConfigAllResponse\"\n                },\n                \"examples\": {\n                  \"sample\": {\n                    \"summary\": \"All config parameters example\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"@type\": \"configInfo\",\n                        \"config\": {\n                          \"@type\": \"tvm.cell\",\n                          \"bytes\": \"te6cckIDB4wAAQAAARdQAAAACASAAAQAgLgYAAAAAgAAAAAAAQAAAAA=\"\n                        },\n                        \"@extra\": \"1755815324.351419:11:0.2985065689610278\"\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/getLibraries\": {\n      \"get\": {\n        \"tags\": [\n          \"Blocks\"\n        ],\n        \"summary\": \"Get smart contract libraries\",\n        \"description\": \"Get libraries codes.\",\n        \"operationId\": \"get_libraries_getLibraries_get\",\n        \"parameters\": [\n          {\n            \"description\": \"List of base64 encoded libraries hashes\",\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"array\",\n              \"items\": {\n                \"type\": \"string\"\n              },\n              \"title\": \"Libraries\",\n              \"description\": \"List of base64 encoded libraries hashes\"\n            },\n            \"name\": \"libraries\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"type\": \"object\",\n                  \"properties\": {\n                    \"ok\": {\n                      \"type\": \"boolean\"\n                    },\n                    \"result\": {\n                      \"type\": \"object\",\n                      \"properties\": {\n                        \"@type\": {\n                          \"type\": \"string\",\n                          \"example\": \"smc.libraryResult\"\n                        },\n                        \"result\": {\n                          \"type\": \"array\",\n                          \"items\": {\n                            \"type\": \"object\",\n                            \"properties\": {\n                              \"@type\": {\n                                \"type\": \"string\",\n                                \"example\": \"smc.libraryEntry\"\n                              },\n                              \"hash\": {\n                                \"type\": \"string\",\n                                \"example\": \"RZuqu83SGYHpN7D/5z+dUoN/hO08EXrRJg1TXsFigAo=\"\n                              },\n                              \"data\": {\n                                \"type\": \"string\",\n                                \"description\": \"Base64-encoded library data\"\n                              }\n                            }\n                          }\n                        },\n                        \"@extra\": {\n                          \"type\": \"string\",\n                          \"example\": \"1758735556.956807:1:0.731451399868406\"\n                        }\n                      }\n                    }\n                  },\n                  \"required\": [\"ok\", \"result\"]\n                },\n                \"examples\": {\n                  \"sample\": {\n                    \"summary\": \"Example response\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"@type\": \"smc.libraryResult\",\n                        \"result\": [\n                          {\n                            \"@type\": \"smc.libraryEntry\",\n                            \"hash\": \"RZuqu83SGYHpN7D/5z+dUoN/hO08EXrRJg1TXsFigAo=\",\n                            \"data\": \"te6ccgECDQEAA4kAART/APSkE/...\"\n                          }\n                        ],\n                        \"@extra\": \"1758735556.956807:1:0.731451399868406\"\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/getOutMsgQueueSizes\": {\n      \"get\": {\n        \"tags\": [\n          \"Blocks\"\n        ],\n        \"summary\": \"Get outgoing message queue sizes\",\n        \"description\": \"Get info with current sizes of messages queues by shards.\",\n        \"operationId\": \"get_out_msg_queue_sizes_getOutMsgQueueSizes_get\",\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/GetOutMsgQueueSizesResponse\"\n                },\n                \"examples\": {\n                  \"sample\": {\n                    \"summary\": \"Outgoing message queue sizes example\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"@type\": \"blocks.outMsgQueueSizes\",\n                        \"shards\": [\n                          {\n                            \"@type\": \"blocks.outMsgQueueSize\",\n                            \"id\": {\n                              \"@type\": \"ton.blockIdExt\",\n                              \"workchain\": -1,\n                              \"shard\": \"-9223372036854775808\",\n                              \"seqno\": 51149550,\n                              \"root_hash\": \"aa5DrbypWLx+3hICy5IOusAsMB8LA+JY41tjUtlYVhQ=\",\n                              \"file_hash\": \"Yd96kDamNL490591/O2unVWv9FUrkANnso8ZMwEHtqU=\"\n                            },\n                            \"size\": 0\n                          },\n                          {\n                            \"@type\": \"blocks.outMsgQueueSize\",\n                            \"id\": {\n                              \"@type\": \"ton.blockIdExt\",\n                              \"workchain\": 0,\n                              \"shard\": \"-9223372036854775808\",\n                              \"seqno\": 56263368,\n                              \"root_hash\": \"jdalpRwHiguMp1Vxij4gWAkdzeIN56M0mfrjb9tVvmY=\",\n                              \"file_hash\": \"/j8B/o8axBw0DZOlv1WGqvPh/KgJFeV8S4p3Ai2EDzQ=\"\n                            },\n                            \"size\": 0\n                          }\n                        ],\n                        \"ext_msg_queue_size_limit\": 8000,\n                        \"@extra\": \"1755815024.4620872:9:0.8277963175010491\"\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/getTokenData\": {\n      \"get\": {\n        \"tags\": [\n          \"Accounts\"\n        ],\n        \"summary\": \"Get NFT or Jetton metadata\",\n        \"description\": \"Get NFT or Jetton information.\",\n        \"operationId\": \"get_token_data_getTokenData_get\",\n        \"parameters\": [\n          {\n            \"description\": \"Address of NFT collection/item or Jetton master/wallet smart contract\",\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"Address\",\n              \"description\": \"Address of NFT collection/item or Jetton master/wallet smart contract\"\n            },\n            \"name\": \"address\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/GetTokenDataResponse\"\n                },\n                \"examples\": {\n                  \"sample\": {\n                    \"summary\": \"Example\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"@type\": \"nft.item\",\n                        \"init\": true,\n                        \"index\": 123,\n                        \"owner_address\": \"EQ...\",\n                        \"collection_address\": \"EQ...\",\n                        \"content\": {\n                          \"uri\": \"ipfs://...\"\n                        },\n                        \"metadata\": {\n                          \"name\": \"Example NFT\",\n                          \"image\": \"ipfs://...\"\n                        }\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/tryLocateTx\": {\n      \"get\": {\n        \"tags\": [\n          \"Transactions\"\n        ],\n        \"summary\": \"Locate transaction by incoming message\",\n        \"description\": \"Locate outcoming transaction of *destination* address by incoming message.\",\n        \"operationId\": \"get_try_locate_tx_tryLocateTx_get\",\n        \"parameters\": [\n          {\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"Source\"\n            },\n            \"name\": \"source\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"Destination\"\n            },\n            \"name\": \"destination\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Created Lt\"\n            },\n            \"name\": \"created_lt\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/TonResponse\"\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/tryLocateResultTx\": {\n      \"get\": {\n        \"tags\": [\n          \"Transactions\"\n        ],\n        \"summary\": \"Locate result transaction by incoming message\",\n        \"description\": \"Same as previous. Locate outcoming transaction of *destination* address by incoming message\",\n        \"operationId\": \"get_try_locate_result_tx_tryLocateResultTx_get\",\n        \"parameters\": [\n          {\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"Source\"\n            },\n            \"name\": \"source\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"Destination\"\n            },\n            \"name\": \"destination\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Created Lt\"\n            },\n            \"name\": \"created_lt\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/TonResponse\"\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/tryLocateSourceTx\": {\n      \"get\": {\n        \"tags\": [\n          \"Transactions\"\n        ],\n        \"summary\": \"Locate source transaction by outgoing message\",\n        \"description\": \"Locate incoming transaction of *source* address by outcoming message.\",\n        \"operationId\": \"get_try_locate_source_tx_tryLocateSourceTx_get\",\n        \"parameters\": [\n          {\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"Source\"\n            },\n            \"name\": \"source\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"Destination\"\n            },\n            \"name\": \"destination\",\n            \"in\": \"query\"\n          },\n          {\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"integer\",\n              \"title\": \"Created Lt\"\n            },\n            \"name\": \"created_lt\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/TonResponse\"\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/detectAddress\": {\n      \"get\": {\n        \"tags\": [\n          \"Accounts\"\n        ],\n        \"summary\": \"Detect all address formats\",\n        \"description\": \"Get all possible address forms.\",\n        \"operationId\": \"detect_address_detectAddress_get\",\n        \"parameters\": [\n          {\n            \"description\": \"Identifier of target TON account in any form.\",\n            \"required\": true,\n            \"schema\": {\n              \"type\": \"string\",\n              \"title\": \"Address\",\n              \"description\": \"Identifier of target TON account in any form.\"\n            },\n            \"name\": \"address\",\n            \"in\": \"query\"\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/DetectAddressResponse\"\n                },\n                \"examples\": {\n                  \"sample\": {\n                    \"summary\": \"Example\",\n                    \"value\": {\n                      \"ok\": true,\n                      \"result\": {\n                        \"raw_form\": \"0:83DF...31A8\",\n                        \"bounceable\": \"EQCD39VS5jcptHL8v...\",\n                        \"non_bounceable\": \"UQCD39VS5jcptHL8v...\"\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/sendBoc\": {\n      \"post\": {\n        \"tags\": [\n          \"Messages and transactions\"\n        ],\n        \"summary\": \"Send external message (BoC)\",\n        \"description\": \"Send serialized BoC file: fully packed and serialized external message to blockchain.\",\n        \"operationId\": \"send_boc_sendBoc_post\",\n        \"requestBody\": {\n          \"content\": {\n            \"application/json\": {\n              \"schema\": {\n                \"$ref\": \"#/components/schemas/Body_send_boc_sendBoc_post\"\n              }\n            }\n          },\n          \"required\": true\n        },\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/TonResponse\"\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/sendBocReturnHash\": {\n      \"post\": {\n        \"tags\": [\n          \"Messages and transactions\"\n        ],\n        \"summary\": \"Send external message and return hash\",\n        \"description\": \"Send serialized BoC file: fully packed and serialized external message to blockchain. The method returns message hash.\",\n        \"operationId\": \"send_boc_return_hash_sendBocReturnHash_post\",\n        \"requestBody\": {\n          \"content\": {\n            \"application/json\": {\n              \"schema\": {\n                \"$ref\": \"#/components/schemas/Body_send_boc_return_hash_sendBocReturnHash_post\"\n              }\n            }\n          },\n          \"required\": true\n        },\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/TonResponse\"\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/sendQuery\": {\n      \"post\": {\n        \"tags\": [\n          \"Messages and transactions\"\n        ],\n        \"summary\": \"Send unpacked external query\",\n        \"description\": \"Send query - unpacked external message. This method takes address, body and init-params (if any), packs it to external message and sends to network. All params should be BoC-serialized.\",\n        \"operationId\": \"send_query_sendQuery_post\",\n        \"requestBody\": {\n          \"content\": {\n            \"application/json\": {\n              \"schema\": {\n                \"$ref\": \"#/components/schemas/Body_send_query_sendQuery_post\"\n              }\n            }\n          },\n          \"required\": true\n        },\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/TonResponse\"\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/estimateFee\": {\n      \"post\": {\n        \"tags\": [\n          \"Messages and transactions\"\n        ],\n        \"summary\": \"Estimate transaction fees\",\n        \"description\": \"Estimate fees required for query processing. *body*, *init-code* and *init-data* accepted in serialized format (b64-encoded).\",\n        \"operationId\": \"estimate_fee_estimateFee_post\",\n        \"requestBody\": {\n          \"content\": {\n            \"application/json\": {\n              \"schema\": {\n                \"$ref\": \"#/components/schemas/Body_estimate_fee_estimateFee_post\"\n              }\n            }\n          },\n          \"required\": true\n        },\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/TonResponse\"\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/runGetMethod\": {\n      \"post\": {\n        \"tags\": [\n          \"Smart contracts\"\n        ],\n        \"summary\": \"Run get-method on contract\",\n        \"description\": \"Run get method on smart contract.\",\n        \"operationId\": \"run_get_method_runGetMethod_post\",\n        \"requestBody\": {\n          \"content\": {\n            \"application/json\": {\n              \"schema\": {\n                \"$ref\": \"#/components/schemas/Body_run_get_method_runGetMethod_post\"\n              }\n            }\n          },\n          \"required\": true\n        },\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/TonResponse\"\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    },\n    \"/jsonRPC\": {\n      \"post\": {\n        \"tags\": [\n          \"JSON-RPC\"\n        ],\n        \"summary\": \"JSON-RPC handler\",\n        \"description\": \"All methods in the API are available through JSON-RPC protocol ([spec](https://www.jsonrpc.org/specification)).\",\n        \"operationId\": \"jsonrpc_handler_jsonRPC_post\",\n        \"requestBody\": {\n          \"content\": {\n            \"application/json\": {\n              \"schema\": {\n                \"$ref\": \"#/components/schemas/TonRequestJsonRPC\"\n              }\n            }\n          },\n          \"required\": true\n        },\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Successful Response\",\n            \"content\": {\n              \"application/json\": {\n                \"schema\": {\n                  \"$ref\": \"#/components/schemas/DeprecatedTonResponseJsonRPC\"\n                }\n              }\n            }\n          },\n          \"422\": {\n            \"description\": \"Validation Error\"\n          },\n          \"504\": {\n            \"description\": \"Lite Server Timeout\"\n          }\n        },\n        \"security\": []\n      }\n    }\n  },\n  \"components\": {\n    \"schemas\": {\n      \"Body_estimate_fee_estimateFee_post\": {\n        \"properties\": {\n          \"address\": {\n            \"type\": \"string\",\n            \"title\": \"Address\",\n            \"description\": \"Address in any format\"\n          },\n          \"body\": {\n            \"type\": \"string\",\n            \"title\": \"Body\",\n            \"description\": \"b64-encoded cell with message body\"\n          },\n          \"init_code\": {\n            \"type\": \"string\",\n            \"title\": \"Init Code\",\n            \"description\": \"b64-encoded cell with init-code\",\n            \"default\": \"\"\n          },\n          \"init_data\": {\n            \"type\": \"string\",\n            \"title\": \"Init Data\",\n            \"description\": \"b64-encoded cell with init-data\",\n            \"default\": \"\"\n          },\n          \"ignore_chksig\": {\n            \"type\": \"boolean\",\n            \"title\": \"Ignore Chksig\",\n            \"description\": \"If true during test query processing assume that all chksig operations return True\",\n            \"default\": true\n          }\n        },\n        \"type\": \"object\",\n        \"required\": [\n          \"address\",\n          \"body\"\n        ],\n        \"title\": \"Body_estimate_fee_estimateFee_post\"\n      },\n      \"Body_run_get_method_runGetMethod_post\": {\n        \"properties\": {\n          \"address\": {\n            \"type\": \"string\",\n            \"title\": \"Address\",\n            \"description\": \"Contract address\"\n          },\n          \"method\": {\n            \"anyOf\": [\n              {\n                \"type\": \"string\"\n              },\n              {\n                \"type\": \"integer\"\n              }\n            ],\n            \"title\": \"Method\",\n            \"description\": \"Method name or method id\"\n          },\n          \"stack\": {\n            \"items\": {\n              \"items\": {},\n              \"type\": \"array\"\n            },\n            \"type\": \"array\",\n            \"title\": \"Stack\",\n            \"description\": \"Array of stack elements: `[['num',3], ['cell', cell_object], ['slice', slice_object]]`\"\n          },\n          \"seqno\": {\n            \"type\": \"integer\",\n            \"title\": \"Seqno\",\n            \"description\": \"Seqno of masterchain block at which moment the Get Method is to be executed\"\n          }\n        },\n        \"type\": \"object\",\n        \"required\": [\n          \"address\",\n          \"method\",\n          \"stack\"\n        ],\n        \"title\": \"Body_run_get_method_runGetMethod_post\"\n      },\n      \"Body_send_boc_return_hash_sendBocReturnHash_post\": {\n        \"properties\": {\n          \"boc\": {\n            \"type\": \"string\",\n            \"title\": \"Boc\",\n            \"description\": \"b64 encoded bag of cells\"\n          }\n        },\n        \"type\": \"object\",\n        \"required\": [\n          \"boc\"\n        ],\n        \"title\": \"Body_send_boc_return_hash_sendBocReturnHash_post\"\n      },\n      \"Body_send_boc_sendBoc_post\": {\n        \"properties\": {\n          \"boc\": {\n            \"type\": \"string\",\n            \"title\": \"Boc\",\n            \"description\": \"b64 encoded bag of cells\"\n          }\n        },\n        \"type\": \"object\",\n        \"required\": [\n          \"boc\"\n        ],\n        \"title\": \"Body_send_boc_sendBoc_post\"\n      },\n      \"Body_send_query_sendQuery_post\": {\n        \"properties\": {\n          \"address\": {\n            \"type\": \"string\",\n            \"title\": \"Address\",\n            \"description\": \"Address in any format\"\n          },\n          \"body\": {\n            \"type\": \"string\",\n            \"title\": \"Body\",\n            \"description\": \"b64-encoded BoC-serialized cell with message body\"\n          },\n          \"init_code\": {\n            \"type\": \"string\",\n            \"title\": \"Init Code\",\n            \"description\": \"b64-encoded BoC-serialized cell with init-code\",\n            \"default\": \"\"\n          },\n          \"init_data\": {\n            \"type\": \"string\",\n            \"title\": \"Init Data\",\n            \"description\": \"b64-encoded BoC-serialized cell with init-data\",\n            \"default\": \"\"\n          }\n        },\n        \"type\": \"object\",\n        \"required\": [\n          \"address\",\n          \"body\"\n        ],\n        \"title\": \"Body_send_query_sendQuery_post\"\n      },\n      \"DeprecatedTonResponseJsonRPC\": {\n        \"properties\": {\n          \"ok\": {\n            \"type\": \"boolean\",\n            \"title\": \"Ok\"\n          },\n          \"result\": {\n            \"title\": \"Result\"\n          },\n          \"error\": {\n            \"type\": \"string\",\n            \"title\": \"Error\"\n          },\n          \"code\": {\n            \"type\": \"integer\",\n            \"title\": \"Code\"\n          },\n          \"id\": {\n            \"type\": \"string\",\n            \"title\": \"Id\"\n          },\n          \"jsonrpc\": {\n            \"type\": \"string\",\n            \"title\": \"Jsonrpc\",\n            \"default\": \"2.0\"\n          }\n        },\n        \"type\": \"object\",\n        \"required\": [\n          \"ok\",\n          \"id\"\n        ],\n        \"title\": \"DeprecatedTonResponseJsonRPC\"\n      },\n      \"TonRequestJsonRPC\": {\n        \"properties\": {\n          \"method\": {\n            \"type\": \"string\",\n            \"title\": \"Method\"\n          },\n          \"params\": {\n            \"type\": \"object\",\n            \"title\": \"Params\",\n            \"default\": {}\n          },\n          \"id\": {\n            \"type\": \"string\",\n            \"title\": \"Id\"\n          },\n          \"jsonrpc\": {\n            \"type\": \"string\",\n            \"title\": \"Jsonrpc\"\n          }\n        },\n        \"type\": \"object\",\n        \"required\": [\n          \"method\"\n        ],\n        \"title\": \"TonRequestJsonRPC\"\n      },\n      \"TonResponse\": {\n        \"properties\": {\n          \"ok\": {\n            \"type\": \"boolean\",\n            \"title\": \"Ok\"\n          },\n          \"result\": {\n            \"anyOf\": [\n              {\n                \"type\": \"string\"\n              },\n              {\n                \"items\": {},\n                \"type\": \"array\"\n              },\n              {\n                \"type\": \"object\"\n              }\n            ],\n            \"title\": \"Result\"\n          },\n          \"error\": {\n            \"type\": \"string\",\n            \"title\": \"Error\"\n          },\n          \"code\": {\n            \"type\": \"integer\",\n            \"title\": \"Code\"\n          }\n        },\n        \"type\": \"object\",\n        \"required\": [\n          \"ok\"\n        ],\n        \"title\": \"TonResponse\"\n      },\n      \"InternalTransactionId\": {\n        \"type\": \"object\",\n        \"description\": \"Internal transaction identifier.\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"internal.transactionId\"\n          },\n          \"lt\": {\n            \"type\": \"string\",\n            \"description\": \"Logical time.\"\n          },\n          \"hash\": {\n            \"type\": \"string\",\n            \"description\": \"Base64 hash of the tx.\"\n          }\n        },\n        \"required\": [\n          \"lt\",\n          \"hash\"\n        ]\n      },\n      \"TonBlockIdExt\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"ton.blockIdExt\"\n          },\n          \"workchain\": {\n            \"type\": \"integer\"\n          },\n          \"shard\": {\n            \"type\": \"string\",\n            \"description\": \"64-bit signed integer as string\"\n          },\n          \"seqno\": {\n            \"type\": \"integer\"\n          },\n          \"root_hash\": {\n            \"type\": \"string\"\n          },\n          \"file_hash\": {\n            \"type\": \"string\"\n          }\n        },\n        \"required\": [\n          \"workchain\",\n          \"shard\",\n          \"seqno\",\n          \"root_hash\",\n          \"file_hash\"\n        ],\n        \"description\": \"Extended block identifier.\"\n      },\n      \"AccountAddress\": {\n        \"type\": \"object\",\n        \"description\": \"Account address object.\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"accountAddress\"\n          },\n          \"account_address\": {\n            \"type\": \"string\",\n            \"description\": \"Friendly address string.\"\n          }\n        },\n        \"required\": [\n          \"account_address\"\n        ]\n      },\n      \"GetAddressInformationResult\": {\n        \"type\": \"object\",\n        \"description\": \"Raw account state augmented with computed `state`. Fields come directly from tonlib.\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"raw.fullAccountState\"\n          },\n          \"address\": {\n            \"$ref\": \"#/components/schemas/AccountAddress\"\n          },\n          \"balance\": {\n            \"type\": \"string\",\n            \"description\": \"Balance in nanotons.\"\n          },\n          \"extra_currencies\": {\n            \"type\": \"array\",\n            \"items\": {\n              \"type\": \"object\"\n            }\n          },\n          \"code\": {\n            \"type\": \"string\",\n            \"description\": \"Base64-encoded code cell\"\n          },\n          \"data\": {\n            \"type\": \"string\",\n            \"description\": \"Base64-encoded data cell\"\n          },\n          \"last_transaction_id\": {\n            \"$ref\": \"#/components/schemas/InternalTransactionId\"\n          },\n          \"block_id\": {\n            \"$ref\": \"#/components/schemas/TonBlockIdExt\"\n          },\n          \"frozen_hash\": {\n            \"type\": \"string\"\n          },\n          \"sync_utime\": {\n            \"type\": \"integer\"\n          },\n          \"@extra\": {\n            \"type\": \"string\"\n          },\n          \"state\": {\n            \"type\": \"string\",\n            \"enum\": [\n              \"uninitialized\",\n              \"active\",\n              \"frozen\"\n            ],\n            \"description\": \"Computed from code/frozen_hash by the API server.\"\n          }\n        },\n        \"required\": [\n          \"balance\",\n          \"last_transaction_id\",\n          \"state\"\n        ]\n      },\n      \"GetAddressInformationResponse\": {\n        \"allOf\": [\n          {\n            \"$ref\": \"#/components/schemas/TonResponse\"\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"result\": {\n                \"$ref\": \"#/components/schemas/GetAddressInformationResult\"\n              }\n            }\n          }\n        ]\n      },\n      \"GetExtendedAddressInformationResult\": {\n        \"type\": \"object\",\n        \"description\": \"Generic account state decoded by tonlib; contract-specific `account_state` may contain typed fields (e.g., wallet.v3.accountState).\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"fullAccountState\"\n          },\n          \"address\": {\n            \"$ref\": \"#/components/schemas/AccountAddress\"\n          },\n          \"balance\": {\n            \"type\": \"string\"\n          },\n          \"extra_currencies\": {\n            \"type\": \"array\",\n            \"items\": {\n              \"type\": \"object\"\n            }\n          },\n          \"last_transaction_id\": {\n            \"$ref\": \"#/components/schemas/InternalTransactionId\"\n          },\n          \"block_id\": {\n            \"$ref\": \"#/components/schemas/TonBlockIdExt\"\n          },\n          \"sync_utime\": {\n            \"type\": \"integer\"\n          },\n          \"account_state\": {\n            \"type\": \"object\",\n            \"description\": \"Decoded state depending on contract type. For wallets, may include wallet_id and seqno.\",\n            \"properties\": {\n              \"@type\": {\n                \"type\": \"string\",\n                \"example\": \"wallet.v3.accountState\"\n              },\n              \"wallet_id\": {\n                \"type\": \"string\"\n              },\n              \"seqno\": {\n                \"type\": \"integer\"\n              }\n            },\n            \"additionalProperties\": true\n          },\n          \"revision\": {\n            \"type\": \"integer\"\n          },\n          \"@extra\": {\n            \"type\": \"string\"\n          }\n        },\n        \"required\": [\n          \"balance\",\n          \"last_transaction_id\"\n        ]\n      },\n      \"GetExtendedAddressInformationResponse\": {\n        \"allOf\": [\n          {\n            \"$ref\": \"#/components/schemas/TonResponse\"\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"result\": {\n                \"$ref\": \"#/components/schemas/GetExtendedAddressInformationResult\"\n              }\n            }\n          }\n        ]\n      },\n      \"GetWalletInformationResult\": {\n        \"type\": \"object\",\n        \"description\": \"Parsed wallet info built by the API: wallet flags + wallet-specific fields if recognized.\",\n        \"properties\": {\n          \"wallet\": {\n            \"type\": \"boolean\"\n          },\n          \"balance\": {\n            \"type\": \"string\"\n          },\n          \"extra_currencies\": {\n            \"type\": \"array\",\n            \"items\": {\n              \"type\": \"object\"\n            }\n          },\n          \"account_state\": {\n            \"type\": \"string\",\n            \"enum\": [\n              \"uninitialized\",\n              \"active\",\n              \"frozen\"\n            ]\n          },\n          \"wallet_type\": {\n            \"type\": \"string\",\n            \"nullable\": true\n          },\n          \"seqno\": {\n            \"type\": \"integer\",\n            \"nullable\": true\n          },\n          \"last_transaction_id\": {\n            \"$ref\": \"#/components/schemas/InternalTransactionId\"\n          },\n          \"wallet_id\": {\n            \"type\": \"string\"\n          },\n          \"public_key\": {\n            \"type\": \"string\"\n          }\n        },\n        \"required\": [\n          \"wallet\",\n          \"balance\",\n          \"extra_currencies\",\n          \"account_state\"\n        ]\n      },\n      \"GetWalletInformationResponse\": {\n        \"allOf\": [\n          {\n            \"$ref\": \"#/components/schemas/TonResponse\"\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"result\": {\n                \"$ref\": \"#/components/schemas/GetWalletInformationResult\"\n              }\n            }\n          }\n        ]\n      },\n      \"DetectAddressResult\": {\n        \"type\": \"object\",\n        \"description\": \"All possible address forms derived from the input. Exact keys depend on pytonlib utils.\",\n        \"properties\": {\n          \"raw_form\": {\n            \"type\": \"string\",\n            \"description\": \"Hex raw address (workchain:hash)\"\n          },\n          \"bounceable\": {\n            \"type\": \"string\",\n            \"description\": \"User-friendly bounceable\"\n          },\n          \"non_bounceable\": {\n            \"type\": \"string\",\n            \"description\": \"User-friendly non-bounceable\"\n          }\n        },\n        \"additionalProperties\": true\n      },\n      \"DetectAddressResponse\": {\n        \"allOf\": [\n          {\n            \"$ref\": \"#/components/schemas/TonResponse\"\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"result\": {\n                \"$ref\": \"#/components/schemas/DetectAddressResult\"\n              }\n            }\n          }\n        ]\n      },\n      \"StringResultResponse\": {\n        \"allOf\": [\n          {\n            \"$ref\": \"#/components/schemas/TonResponse\"\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"result\": {\n                \"type\": \"string\"\n              }\n            }\n          }\n        ]\n      },\n      \"AddressStateResponse\": {\n        \"allOf\": [\n          {\n            \"$ref\": \"#/components/schemas/TonResponse\"\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"result\": {\n                \"type\": \"string\",\n                \"enum\": [\n                  \"uninitialized\",\n                  \"active\",\n                  \"frozen\"\n                ]\n              }\n            }\n          }\n        ]\n      },\n      \"GetTokenDataResult\": {\n        \"type\": \"object\",\n        \"description\": \"NFT or Jetton information as returned by tonlib; varies by contract type.\",\n        \"additionalProperties\": true\n      },\n      \"GetTokenDataResponse\": {\n        \"allOf\": [\n          {\n            \"$ref\": \"#/components/schemas/TonResponse\"\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"result\": {\n                \"$ref\": \"#/components/schemas/GetTokenDataResult\"\n              }\n            }\n          }\n        ]\n      },\n      \"BlocksMasterchainInfo\": {\n        \"type\": \"object\",\n        \"description\": \"Information about the latest masterchain block.\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"blocks.masterchainInfo\"\n          },\n          \"last\": {\n            \"$ref\": \"#/components/schemas/TonBlockIdExt\"\n          },\n          \"state_root_hash\": {\n            \"type\": \"string\"\n          },\n          \"init\": {\n            \"$ref\": \"#/components/schemas/TonBlockIdExt\"\n          },\n          \"@extra\": {\n            \"type\": \"string\"\n          }\n        },\n        \"required\": [\n          \"last\",\n          \"state_root_hash\",\n          \"init\"\n        ]\n      },\n      \"GetMasterchainInfoResponse\": {\n        \"allOf\": [\n          {\n            \"$ref\": \"#/components/schemas/TonResponse\"\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"result\": {\n                \"$ref\": \"#/components/schemas/BlocksMasterchainInfo\",\n                \"description\": \"Information about the latest masterchain block.\"\n              }\n            }\n          }\n        ]\n      },\n      \"BlockSignature\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"blocks.signature\"\n          },\n          \"node_id_short\": {\n            \"type\": \"string\",\n            \"description\": \"Short node ID\"\n          },\n          \"signature\": {\n            \"type\": \"string\",\n            \"description\": \"Base64 signature\"\n          }\n        },\n        \"required\": [\n          \"node_id_short\",\n          \"signature\"\n        ],\n        \"description\": \"Validator signature.\"\n      },\n      \"BlocksBlockSignatures\": {\n        \"type\": \"object\",\n        \"description\": \"Validator signatures for a given block.\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"blocks.blockSignatures\"\n          },\n          \"id\": {\n            \"$ref\": \"#/components/schemas/TonBlockIdExt\"\n          },\n          \"signatures\": {\n            \"type\": \"array\",\n            \"items\": {\n              \"$ref\": \"#/components/schemas/BlockSignature\"\n            },\n            \"description\": \"List of validator signatures for the block.\"\n          },\n          \"@extra\": {\n            \"type\": \"string\"\n          }\n        },\n        \"required\": [\n          \"id\",\n          \"signatures\"\n        ]\n      },\n      \"GetMasterchainBlockSignaturesResponse\": {\n        \"allOf\": [\n          {\n            \"$ref\": \"#/components/schemas/TonResponse\"\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"result\": {\n                \"$ref\": \"#/components/schemas/BlocksBlockSignatures\",\n                \"description\": \"Validator signatures for a given block.\"\n              }\n            }\n          }\n        ]\n      },\n      \"GetConsensusBlockResponse\": {\n        \"allOf\": [\n          {\n            \"$ref\": \"#/components/schemas/TonResponse\"\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"result\": {\n                \"$ref\": \"#/components/schemas/BlocksMasterchainInfo\",\n                \"description\": \"Consensus block information from the masterchain.\"\n              }\n            }\n          }\n        ]\n      },\n      \"BlocksShardBlockProof\": {\n        \"type\": \"object\",\n        \"description\": \"Proof of inclusion of a shard block in the masterchain.\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"blocks.shardBlockProof\"\n          },\n          \"from\": {\n            \"$ref\": \"#/components/schemas/TonBlockIdExt\"\n          },\n          \"mc_id\": {\n            \"$ref\": \"#/components/schemas/TonBlockIdExt\"\n          },\n          \"links\": {\n            \"type\": \"array\",\n            \"items\": {\n              \"type\": \"object\"\n            }\n          },\n          \"mc_proof\": {\n            \"type\": \"array\",\n            \"items\": {\n              \"type\": \"object\"\n            }\n          },\n          \"@extra\": {\n            \"type\": \"string\"\n          }\n        },\n        \"required\": [\n          \"from\",\n          \"mc_id\"\n        ]\n      },\n      \"GetShardBlockProofResponse\": {\n        \"allOf\": [\n          {\n            \"$ref\": \"#/components/schemas/TonResponse\"\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"result\": {\n                \"$ref\": \"#/components/schemas/BlocksShardBlockProof\",\n                \"description\": \"Proof of inclusion of a shard block in the masterchain.\"\n              }\n            }\n          }\n        ]\n      },\n      \"LookupBlockResponse\": {\n        \"allOf\": [\n          {\n            \"$ref\": \"#/components/schemas/TonResponse\"\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"result\": {\n                \"$ref\": \"#/components/schemas/TonBlockIdExt\",\n                \"description\": \"Block identifier for the looked-up block.\"\n              }\n            }\n          }\n        ]\n      },\n      \"BlocksShards\": {\n        \"type\": \"object\",\n        \"description\": \"List of shard blocks at a given masterchain seqno.\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"blocks.shards\"\n          },\n          \"shards\": {\n            \"type\": \"array\",\n            \"items\": {\n              \"$ref\": \"#/components/schemas/TonBlockIdExt\"\n            },\n            \"description\": \"Shard block IDs at the given masterchain seqno.\"\n          },\n          \"@extra\": {\n            \"type\": \"string\"\n          }\n        },\n        \"required\": [\n          \"shards\"\n        ]\n      },\n      \"ShardsResponse\": {\n        \"allOf\": [\n          {\n            \"$ref\": \"#/components/schemas/TonResponse\"\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"result\": {\n                \"$ref\": \"#/components/schemas/BlocksShards\",\n                \"description\": \"List of shard blocks at a given masterchain seqno.\"\n              }\n            }\n          }\n        ]\n      },\n      \"ShortTxId\": {\n        \"type\": \"object\",\n        \"description\": \"Short transaction identifier.\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"blocks.shortTxId\"\n          },\n          \"mode\": {\n            \"type\": \"integer\",\n            \"description\": \"Transaction mode flags.\"\n          },\n          \"account\": {\n            \"type\": \"string\",\n            \"description\": \"Account address of the transaction.\"\n          },\n          \"lt\": {\n            \"type\": \"string\",\n            \"description\": \"Logical time of the transaction.\"\n          },\n          \"hash\": {\n            \"type\": \"string\",\n            \"description\": \"Base64 hash of the transaction.\"\n          }\n        },\n        \"required\": [\n          \"account\",\n          \"lt\",\n          \"hash\"\n        ]\n      },\n      \"BlocksTransactions\": {\n        \"type\": \"object\",\n        \"description\": \"Transactions included in a block.\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"blocks.transactions\"\n          },\n          \"id\": {\n            \"description\": \"Identifier of the block containing the transactions.\",\n            \"$ref\": \"#/components/schemas/TonBlockIdExt\"\n          },\n          \"req_count\": {\n            \"type\": \"integer\",\n            \"description\": \"Number of requested transactions.\"\n          },\n          \"incomplete\": {\n            \"type\": \"boolean\",\n            \"description\": \"Indicates if the transaction list is incomplete.\"\n          },\n          \"transactions\": {\n            \"type\": \"array\",\n            \"description\": \"List of short transaction identifiers.\",\n            \"items\": {\n              \"$ref\": \"#/components/schemas/ShortTxId\"\n            }\n          },\n          \"@extra\": {\n            \"type\": \"string\",\n            \"description\": \"Extra metadata for the response.\"\n          }\n        },\n        \"required\": [\n          \"id\",\n          \"transactions\"\n        ]\n      },\n      \"GetBlockTransactionsResponse\": {\n        \"allOf\": [\n          {\n            \"$ref\": \"#/components/schemas/TonResponse\"\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"result\": {\n                \"description\": \"Transactions included in the specified block.\",\n                \"$ref\": \"#/components/schemas/BlocksTransactions\"\n              }\n            }\n          }\n        ]\n      },\n      \"ExtraCurrency\": {\n        \"type\": \"object\",\n        \"description\": \"Extra currency amount.\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"extraCurrency\"\n          },\n          \"id\": {\n            \"type\": \"integer\",\n            \"description\": \"Currency ID.\"\n          },\n          \"amount\": {\n            \"type\": \"string\",\n            \"description\": \"Amount in smallest units.\"\n          }\n        },\n        \"required\": [\n          \"id\",\n          \"amount\"\n        ]\n      },\n      \"MsgDataRaw\": {\n        \"type\": \"object\",\n        \"description\": \"Raw message data.\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"msg.dataRaw\"\n          },\n          \"body\": {\n            \"type\": \"string\",\n            \"description\": \"Base64-encoded message body.\"\n          },\n          \"init_state\": {\n            \"type\": \"string\",\n            \"description\": \"Base64-encoded init state.\",\n            \"nullable\": true\n          }\n        },\n        \"required\": [\n          \"body\"\n        ]\n      },\n      \"RawMessage\": {\n        \"type\": \"object\",\n        \"description\": \"Raw message.\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"raw.message\"\n          },\n          \"hash\": {\n            \"type\": \"string\",\n            \"description\": \"Base64 hash of the message.\"\n          },\n          \"source\": {\n            \"$ref\": \"#/components/schemas/AccountAddress\",\n            \"description\": \"Source address.\"\n          },\n          \"destination\": {\n            \"$ref\": \"#/components/schemas/AccountAddress\",\n            \"description\": \"Destination address.\"\n          },\n          \"value\": {\n            \"type\": \"string\",\n            \"description\": \"Value in nanotons.\"\n          },\n          \"extra_currencies\": {\n            \"type\": \"array\",\n            \"items\": {\n              \"$ref\": \"#/components/schemas/ExtraCurrency\"\n            },\n            \"description\": \"Optional extra currencies.\"\n          },\n          \"fwd_fee\": {\n            \"type\": \"string\",\n            \"description\": \"Forwarding fee in nanotons.\"\n          },\n          \"ihr_fee\": {\n            \"type\": \"string\",\n            \"description\": \"Instant Hypercube Routing fee in nanotons.\"\n          },\n          \"created_lt\": {\n            \"type\": \"string\",\n            \"description\": \"Message creation logical time.\"\n          },\n          \"body_hash\": {\n            \"type\": \"string\",\n            \"description\": \"Base64 hash of message body.\"\n          },\n          \"msg_data\": {\n            \"$ref\": \"#/components/schemas/MsgDataRaw\",\n            \"description\": \"Message data.\"\n          }\n        },\n        \"required\": [\n          \"hash\",\n          \"destination\",\n          \"value\",\n          \"created_lt\",\n          \"msg_data\"\n        ]\n      },\n      \"RawTransaction\": {\n        \"type\": \"object\",\n        \"description\": \"Raw transaction object.\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"raw.transaction\"\n          },\n          \"address\": {\n            \"$ref\": \"#/components/schemas/AccountAddress\",\n            \"description\": \"Account address.\"\n          },\n          \"utime\": {\n            \"type\": \"integer\",\n            \"description\": \"UNIX timestamp of the transaction.\"\n          },\n          \"data\": {\n            \"type\": \"string\",\n            \"description\": \"Base64-encoded raw transaction data.\"\n          },\n          \"transaction_id\": {\n            \"$ref\": \"#/components/schemas/InternalTransactionId\",\n            \"description\": \"Internal transaction id.\"\n          },\n          \"fee\": {\n            \"type\": \"string\",\n            \"description\": \"Total fee in nanotons.\"\n          },\n          \"storage_fee\": {\n            \"type\": \"string\",\n            \"description\": \"Storage fee in nanotons.\"\n          },\n          \"other_fee\": {\n            \"type\": \"string\",\n            \"description\": \"Other fees in nanotons.\"\n          },\n          \"in_msg\": {\n            \"$ref\": \"#/components/schemas/RawMessage\",\n            \"description\": \"Incoming message.\",\n            \"nullable\": true\n          },\n          \"out_msgs\": {\n            \"type\": \"array\",\n            \"items\": {\n              \"$ref\": \"#/components/schemas/RawMessage\"\n            },\n            \"description\": \"Outgoing messages.\"\n          },\n          \"account\": {\n            \"type\": \"string\",\n            \"description\": \"Workchain:hex account id.\"\n          }\n        },\n        \"required\": [\n          \"transaction_id\",\n          \"fee\",\n          \"other_fee\",\n          \"out_msgs\",\n          \"account\"\n        ]\n      },\n      \"BlocksTransactionsExt\": {\n        \"type\": \"object\",\n        \"description\": \"Extended transactions included in a block.\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"blocks.transactionsExt\"\n          },\n          \"id\": {\n            \"$ref\": \"#/components/schemas/TonBlockIdExt\",\n            \"description\": \"Identifier of the block.\"\n          },\n          \"req_count\": {\n            \"type\": \"integer\",\n            \"description\": \"Number of requested transactions.\"\n          },\n          \"incomplete\": {\n            \"type\": \"boolean\",\n            \"description\": \"Whether the list is truncated.\"\n          },\n          \"transactions\": {\n            \"type\": \"array\",\n            \"description\": \"Verbose transaction list with raw messages.\",\n            \"items\": {\n              \"$ref\": \"#/components/schemas/RawTransaction\"\n            }\n          },\n          \"@extra\": {\n            \"type\": \"string\",\n            \"description\": \"Extra metadata for the response.\"\n          }\n        },\n        \"required\": [\n          \"id\",\n          \"transactions\"\n        ]\n      },\n      \"GetBlockTransactionsExtResponse\": {\n        \"allOf\": [\n          {\n            \"$ref\": \"#/components/schemas/TonResponse\"\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"result\": {\n                \"description\": \"Extended transactions included in the specified block.\",\n                \"$ref\": \"#/components/schemas/BlocksTransactionsExt\"\n              }\n            }\n          }\n        ]\n      },\n      \"BlocksHeader\": {\n        \"type\": \"object\",\n        \"description\": \"Block header information.\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"blocks.header\"\n          },\n          \"id\": {\n            \"$ref\": \"#/components/schemas/TonBlockIdExt\",\n            \"description\": \"Extended identifier of the block.\"\n          },\n          \"global_id\": {\n            \"type\": \"integer\",\n            \"description\": \"Global network identifier.\"\n          },\n          \"version\": {\n            \"type\": \"integer\",\n            \"description\": \"Block format version.\"\n          },\n          \"after_merge\": {\n            \"type\": \"boolean\",\n            \"description\": \"True if block was created after a merge.\"\n          },\n          \"after_split\": {\n            \"type\": \"boolean\",\n            \"description\": \"True if block was created after a split.\"\n          },\n          \"before_split\": {\n            \"type\": \"boolean\",\n            \"description\": \"True if block was created before a split.\"\n          },\n          \"want_merge\": {\n            \"type\": \"boolean\",\n            \"description\": \"Indicates if validators wanted a merge.\"\n          },\n          \"want_split\": {\n            \"type\": \"boolean\",\n            \"description\": \"Indicates if validators wanted a split.\"\n          },\n          \"validator_list_hash_short\": {\n            \"type\": \"integer\",\n            \"description\": \"Short hash of validator list.\"\n          },\n          \"catchain_seqno\": {\n            \"type\": \"integer\",\n            \"description\": \"Catchain sequence number.\"\n          },\n          \"min_ref_mc_seqno\": {\n            \"type\": \"integer\",\n            \"description\": \"Minimum referenced masterchain seqno.\"\n          },\n          \"is_key_block\": {\n            \"type\": \"boolean\",\n            \"description\": \"True if this block is a key block.\"\n          },\n          \"prev_key_block_seqno\": {\n            \"type\": \"integer\",\n            \"description\": \"Previous key block sequence number.\"\n          },\n          \"start_lt\": {\n            \"type\": \"string\",\n            \"description\": \"Starting logical time.\"\n          },\n          \"end_lt\": {\n            \"type\": \"string\",\n            \"description\": \"Ending logical time.\"\n          },\n          \"gen_utime\": {\n            \"type\": \"integer\",\n            \"description\": \"Block generation UNIX timestamp.\"\n          },\n          \"prev_blocks\": {\n            \"type\": \"array\",\n            \"description\": \"List of previous block identifiers.\",\n            \"items\": {\n              \"$ref\": \"#/components/schemas/TonBlockIdExt\"\n            }\n          },\n          \"@extra\": {\n            \"type\": \"string\",\n            \"description\": \"Extra metadata for the response.\"\n          }\n        },\n        \"required\": [\n          \"id\",\n          \"global_id\",\n          \"version\",\n          \"gen_utime\"\n        ]\n      },\n      \"GetBlockHeaderResponse\": {\n        \"allOf\": [\n          {\n            \"$ref\": \"#/components/schemas/TonResponse\"\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"result\": {\n                \"description\": \"Header information of the specified block.\",\n                \"$ref\": \"#/components/schemas/BlocksHeader\"\n              }\n            }\n          }\n        ]\n      },\n      \"BlocksOutMsgQueueSize\": {\n        \"type\": \"object\",\n        \"description\": \"Size of the outgoing message queue for a shard.\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"blocks.outMsgQueueSize\"\n          },\n          \"id\": {\n            \"$ref\": \"#/components/schemas/TonBlockIdExt\",\n            \"description\": \"Block identifier for the shard.\"\n          },\n          \"size\": {\n            \"type\": \"integer\",\n            \"description\": \"Queue size for the shard.\"\n          }\n        },\n        \"required\": [\n          \"id\",\n          \"size\"\n        ]\n      },\n      \"BlocksOutMsgQueueSizes\": {\n        \"type\": \"object\",\n        \"description\": \"Outgoing message queue sizes for shards.\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"blocks.outMsgQueueSizes\"\n          },\n          \"shards\": {\n            \"type\": \"array\",\n            \"description\": \"List of outgoing message queue sizes per shard.\",\n            \"items\": {\n              \"$ref\": \"#/components/schemas/BlocksOutMsgQueueSize\"\n            }\n          },\n          \"ext_msg_queue_size_limit\": {\n            \"type\": \"integer\",\n            \"description\": \"Limit for the external message queue size.\"\n          },\n          \"@extra\": {\n            \"type\": \"string\",\n            \"description\": \"Extra metadata for the response.\"\n          }\n        },\n        \"required\": [\n          \"shards\",\n          \"ext_msg_queue_size_limit\"\n        ]\n      },\n      \"GetOutMsgQueueSizesResponse\": {\n        \"allOf\": [\n          {\n            \"$ref\": \"#/components/schemas/TonResponse\"\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"result\": {\n                \"description\": \"Outgoing message queue sizes for all shards.\",\n                \"$ref\": \"#/components/schemas/BlocksOutMsgQueueSizes\"\n              }\n            }\n          }\n        ]\n      },\n      \"TvmCell\": {\n        \"type\": \"object\",\n        \"description\": \"Raw TVM cell serialized as base64 bytes.\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"tvm.cell\"\n          },\n          \"bytes\": {\n            \"type\": \"string\",\n            \"description\": \"Base64-encoded BoC bytes.\"\n          }\n        },\n        \"required\": [\n          \"bytes\"\n        ]\n      },\n      \"ConfigInfo\": {\n        \"type\": \"object\",\n        \"description\": \"Configuration parameter payload.\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"configInfo\"\n          },\n          \"config\": {\n            \"$ref\": \"#/components/schemas/TvmCell\",\n            \"description\": \"TVM cell with the parameter contents.\"\n          },\n          \"@extra\": {\n            \"type\": \"string\",\n            \"description\": \"Extra metadata for the response.\"\n          }\n        },\n        \"required\": [\n          \"config\"\n        ]\n      },\n      \"GetConfigParamResponse\": {\n        \"allOf\": [\n          {\n            \"$ref\": \"#/components/schemas/TonResponse\"\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"result\": {\n                \"description\": \"Configuration parameter for the requested id (at optional seqno).\",\n                \"$ref\": \"#/components/schemas/ConfigInfo\"\n              }\n            }\n          }\n        ]\n      },\n      \"ConfigAll\": {\n        \"type\": \"object\",\n        \"description\": \"All configuration parameters at a specific masterchain state.\",\n        \"properties\": {\n          \"@type\": {\n            \"type\": \"string\",\n            \"example\": \"configInfo\"\n          },\n          \"config\": {\n            \"$ref\": \"#/components/schemas/TvmCell\",\n            \"description\": \"TVM cell containing all configuration parameters.\"\n          },\n          \"@extra\": {\n            \"type\": \"string\",\n            \"description\": \"Extra metadata for the response.\"\n          }\n        },\n        \"required\": [\n          \"config\"\n        ]\n      },\n      \"GetConfigAllResponse\": {\n        \"allOf\": [\n          {\n            \"$ref\": \"#/components/schemas/TonResponse\"\n          },\n          {\n            \"type\": \"object\",\n            \"properties\": {\n              \"result\": {\n                \"description\": \"All configuration parameters for the requested masterchain seqno.\",\n                \"$ref\": \"#/components/schemas/ConfigAll\"\n              }\n            }\n          }\n        ]\n      }\n    }\n  },\n  \"tags\": [\n    {\n      \"name\": \"Accounts\",\n      \"description\": \"Information about accounts.\"\n    },\n    {\n      \"name\": \"Blocks\",\n      \"description\": \"Information about blocks.\"\n    },\n    {\n      \"name\": \"Transactions\",\n      \"description\": \"Fetching and locating transactions.\"\n    },\n    {\n      \"name\": \"Config\",\n      \"description\": \"Get blockchain config\"\n    },\n    {\n      \"name\": \"Smart contracts\",\n      \"description\": \"Run get method of smart contract.\"\n    },\n    {\n      \"name\": \"Messages and Transactions\",\n      \"description\": \"Send data to blockchain.\"\n    },\n    {\n      \"name\": \"JSON-RPC\",\n      \"description\": \"JSON-RPC endpoint.\"\n    }\n  ]\n}\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/accounts/address-book.mdx",
    "content": "---\nopenapi: get /api/v3/addressBook\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/accounts/get-account-states.mdx",
    "content": "---\nopenapi: get /api/v3/accountStates\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/accounts/get-wallet-states.mdx",
    "content": "---\nopenapi: get /api/v3/walletStates\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/accounts/metadata.mdx",
    "content": "---\nopenapi: get /api/v3/metadata\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/actions-and-traces/get-actions.mdx",
    "content": "---\nopenapi: get /api/v3/actions\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/actions-and-traces/get-pending-actions.mdx",
    "content": "---\nopenapi: get /api/v3/pendingActions\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/actions-and-traces/get-pending-traces.mdx",
    "content": "---\nopenapi: get /api/v3/pendingTraces\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/actions-and-traces/get-traces.mdx",
    "content": "---\nopenapi: get /api/v3/traces\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/apiv2/estimate-fee.mdx",
    "content": "---\nopenapi: post /api/v3/estimateFee\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/apiv2/get-address-information.mdx",
    "content": "---\nopenapi: get /api/v3/addressInformation\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/apiv2/get-wallet-information.mdx",
    "content": "---\nopenapi: get /api/v3/walletInformation\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/apiv2/run-get-method.mdx",
    "content": "---\nopenapi: post /api/v3/runGetMethod\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/apiv2/send-message.mdx",
    "content": "---\nopenapi: post /api/v3/message\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/blockchain-data/get-adjacent-transactions.mdx",
    "content": "---\nopenapi: get /api/v3/adjacentTransactions\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/blockchain-data/get-blocks.mdx",
    "content": "---\nopenapi: get /api/v3/blocks\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/blockchain-data/get-masterchain-block-shard-state-1.mdx",
    "content": "---\nopenapi: get /api/v3/masterchainBlockShards\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/blockchain-data/get-masterchain-block-shard-state.mdx",
    "content": "---\nopenapi: get /api/v3/masterchainBlockShardState\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/blockchain-data/get-masterchain-info.mdx",
    "content": "---\nopenapi: get /api/v3/masterchainInfo\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/blockchain-data/get-messages.mdx",
    "content": "---\nopenapi: get /api/v3/messages\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/blockchain-data/get-pending-transactions.mdx",
    "content": "---\nopenapi: get /api/v3/pendingTransactions\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/blockchain-data/get-transactions-by-masterchain-block.mdx",
    "content": "---\nopenapi: get /api/v3/transactionsByMasterchainBlock\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/blockchain-data/get-transactions-by-message.mdx",
    "content": "---\nopenapi: get /api/v3/transactionsByMessage\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/blockchain-data/get-transactions.mdx",
    "content": "---\nopenapi: get /api/v3/transactions\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/dns/get-dns-records.mdx",
    "content": "---\nopenapi: get /api/v3/dns/records\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/jettons/get-jetton-burns.mdx",
    "content": "---\nopenapi: get /api/v3/jetton/burns\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/jettons/get-jetton-masters.mdx",
    "content": "---\nopenapi: get /api/v3/jetton/masters\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/jettons/get-jetton-transfers.mdx",
    "content": "---\nopenapi: get /api/v3/jetton/transfers\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/jettons/get-jetton-wallets.mdx",
    "content": "---\nopenapi: get /api/v3/jetton/wallets\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/multisig/get-multisig-orders.mdx",
    "content": "---\nopenapi: get /api/v3/multisig/orders\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/multisig/get-multisig-wallets.mdx",
    "content": "---\nopenapi: get /api/v3/multisig/wallets\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/nfts/get-nft-collections.mdx",
    "content": "---\nopenapi: get /api/v3/nft/collections\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/nfts/get-nft-items.mdx",
    "content": "---\nopenapi: get /api/v3/nft/items\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/nfts/get-nft-transfers.mdx",
    "content": "---\nopenapi: get /api/v3/nft/transfers\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/overview.mdx",
    "content": "---\ntitle: Overview\n---\n\nThe TON Center API v3 provides developer access to the TON blockchain through an indexed data layer.\nIt allows applications to read blockchain data, run analytical queries, retrieve historical information,\nand decode Jetton, NFT, and action data.\n\nAPI v3 serves as the indexed access layer.\n\nIt reads raw data from a node’s RocksDB storage, parses and decodes it, and stores it in PostgreSQL.\n\n## Base URLs\n\n| API        | Mainnet                        | Testnet                                |\n| ---------- | ------------------------------ | -------------------------------------- |\n| **API v3** | `https://toncenter.com/api/v3` | `https://testnet.toncenter.com/api/v3` |\n\n## Typical use cases\n\n- Query historical transactions and traces\n- Retrieve decoded Jetton and NFT data\n- Run analytical or filtered searches across multiple accounts\n- Power explorers or reporting tools\n\n## Endpoints\n\n{/* BEGIN_AUTO_GENERATED: API_V3_ENDPOINTS */}\n| Category | Method | Description |\n| -------- | ------ | ----------- |\n| **Accounts** | [`GET /accountStates`](/ecosystem/api/toncenter/v3/accounts/get-account-states) | Get Account States |\n| **Accounts** | [`GET /addressBook`](/ecosystem/api/toncenter/v3/accounts/address-book) | Address Book |\n| **Accounts** | [`GET /metadata`](/ecosystem/api/toncenter/v3/accounts/metadata) | Metadata |\n| **Accounts** | [`GET /walletStates`](/ecosystem/api/toncenter/v3/accounts/get-wallet-states) | Get Wallet States |\n| **Actions and traces** | [`GET /actions`](/ecosystem/api/toncenter/v3/actions-and-traces/get-actions) | Get Actions |\n| **Actions and traces** | [`GET /pendingActions`](/ecosystem/api/toncenter/v3/actions-and-traces/get-pending-actions) | Get Pending Actions |\n| **Actions and traces** | [`GET /pendingTraces`](/ecosystem/api/toncenter/v3/actions-and-traces/get-pending-traces) | Get Pending Traces |\n| **Actions and traces** | [`GET /traces`](/ecosystem/api/toncenter/v3/actions-and-traces/get-traces) | Get Traces |\n| **Blockchain Data** | [`GET /adjacentTransactions`](/ecosystem/api/toncenter/v3/blockchain-data/get-adjacent-transactions) | Get Adjacent Transactions |\n| **Blockchain Data** | [`GET /blocks`](/ecosystem/api/toncenter/v3/blockchain-data/get-blocks) | Get blocks |\n| **Blockchain Data** | [`GET /masterchainBlockShardState`](/ecosystem/api/toncenter/v3/blockchain-data/get-masterchain-block-shard-state) | Get masterchain block shard state |\n| **Blockchain Data** | [`GET /masterchainBlockShards`](/ecosystem/api/toncenter/v3/blockchain-data/get-masterchain-block-shard-state) | Get masterchain block shard state |\n| **Blockchain Data** | [`GET /masterchainInfo`](/ecosystem/api/toncenter/v3/blockchain-data/get-masterchain-info) | Get Masterchain Info |\n| **Blockchain Data** | [`GET /messages`](/ecosystem/api/toncenter/v3/blockchain-data/get-messages) | Get messages |\n| **Blockchain Data** | [`GET /pendingTransactions`](/ecosystem/api/toncenter/v3/blockchain-data/get-pending-transactions) | Get pending transactions |\n| **Blockchain Data** | [`GET /transactions`](/ecosystem/api/toncenter/v3/blockchain-data/get-transactions) | Get transactions |\n| **Blockchain Data** | [`GET /transactionsByMasterchainBlock`](/ecosystem/api/toncenter/v3/blockchain-data/get-transactions-by-masterchain-block) | Get transactions by Masterchain block |\n| **Blockchain Data** | [`GET /transactionsByMessage`](/ecosystem/api/toncenter/v3/blockchain-data/get-transactions-by-message) | Get transactions by message |\n| **Jettons** | [`GET /jetton/burns`](/ecosystem/api/toncenter/v3/jettons/get-jetton-burns) | Get Jetton Burns |\n| **Jettons** | [`GET /jetton/masters`](/ecosystem/api/toncenter/v3/jettons/get-jetton-masters) | Get Jetton Masters |\n| **Jettons** | [`GET /jetton/transfers`](/ecosystem/api/toncenter/v3/jettons/get-jetton-transfers) | Get Jetton Transfers |\n| **Jettons** | [`GET /jetton/wallets`](/ecosystem/api/toncenter/v3/jettons/get-jetton-wallets) | Get Jetton Wallets |\n| **NFTs** | [`GET /nft/collections`](/ecosystem/api/toncenter/v3/nfts/get-nft-collections) | Get NFT collections |\n| **NFTs** | [`GET /nft/items`](/ecosystem/api/toncenter/v3/nfts/get-nft-items) | Get NFT items |\n| **NFTs** | [`GET /nft/transfers`](/ecosystem/api/toncenter/v3/nfts/get-nft-transfers) | Get NFT Transfers |\n| **Dns** | [`GET /dns/records`](/ecosystem/api/toncenter/v3/dns/get-dns-records) | Get DNS Records |\n| **Multisig** | [`GET /multisig/orders`](/ecosystem/api/toncenter/v3/multisig/get-multisig-orders) | Get Multisig Orders |\n| **Multisig** | [`GET /multisig/wallets`](/ecosystem/api/toncenter/v3/multisig/get-multisig-wallets) | Get Multisig Wallets |\n| **Vesting** | [`GET /vesting`](/ecosystem/api/toncenter/v3/vesting/get-vesting-contracts) | Get Vesting Contracts |\n| **Stats** | [`GET /topAccountsByBalance`](/ecosystem/api/toncenter/v3/stats/get-top-accounts-by-balance) | Get Top Accounts By Balance |\n| **Utils** | [`GET /decode`](/ecosystem/api/toncenter/v3/utils/decode-opcodes-and-bodies) | Decode Opcodes and Bodies |\n| **Legacy (v2)** | [`GET /addressInformation`](/ecosystem/api/toncenter/v3/apiv2/get-address-information) | Get Address Information |\n| **Legacy (v2)** | [`POST /estimateFee`](/ecosystem/api/toncenter/v3/apiv2/estimate-fee) | Estimate Fee |\n| **Legacy (v2)** | [`POST /message`](/ecosystem/api/toncenter/v3/apiv2/send-message) | Send Message |\n| **Legacy (v2)** | [`POST /runGetMethod`](/ecosystem/api/toncenter/v3/apiv2/run-get-method) | Run Get-Method |\n| **Legacy (v2)** | [`GET /walletInformation`](/ecosystem/api/toncenter/v3/apiv2/get-wallet-information) | Get Wallet Information |\n{/* END_AUTO_GENERATED: API_V3_ENDPOINTS */}\n\n## How to access the API\n\nDevelopers can access TON Center API v3 either through hosted infrastructure or by running a self-hosted instance.\n\n### Managed service\n\nHosted access uses TON Center’s indexed infrastructure.\nRequests without an API key are rate-limited to a default value.\n\nTo increase limits, generate an [API key](/ecosystem/api/toncenter/get-api-key) and select a [plan](/ecosystem/api/toncenter/rate-limit).\n\n### Self-hosted service\n\nRun a self-hosted API v3 setup for full control over performance and data retention.\nSee the [ton-indexer](https://github.com/toncenter/ton-indexer) repository for setup instructions.\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/stats/get-top-accounts-by-balance.mdx",
    "content": "---\nopenapi: get /api/v3/topAccountsByBalance\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/utils/decode-opcodes-and-bodies-1.mdx",
    "content": "---\nopenapi: post /api/v3/decode\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/utils/decode-opcodes-and-bodies.mdx",
    "content": "---\nopenapi: get /api/v3/decode\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3/vesting/get-vesting-contracts.mdx",
    "content": "---\nopenapi: get /api/v3/vesting\n---\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3-authentication.mdx",
    "content": "---\ntitle: \"API authentication\"\nsidebarTitle: \"Authentication\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\n\n## Overview\n\nThe API v3 accepts an API key for all methods. Requests without an API key are limited to one request per second. To make more than one request per second, please include an API key.\n\nThe key can be sent either in an HTTP header or as a query parameter. Only one of these is needed per request.\n\nTo obtain an API key, see the [TON Center API key guide](/ecosystem/api/toncenter/get-api-key).\n\n| Method  | Location | Name        |\n| ------- | -------- | ----------- |\n| API key | Header   | `X-API-Key` |\n| API key | Query    | `api_key`   |\n\n<Aside\n  type=\"caution\"\n>\n  Never expose the API key in client-side code or public repositories. Store keys in a secrets manager or environment variables, rotate them periodically, and generate a new key immediately if one is compromised.\n</Aside>\n\n## Public hosts\n\n| Network | Host                                   |\n| ------- | -------------------------------------- |\n| Testnet | `https://testnet.toncenter.com/api/v3` |\n| Mainnet | `https://toncenter.com/api/v3`         |\n\n## REST endpoint authentication\n\n### Header authentication\n\nSend the API key in the `X-API-Key` header:\n\n```bash\ncurl \"https://testnet.toncenter.com/api/v3/masterchainInfo\" \\\n  -H \"X-API-Key: <API_KEY>\"\n```\n\n### Query parameter authentication\n\nPass the key as a query parameter named `api_key`:\n\n```bash\ncurl \"https://testnet.toncenter.com/api/v3/masterchainInfo?api_key=<API_KEY>\"\n```\n\nBoth forms are equivalent.\n\n## API key error codes\n\n| Status | Error                    | Meaning                                                                                                           |\n| -----: | ------------------------ | ----------------------------------------------------------------------------------------------------------------- |\n|  `401` | `API key does not exist` | The provided key is invalid. Check for typos or generate a new key.                                               |\n|  `403` | `Network not allowed`    | The key was issued for a different network (e.g., testnet key on mainnet). Use a key matching the target network. |\n|  `429` | `Ratelimit exceeded`     | Too many requests. Back off and retry, or use an API key for higher limits.                                       |\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3-errors.mdx",
    "content": "---\ntitle: \"API error codes\"\nsidebarTitle: \"Error codes\"\n---\n\nAll TON Center API v3 methods use a standard set of HTTP status codes to indicate the result of a request.\n\n| Status code                 | Description                                                                        |\n| --------------------------- | ---------------------------------------------------------------------------------- |\n| `401 Unauthorized`          | A required parameter was not included in the request.                              |\n| `404 Not Found`             | The requested resource does not exist in storage.                                  |\n| `409 Conflict`              | The resource was found but does not match the expected type for this method.       |\n| `422 Unprocessable Content` | The request parameters failed validation (e.g., conflicting or malformed filters). |\n| `500 Internal Server Error` | An internal error occurred. Retry or contact support if it persists.               |\n\nFor method-specific error messages and troubleshooting details, refer to the documentation for the relevant endpoint.\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3-pagination.mdx",
    "content": "---\ntitle: \"Pagination\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nThe v3 API uses offset-based pagination. Each paginated endpoint accepts `limit` and `offset` parameters. `limit` controls how many results to return per request, and `offset` skips a number of rows from the beginning of the result set. To retrieve the next page, increment `offset` by the value of `limit`.\n\nThe following endpoints support pagination:\n\n| Endpoint                                                                                                              | Default limit | Max limit | Sortable |\n| --------------------------------------------------------------------------------------------------------------------- | :-----------: | :-------: | :------: |\n| [`transactions`](/ecosystem/api/toncenter/v3/blockchain-data/get-transactions)                                        |       10      |    1000   |    Yes   |\n| [`actions`](/ecosystem/api/toncenter/v3/actions-and-traces/get-actions)                                               |       10      |    1000   |    Yes   |\n| [`blocks`](/ecosystem/api/toncenter/v3/blockchain-data/get-blocks)                                                    |       10      |    1000   |    Yes   |\n| [`messages`](/ecosystem/api/toncenter/v3/blockchain-data/get-messages)                                                |       10      |    1000   |    Yes   |\n| [`traces`](/ecosystem/api/toncenter/v3/actions-and-traces/get-traces)                                                 |       10      |    1000   |    Yes   |\n| [`jetton/burns`](/ecosystem/api/toncenter/v3/jettons/get-jetton-burns)                                                |       10      |    1000   |    Yes   |\n| [`jetton/transfers`](/ecosystem/api/toncenter/v3/jettons/get-jetton-transfers)                                        |       10      |    1000   |    Yes   |\n| [`jetton/wallets`](/ecosystem/api/toncenter/v3/jettons/get-jetton-wallets)                                            |       10      |    1000   |    Yes   |\n| [`nft/items`](/ecosystem/api/toncenter/v3/nfts/get-nft-items)                                                         |       10      |    1000   |    Yes   |\n| [`nft/transfers`](/ecosystem/api/toncenter/v3/nfts/get-nft-transfers)                                                 |       10      |    1000   |    Yes   |\n| [`multisig/orders`](/ecosystem/api/toncenter/v3/multisig/get-multisig-orders)                                         |       10      |    1000   |    Yes   |\n| [`multisig/wallets`](/ecosystem/api/toncenter/v3/multisig/get-multisig-wallets)                                       |       10      |    1000   |    Yes   |\n| [`transactionsByMasterchainBlock`](/ecosystem/api/toncenter/v3/blockchain-data/get-transactions-by-masterchain-block) |       10      |    1000   |    Yes   |\n| [`jetton/masters`](/ecosystem/api/toncenter/v3/jettons/get-jetton-masters)                                            |       10      |    1000   |    No    |\n| [`nft/collections`](/ecosystem/api/toncenter/v3/nfts/get-nft-collections)                                             |       10      |    1000   |    No    |\n| [`dns/records`](/ecosystem/api/toncenter/v3/dns/get-dns-records)                                                      |      100      |    1000   |    No    |\n| [`masterchainBlockShards`](/ecosystem/api/toncenter/v3/blockchain-data/get-masterchain-block-shard-state-1)           |       10      |    1000   |    No    |\n| [`topAccountsByBalance`](/ecosystem/api/toncenter/v3/stats/get-top-accounts-by-balance)                               |       10      |    1024   |    No    |\n| [`transactionsByMessage`](/ecosystem/api/toncenter/v3/blockchain-data/get-transactions-by-message)                    |       10      |    1000   |    No    |\n| [`vesting`](/ecosystem/api/toncenter/v3/vesting/get-vesting-contracts)                                                |       10      |    1000   |    No    |\n\nAll other v3 endpoints return single objects or fixed results and do not support pagination.\n\n## Parameters\n\nThese parameters are shared across all paginated endpoints.\n\n| Parameter | Type    | Description                                                                                               |\n| --------- | ------- | --------------------------------------------------------------------------------------------------------- |\n| `limit`   | integer | Maximum number of rows to return. Defaults vary by endpoint; see table above.                             |\n| `offset`  | integer | Number of rows to skip from the beginning of the result set. Default is `0`.                              |\n| `sort`    | string  | Sort order: `desc` (default, newest first) or `asc` (oldest first). Available only on sortable endpoints. |\n\n## Pagination example\n\nThis example uses the `transactions` endpoint, but the same `limit` and `offset` pattern applies to all paginated endpoints.\n\n<Steps>\n  <Step\n    title=\"Fetch the first page\"\n  >\n    Send a request with `account` and `limit`. `offset` defaults to `0` for the first page.\n\n    ```bash\n    curl \"https://toncenter.com/api/v3/transactions?account=EQDtFpEwcFAEcRe5mLVh2N6C0x-_hJEM7W61_JLnSF74p4q2&limit=3\"\n    ```\n\n    Response (abbreviated):\n\n    ```json\n    {\n      \"transactions\": [\n        {\n          \"account\": \"0:ED1691307050047117B998B561D8DE82D31FBF84910CED6EB5FC92E7485EF8A7\",\n          \"hash\": \"KkpVTX9RwiZcug8KQuOFUF8+eNoxuHVuIFpGQqufCWU=\",\n          \"lt\": \"67064337000004\",\n          \"now\": 1771410670\n        },\n        {\n          \"account\": \"0:ED1691307050047117B998B561D8DE82D31FBF84910CED6EB5FC92E7485EF8A7\",\n          \"hash\": \"b5fhFby+j8gg936W+XEsAEhboQW0zPcOHOHgyqXkTwI=\",\n          \"lt\": \"67011337000003\",\n          \"now\": 1771286044\n        },\n        {\n          \"account\": \"0:ED1691307050047117B998B561D8DE82D31FBF84910CED6EB5FC92E7485EF8A7\",\n          \"hash\": \"lT/wWTiJIdEF8A2Rox9CRdQRzlUgnIDGeUfEHQ8jGZQ=\",\n          \"lt\": \"66986300000006\",\n          \"now\": 1771226782\n        }\n      ],\n      \"address_book\": { ... }\n    }\n    ```\n\n    Three transactions returned, sorted by logical time in descending order (newest first).\n  </Step>\n\n  <Step\n    title=\"Fetch the next page\"\n  >\n    Set `offset=3` to skip the first 3 results and get the next batch.\n\n    ```bash\n    curl \"https://toncenter.com/api/v3/transactions?account=EQDtFpEwcFAEcRe5mLVh2N6C0x-_hJEM7W61_JLnSF74p4q2&limit=3&offset=3\"\n    ```\n\n    Response (abbreviated):\n\n    ```json\n    {\n      \"transactions\": [\n        {\n          \"account\": \"0:ED1691307050047117B998B561D8DE82D31FBF84910CED6EB5FC92E7485EF8A7\",\n          \"hash\": \"07QaeBRRA62+RJPgetgSraYLH5i9G5QhC2dUvKAsAiI=\",\n          \"lt\": \"66927779000007\",\n          \"now\": 1771088713\n        },\n        {\n          \"account\": \"0:ED1691307050047117B998B561D8DE82D31FBF84910CED6EB5FC92E7485EF8A7\",\n          \"hash\": \"8d7sSor1NqbGNdX1JEGl1d4rX3lb7CeC3DZjhe7V7z4=\",\n          \"lt\": \"66927779000003\",\n          \"now\": 1771088713\n        },\n        {\n          \"account\": \"0:ED1691307050047117B998B561D8DE82D31FBF84910CED6EB5FC92E7485EF8A7\",\n          \"hash\": \"szM1I5/MU1uJGgeScS7uxNF6V/FsLkokCpul88ZEau8=\",\n          \"lt\": \"66926353000007\",\n          \"now\": 1771085323\n        }\n      ],\n      \"address_book\": { ... }\n    }\n    ```\n\n    No overlap with the previous page. Offset pagination does not produce duplicates.\n  </Step>\n\n  <Step\n    title=\"Repeat until the last page\"\n  >\n    Continue incrementing `offset` by the `limit` value on each request (`offset=6`, `offset=9`, ...). When the response returns fewer transactions than the `limit`, all results have been retrieved.\n  </Step>\n</Steps>\n\n<Accordion\n  title=\"Full pagination script\"\n>\n  ```javascript\n  const address = \"EQDtFpEwcFAEcRe5mLVh2N6C0x-_hJEM7W61_JLnSF74p4q2\";\n\n  async function main() {\n    let allTransactions = [];\n    let offset = 0;\n    const limit = 3;\n    let page = 0;\n\n    while (true) {\n      page++;\n      const params = new URLSearchParams({\n        account: address,\n        limit: String(limit),\n        offset: String(offset),\n      });\n\n      const res = await fetch(\n        `https://toncenter.com/api/v3/transactions?${params}`\n      );\n      const data = await res.json();\n      const transactions = data.transactions || [];\n\n      console.log(`\\n--- Page ${page} (offset=${offset}) ---`);\n\n      for (const tx of transactions) {\n        console.log(`  lt: ${tx.lt}  hash: ${tx.hash}`);\n      }\n\n      allTransactions.push(...transactions);\n\n      if (transactions.length < limit) break;\n\n      offset += limit;\n    }\n\n    console.log(`\\nTotal transactions: ${allTransactions.length}`);\n  }\n\n  main();\n  ```\n\n  Output:\n\n  ```bash\n  --- Page 1 (offset=0) ---\n    lt: 67064337000004  hash: KkpVTX9RwiZcug8KQuOFUF8+eNoxuHVuIFpGQqufCWU=\n    lt: 67011337000003  hash: b5fhFby+j8gg936W+XEsAEhboQW0zPcOHOHgyqXkTwI=\n    lt: 66986300000006  hash: lT/wWTiJIdEF8A2Rox9CRdQRzlUgnIDGeUfEHQ8jGZQ=\n\n  --- Page 2 (offset=3) ---\n    lt: 66927779000007  hash: 07QaeBRRA62+RJPgetgSraYLH5i9G5QhC2dUvKAsAiI=\n    lt: 66927779000003  hash: 8d7sSor1NqbGNdX1JEGl1d4rX3lb7CeC3DZjhe7V7z4=\n    lt: 66926353000007  hash: szM1I5/MU1uJGgeScS7uxNF6V/FsLkokCpul88ZEau8=\n\n  --- Page 3 (offset=6) ---\n\n  Total transactions: 6\n  ```\n</Accordion>\n\n## Sorting options\n\nSortable endpoints accept a `sort` parameter with two values:\n\n- `desc` (default): newest results first, sorted by logical time (or UTC timestamp for `blocks`).\n- `asc`: oldest results first.\n\n```bash\ncurl \"https://toncenter.com/api/v3/transactions?account=EQDtFpEwcFAEcRe5mLVh2N6C0x-_hJEM7W61_JLnSF74p4q2&limit=3&sort=asc\"\n```\n\nResponse (abbreviated):\n\n```json\n{\n  \"transactions\": [\n    {\n      \"hash\": \"3ziyP0yvGklMTNWWXDplmlBcPH0P7MJtusoVthNu8e0=\",\n      \"lt\": \"39547833000003\",\n      \"now\": 1690204554\n    },\n    {\n      \"hash\": \"lYXDtLL53JkKa35vP05gbwTyd6Lq4335TwlZeUebxZ8=\",\n      \"lt\": \"39547876000003\",\n      \"now\": 1690204686\n    },\n    {\n      \"hash\": \"DSz0P/wmE0EkdfaxFl2R36Eie+Lw4paLa1sAHHUliJA=\",\n      \"lt\": \"39548648000003\",\n      \"now\": 1690207175\n    }\n  ],\n  \"address_book\": { ... }\n}\n```\n\nWith `sort=asc`, the earliest transactions are returned first, starting from 2023-07 for this account.\n\n<Aside\n  type=\"caution\"\n  title=\"Sorting with jetton/wallets\"\n>\n  The `jetton/wallets` endpoint sorts results by balance instead of logical time. When balances change between requests, using `limit` and `offset` can skip or repeat wallets because the sort order changes between pages.\n</Aside>\n"
  },
  {
    "path": "ecosystem/api/toncenter/v3.yaml",
    "content": "openapi: 3.0.0\ninfo:\n  title: TON Index (Go)\n  description: TON Index collects data from a full node to PostgreSQL database and provides convenient API to an indexed blockchain.\n  version: 1.2.4-rc\n  contact: {}\nservers:\n- url: https://toncenter.com\n- url: https://testnet.toncenter.com\npaths:\n  /api/v3/accountStates:\n    get:\n      security: []\n      description: Query account states\n      tags:\n      - Accounts\n      summary: Get Account States\n      operationId: api_v3_get_account_states\n      parameters:\n      - name: address\n        in: query\n        description: List of addresses in any form. Maximum 1000 addresses allowed.\n        required: true\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: include_boc\n        in: query\n        description: 'Include code and data BOCs. Default: true'\n        schema:\n          type: boolean\n          default: true\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/AccountStatesResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/actions:\n    get:\n      security: []\n      description: Get actions by specified filter.\n      tags:\n      - Actions and traces\n      summary: Get Actions\n      operationId: api_v3_get_actions\n      parameters:\n      - name: account\n        in: query\n        description: List of account addresses to get actions. Can be sent in hex, base64 or base64url form.\n        schema:\n          type: string\n      - name: tx_hash\n        in: query\n        description: Find actions by transaction hash.\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: msg_hash\n        in: query\n        description: Find actions by message hash.\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: action_id\n        in: query\n        description: Find actions by the action_id.\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: trace_id\n        in: query\n        description: Find actions by the trace_id.\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: mc_seqno\n        in: query\n        description: Query actions of traces which was completed in masterchain block with given seqno\n        schema:\n          type: integer\n          format: int32\n      - name: start_utime\n        in: query\n        description: Query actions for traces with `trace_end_utime >= start_utime`.\n        schema:\n          type: integer\n          format: int32\n          minimum: 0\n      - name: end_utime\n        in: query\n        description: Query actions for traces with `trace_end_utime <= end_utime`.\n        schema:\n          type: integer\n          format: int32\n          minimum: 0\n      - name: start_lt\n        in: query\n        description: Query actions for traces with `trace_end_lt >= start_lt`.\n        schema:\n          type: integer\n          format: int64\n          minimum: 0\n      - name: end_lt\n        in: query\n        description: Query actions for traces with `trace_end_lt <= end_lt`.\n        schema:\n          type: integer\n          format: int64\n          minimum: 0\n      - name: action_type\n        in: query\n        description: Include action types.\n        explode: true\n        schema:\n          type: array\n          items:\n            enum:\n            - call_contract\n            - contract_deploy\n            - ton_transfer\n            - auction_bid\n            - change_dns\n            - dex_deposit_liquidity\n            - dex_withdraw_liquidity\n            - delete_dns\n            - renew_dns\n            - election_deposit\n            - election_recover\n            - jetton_burn\n            - jetton_swap\n            - jetton_transfer\n            - jetton_mint\n            - nft_mint\n            - tick_tock\n            - stake_deposit\n            - stake_withdrawal\n            - stake_withdrawal_request\n            - subscribe\n            - unsubscribe\n            type: string\n      - name: exclude_action_type\n        in: query\n        description: Exclude action types.\n        explode: true\n        schema:\n          type: array\n          items:\n            enum:\n            - call_contract\n            - contract_deploy\n            - ton_transfer\n            - auction_bid\n            - change_dns\n            - dex_deposit_liquidity\n            - dex_withdraw_liquidity\n            - delete_dns\n            - renew_dns\n            - election_deposit\n            - election_recover\n            - jetton_burn\n            - jetton_swap\n            - jetton_transfer\n            - jetton_mint\n            - nft_mint\n            - tick_tock\n            - stake_deposit\n            - stake_withdrawal\n            - stake_withdrawal_request\n            - subscribe\n            - unsubscribe\n            type: string\n      - name: supported_action_types\n        in: query\n        description: Supported action types\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: include_accounts\n        in: query\n        description: Include accounts array for each action in response.\n        schema:\n          type: boolean\n          default: false\n      - name: include_transactions\n        in: query\n        description: Include `transactions_full` array with detailed transaction data for each action in response.\n        schema:\n          type: boolean\n          default: false\n      - name: limit\n        in: query\n        description: Limit number of queried rows. Use with *offset* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 10\n          minimum: 1\n          maximum: 1000\n      - name: offset\n        in: query\n        description: Skip first N rows. Use with *limit* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 0\n          minimum: 0\n      - name: sort\n        in: query\n        description: Sort actions by lt.\n        schema:\n          type: string\n          default: desc\n          enum:\n          - asc\n          - desc\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ActionsResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/addressBook:\n    get:\n      security: []\n      description: Query address book\n      tags:\n      - Accounts\n      summary: Address Book\n      operationId: api_v3_get_address_book\n      parameters:\n      - name: address\n        in: query\n        description: 'List of addresses in any form to get address book. Max: 1024.'\n        required: true\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/AddressBook'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/addressInformation:\n    get:\n      security: []\n      description: Get smart contract information.\n      tags:\n      - Api/v2\n      summary: Get Address Information\n      operationId: api_v3_get_v2_addressInformation\n      parameters:\n      - name: address\n        in: query\n        description: Account address in any form.\n        required: true\n        schema:\n          type: string\n      - name: use_v2\n        in: query\n        description: Use method from api/v2. Not recommended\n        schema:\n          type: boolean\n          default: true\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/V2AddressInformation'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/adjacentTransactions:\n    get:\n      security: []\n      description: Get parent and/or children for specified transaction.\n      tags:\n      - Blockchain Data\n      summary: Get Adjacent Transactions\n      operationId: api_v3_get_adjacent_transactions\n      parameters:\n      - name: hash\n        in: query\n        description: Transaction hash.\n        schema:\n          type: string\n      - name: direction\n        in: query\n        description: Direction of message.\n        schema:\n          type: string\n          enum:\n          - in\n          - out\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/TransactionsResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/blocks:\n    get:\n      security: []\n      description: Returns blocks by specified filters.\n      tags:\n      - Blockchain Data\n      summary: Get blocks\n      operationId: api_v3_get_blocks\n      parameters:\n      - name: workchain\n        in: query\n        description: Block workchain.\n        schema:\n          type: integer\n          format: int32\n      - name: shard\n        in: query\n        description: 'Block shard id. Must be sent with *workchain*. Example: `8000000000000000`.'\n        schema:\n          type: string\n      - name: seqno\n        in: query\n        description: Block block seqno. Must be sent with *workchain* and *shard*.\n        schema:\n          type: integer\n          format: int32\n      - name: root_hash\n        in: query\n        description: Block root hash.\n        schema:\n          type: string\n      - name: file_hash\n        in: query\n        description: Block file hash.\n        schema:\n          type: string\n      - name: mc_seqno\n        in: query\n        description: Masterchain block seqno\n        schema:\n          type: integer\n          format: int32\n      - name: start_utime\n        in: query\n        description: Query blocks with generation UTC timestamp **after** given timestamp.\n        schema:\n          type: integer\n          format: int32\n          minimum: 0\n      - name: end_utime\n        in: query\n        description: Query blocks with generation UTC timestamp **before** given timestamp.\n        schema:\n          type: integer\n          format: int32\n          minimum: 0\n      - name: start_lt\n        in: query\n        description: Query blocks with `lt >= start_lt`.\n        schema:\n          type: integer\n          format: int64\n          minimum: 0\n      - name: end_lt\n        in: query\n        description: Query blocks with `lt <= end_lt`.\n        schema:\n          type: integer\n          format: int64\n          minimum: 0\n      - name: limit\n        in: query\n        description: Limit number of queried rows. Use with *offset* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 10\n          minimum: 1\n          maximum: 1000\n      - name: offset\n        in: query\n        description: Skip first N rows. Use with *limit* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 0\n          minimum: 0\n      - name: sort\n        in: query\n        description: Sort results by UTC timestamp.\n        schema:\n          type: string\n          default: desc\n          enum:\n          - asc\n          - desc\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/BlocksResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/decode:\n    get:\n      security: []\n      description: Decode opcodes and message bodies. Opcodes can be in hex (with or without 0x prefix) or decimal format.\n        Bodies should be in base64 or hex format.\n      tags:\n      - Utils\n      summary: Decode Opcodes and Bodies\n      operationId: api_v3_get_decode\n      parameters:\n      - name: opcodes\n        in: query\n        description: List of opcodes to decode (hex or decimal)\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: bodies\n        in: query\n        description: List of message bodies to decode (base64 or hex)\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/DecodeResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n    post:\n      security: []\n      description: Decode opcodes and message bodies. Opcodes can be in hex (with or without 0x prefix) or decimal format.\n        Bodies should be in base64 or hex format. Use POST method for long parameters that may be truncated in GET requests.\n      tags:\n      - Utils\n      summary: Decode Opcodes and Bodies\n      operationId: api_v3_post_decode\n      requestBody:\n        required: true\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/DecodeRequest'\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/DecodeResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/dns/records:\n    get:\n      security: []\n      description: Query DNS records by specified filters. Currently .ton and .t.me DNS are supported.\n      tags:\n      - Dns\n      summary: Get DNS Records\n      operationId: api_v3_get_dns_records\n      parameters:\n      - name: wallet\n        in: query\n        description: Wallet address in any form. DNS records that contain this address in wallet category will be returned.\n        schema:\n          type: string\n      - name: domain\n        in: query\n        description: Domain name to search for. DNS records with this exact domain name will be returned.\n        schema:\n          type: string\n      - name: limit\n        in: query\n        description: Limit number of queried rows. Use with *offset* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 100\n          minimum: 1\n          maximum: 1000\n      - name: offset\n        in: query\n        description: Skip first N rows. Use with *limit* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 0\n          minimum: 0\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/DNSRecordsResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/estimateFee:\n    post:\n      security: []\n      description: Estimate fees required for query processing. Fields body, init-code and init-data accepted in serialized\n        format (b64-encoded).\n      tags:\n      - Api/v2\n      summary: Estimate Fee\n      operationId: api_v3_post_v2_estimate_fee\n      requestBody:\n        required: true\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/V2EstimateFeeRequest'\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/V2EstimateFeeResult'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/jetton/burns:\n    get:\n      security: []\n      description: Get Jetton burns by specified filters\n      tags:\n      - Jettons\n      summary: Get Jetton Burns\n      operationId: api_v3_get_jetton_burns\n      parameters:\n      - name: address\n        in: query\n        description: Address of jetton wallet owner in any form. Max 1000\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: jetton_wallet\n        in: query\n        description: 'Jetton wallet address in any form. Max: 1000.'\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: jetton_master\n        in: query\n        description: Jetton master address in any form.\n        schema:\n          type: string\n      - name: start_utime\n        in: query\n        description: Query transactions with generation UTC timestamp **after** given timestamp.\n        schema:\n          type: integer\n          format: int32\n          minimum: 0\n      - name: end_utime\n        in: query\n        description: Query transactions with generation UTC timestamp **before** given timestamp.\n        schema:\n          type: integer\n          format: int32\n          minimum: 0\n      - name: start_lt\n        in: query\n        description: Query transactions with `lt >= start_lt`.\n        schema:\n          type: integer\n          format: int64\n          minimum: 0\n      - name: end_lt\n        in: query\n        description: Query transactions with `lt <= end_lt`.\n        schema:\n          type: integer\n          format: int64\n          minimum: 0\n      - name: limit\n        in: query\n        description: Limit number of queried rows. Use with *offset* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 10\n          minimum: 1\n          maximum: 1000\n      - name: offset\n        in: query\n        description: Skip first N rows. Use with *limit* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 0\n          minimum: 0\n      - name: sort\n        in: query\n        description: Sort transactions by lt.\n        schema:\n          type: string\n          default: desc\n          enum:\n          - asc\n          - desc\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/JettonBurnsResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/jetton/masters:\n    get:\n      security: []\n      description: Get Jetton masters by specified filters\n      tags:\n      - Jettons\n      summary: Get Jetton Masters\n      operationId: api_v3_get_jetton_masters\n      parameters:\n      - name: address\n        in: query\n        description: 'Jetton Master address in any form. Max: 1024.'\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: admin_address\n        in: query\n        description: 'Address of Jetton Master''s admin in any form. Max: 1024.'\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: limit\n        in: query\n        description: Limit number of queried rows. Use with *offset* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 10\n          minimum: 1\n          maximum: 1000\n      - name: offset\n        in: query\n        description: Skip first N rows. Use with *limit* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 0\n          minimum: 0\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/JettonMastersResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/jetton/transfers:\n    get:\n      security: []\n      description: Get Jetton transfers by specified filters\n      tags:\n      - Jettons\n      summary: Get Jetton Transfers\n      operationId: api_v3_get_jetton_transfers\n      parameters:\n      - name: owner_address\n        in: query\n        description: Address of jetton wallet owner in any form. Max 1000\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: jetton_wallet\n        in: query\n        description: 'Jetton wallet address in any form. Max: 1000.'\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: jetton_master\n        in: query\n        description: Jetton master address in any form.\n        schema:\n          type: string\n      - name: direction\n        in: query\n        description: Direction of transfer. *Note:* applied only with owner_address.\n        schema:\n          type: string\n          enum:\n          - in\n          - out\n      - name: start_utime\n        in: query\n        description: Query transactions with generation UTC timestamp **after** given timestamp.\n        schema:\n          type: integer\n          format: int32\n          minimum: 0\n      - name: end_utime\n        in: query\n        description: Query transactions with generation UTC timestamp **before** given timestamp.\n        schema:\n          type: integer\n          format: int32\n          minimum: 0\n      - name: start_lt\n        in: query\n        description: Query transactions with `lt >= start_lt`.\n        schema:\n          type: integer\n          format: int64\n          minimum: 0\n      - name: end_lt\n        in: query\n        description: Query transactions with `lt <= end_lt`.\n        schema:\n          type: integer\n          format: int64\n          minimum: 0\n      - name: limit\n        in: query\n        description: Limit number of queried rows. Use with *offset* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 10\n          minimum: 1\n          maximum: 1000\n      - name: offset\n        in: query\n        description: Skip first N rows. Use with *limit* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 0\n          minimum: 0\n      - name: sort\n        in: query\n        description: Sort transactions by lt.\n        schema:\n          type: string\n          default: desc\n          enum:\n          - asc\n          - desc\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/JettonTransfersResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/jetton/wallets:\n    get:\n      security: []\n      description: Get Jetton wallets by specified filters\n      tags:\n      - Jettons\n      summary: Get Jetton Wallets\n      operationId: api_v3_get_jetton_wallets\n      parameters:\n      - name: address\n        in: query\n        description: 'Jetton wallet address in any form. Max: 1000.'\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: owner_address\n        in: query\n        description: 'Address of Jetton wallet''s owner in any form. Max: 1000.'\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: jetton_address\n        in: query\n        description: Jetton Master in any form.\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: exclude_zero_balance\n        in: query\n        description: Exclude jetton wallets with 0 balance.\n        schema:\n          type: boolean\n      - name: limit\n        in: query\n        description: Limit number of queried rows. Use with *offset* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 10\n          minimum: 1\n          maximum: 1000\n      - name: offset\n        in: query\n        description: Skip first N rows. Use with *limit* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 0\n          minimum: 0\n      - name: sort\n        in: query\n        description: Sort jetton wallets by balance. **Warning:** results may be inconsistent during the read with limit and\n          offset.\n        schema:\n          type: string\n          enum:\n          - asc\n          - desc\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/JettonWalletsResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/masterchainBlockShardState:\n    get:\n      security: []\n      description: Get masterchain block shard state. Same as /api/v2/shards.\n      tags:\n      - Blockchain Data\n      summary: Get masterchain block shard state\n      operationId: api_v3_get_masterchainBlockShardState\n      parameters:\n      - name: seqno\n        in: query\n        description: Masterchain block seqno.\n        required: true\n        schema:\n          type: integer\n          format: int32\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/TransactionsResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/masterchainBlockShards:\n    get:\n      security: []\n      description: Returns all worchain blocks, that appeared after previous masterchain block.\n      tags:\n      - Blockchain Data\n      summary: Get masterchain block shard state\n      operationId: api_v3_get_masterchainBlockShards\n      parameters:\n      - name: seqno\n        in: query\n        description: Masterchain block seqno.\n        required: true\n        schema:\n          type: integer\n          format: int32\n      - name: limit\n        in: query\n        description: Limit number of queried rows. Use with *offset* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 10\n          minimum: 1\n          maximum: 1000\n      - name: offset\n        in: query\n        description: Skip first N rows. Use with *limit* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 0\n          minimum: 0\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/TransactionsResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/masterchainInfo:\n    get:\n      security: []\n      description: Get first and last indexed block\n      tags:\n      - Blockchain Data\n      summary: Get Masterchain Info\n      operationId: api_v3_get_masterchain_info\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/MasterchainInfo'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/message:\n    post:\n      security: []\n      description: Send an external message to the TON network.\n      tags:\n      - Api/v2\n      summary: Send Message\n      operationId: api_v3_post_v2_message\n      requestBody:\n        required: true\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/V2SendMessageRequest'\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/V2SendMessageResult'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/messages:\n    get:\n      security: []\n      description: Get messages by specified filters.\n      tags:\n      - Blockchain Data\n      summary: Get messages\n      operationId: api_v3_get_messages\n      parameters:\n      - name: msg_hash\n        in: query\n        description: Message hash. Acceptable in hex, base64 and base64url forms.\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: body_hash\n        in: query\n        description: Hash of message body.\n        schema:\n          type: string\n      - name: source\n        in: query\n        description: The source account address. Can be sent in hex, base64 or base64url form. Use value `null` to get external\n          messages.\n        schema:\n          type: string\n      - name: destination\n        in: query\n        description: The destination account address. Can be sent in hex, base64 or base64url form. Use value `null` to get\n          log messages.\n        schema:\n          type: string\n      - name: opcode\n        in: query\n        description: Opcode of message in hex or signed 32-bit decimal form.\n        schema:\n          type: string\n      - name: start_utime\n        in: query\n        description: Query messages with `created_at >= start_utime`.\n        schema:\n          type: integer\n          format: int32\n          minimum: 0\n      - name: end_utime\n        in: query\n        description: Query messages with `created_at >= start_utime`.\n        schema:\n          type: integer\n          format: int32\n          minimum: 0\n      - name: start_lt\n        in: query\n        description: Query messages with `created_lt >= start_lt`.\n        schema:\n          type: integer\n          format: int64\n          minimum: 0\n      - name: end_lt\n        in: query\n        description: Query messages with `created_lt <= end_lt`.\n        schema:\n          type: integer\n          format: int64\n          minimum: 0\n      - name: direction\n        in: query\n        description: Direction of message.\n        schema:\n          type: string\n          enum:\n          - in\n          - out\n      - name: exclude_externals\n        in: query\n        description: Exclude external messages.\n        schema:\n          type: boolean\n      - name: only_externals\n        in: query\n        description: Return only external messages.\n        schema:\n          type: boolean\n      - name: limit\n        in: query\n        description: Limit number of queried rows. Use with *offset* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 10\n          minimum: 1\n          maximum: 1000\n      - name: offset\n        in: query\n        description: Skip first N rows. Use with *limit* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 0\n          minimum: 0\n      - name: sort\n        in: query\n        description: Sort transactions by lt. If set to `desc`, you better set `start_lt = 1` to get latest messages.\n        schema:\n          type: string\n          default: desc\n          enum:\n          - asc\n          - desc\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/MessagesResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/metadata:\n    get:\n      security: []\n      description: Query address metadata\n      tags:\n      - Accounts\n      summary: Metadata\n      operationId: api_v3_get_metadata\n      parameters:\n      - name: address\n        in: query\n        description: 'List of addresses in any form to get address metadata. Max: 1024.'\n        required: true\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Metadata'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/multisig/orders:\n    get:\n      security: []\n      description: Get multisig orders by specified filters\n      tags:\n      - Multisig\n      summary: Get Multisig Orders\n      operationId: api_v3_get_multisig_orders\n      parameters:\n      - name: address\n        in: query\n        description: 'Order address in any form. Max: 1024.'\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: multisig_address\n        in: query\n        description: 'Address of corresponding multisig. Max: 1024.'\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: parse_actions\n        in: query\n        description: Parser order actions\n        schema:\n          type: boolean\n          default: false\n      - name: limit\n        in: query\n        description: Limit number of queried rows. Use with *offset* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 10\n          minimum: 1\n          maximum: 1024\n      - name: offset\n        in: query\n        description: Skip first N rows. Use with *limit* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 0\n          minimum: 0\n      - name: sort\n        in: query\n        description: Sort orders by last_transaction_lt.\n        schema:\n          type: string\n          default: desc\n          enum:\n          - asc\n          - desc\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/MultisigOrderResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/multisig/wallets:\n    get:\n      security: []\n      description: Get multisig contracts by specified filters with associated orders\n      tags:\n      - Multisig\n      summary: Get Multisig Wallets\n      operationId: api_v3_get_multisig_wallets\n      parameters:\n      - name: address\n        in: query\n        description: 'Multisig contract address in any form. Max: 1024.'\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: wallet_address\n        in: query\n        description: 'Address of signer or proposer wallet in any form. Max: 1024.'\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: limit\n        in: query\n        description: Limit number of queried rows. Use with *offset* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 10\n          minimum: 1\n          maximum: 1024\n      - name: offset\n        in: query\n        description: Skip first N rows. Use with *limit* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 0\n          minimum: 0\n      - name: sort\n        in: query\n        description: Sort multisigs by last_transaction_lt.\n        schema:\n          type: string\n          default: desc\n          enum:\n          - asc\n          - desc\n      - name: include_orders\n        in: query\n        description: Gather multisig orders\n        schema:\n          type: boolean\n          default: true\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/MultisigResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/nft/collections:\n    get:\n      security: []\n      description: Get NFT collections by specified filters\n      tags:\n      - NFTs\n      summary: Get NFT collections\n      operationId: api_v3_get_nft_collections\n      parameters:\n      - name: collection_address\n        in: query\n        description: 'Collection address in any form. Max: 1024.'\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: owner_address\n        in: query\n        description: 'Address of collection owner in any form. Max: 1024.'\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: limit\n        in: query\n        description: Limit number of queried rows. Use with *offset* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 10\n          minimum: 1\n          maximum: 1000\n      - name: offset\n        in: query\n        description: Skip first N rows. Use with *limit* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 0\n          minimum: 0\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/NFTCollectionsResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/nft/items:\n    get:\n      security: []\n      description: Get NFT items by specified filters\n      tags:\n      - NFTs\n      summary: Get NFT items\n      operationId: api_v3_get_nft_items\n      parameters:\n      - name: address\n        in: query\n        description: 'NFT item address in any form. Max: 1000.'\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: owner_address\n        in: query\n        description: 'Address of NFT item owner in any form. Max: 1000.'\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: collection_address\n        in: query\n        description: Collection address in any form.\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: index\n        in: query\n        description: 'Index of item for given collection. Max: 1000.'\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: include_on_sale\n        in: query\n        description: Include nft on sales and auctions. Used only when owner_address is passed\n        schema:\n          type: boolean\n          default: false\n      - name: sort_by_last_transaction_lt\n        in: query\n        description: Sort NFT items by last transaction lt descending. **Warning:** results may be inconsistent during pagination\n          with limit and offset.\n        schema:\n          type: boolean\n      - name: limit\n        in: query\n        description: Limit number of queried rows. Use with *offset* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 10\n          minimum: 1\n          maximum: 1000\n      - name: offset\n        in: query\n        description: Skip first N rows. Use with *limit* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 0\n          minimum: 0\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/NFTItemsResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/nft/transfers:\n    get:\n      security: []\n      description: Get transfers of NFT items by specified filters\n      tags:\n      - NFTs\n      summary: Get NFT Transfers\n      operationId: api_v3_get_nft_transfers\n      parameters:\n      - name: owner_address\n        in: query\n        description: Address of NFT owner in any form. Max 1000\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: item_address\n        in: query\n        description: 'Address of NFT item in any form. Max: 1000.'\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: collection_address\n        in: query\n        description: Collection address in any form.\n        schema:\n          type: string\n      - name: direction\n        in: query\n        description: Direction of transfer.\n        schema:\n          type: string\n          enum:\n          - in\n          - out\n      - name: start_utime\n        in: query\n        description: Query transactions with generation UTC timestamp **after** given timestamp.\n        schema:\n          type: integer\n          format: int32\n          minimum: 0\n      - name: end_utime\n        in: query\n        description: Query transactions with generation UTC timestamp **before** given timestamp.\n        schema:\n          type: integer\n          format: int32\n          minimum: 0\n      - name: start_lt\n        in: query\n        description: Query transactions with `lt >= start_lt`.\n        schema:\n          type: integer\n          format: int64\n          minimum: 0\n      - name: end_lt\n        in: query\n        description: Query transactions with `lt <= end_lt`.\n        schema:\n          type: integer\n          format: int64\n          minimum: 0\n      - name: limit\n        in: query\n        description: Limit number of queried rows. Use with *offset* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 10\n          minimum: 1\n          maximum: 1000\n      - name: offset\n        in: query\n        description: Skip first N rows. Use with *limit* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 0\n          minimum: 0\n      - name: sort\n        in: query\n        description: Sort transactions by lt.\n        schema:\n          type: string\n          default: desc\n          enum:\n          - asc\n          - desc\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/NFTTransfersResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/pendingActions:\n    get:\n      security: []\n      description: Get actions by specified filter.\n      tags:\n      - Actions and traces\n      summary: Get Pending Actions\n      operationId: api_v3_get_pending_actions\n      parameters:\n      - name: account\n        in: query\n        description: List of account addresses to get actions. Can be sent in hex, base64 or base64url form.\n        schema:\n          type: string\n      - name: ext_msg_hash\n        in: query\n        description: Find actions by trace external hash\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: supported_action_types\n        in: query\n        description: Supported action types\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: include_transactions\n        in: query\n        description: Include `transactions_full` array with detailed transaction data for each action in response.\n        schema:\n          type: boolean\n          default: false\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ActionsResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/pendingTraces:\n    get:\n      security: []\n      description: Get traces by specified filter.\n      tags:\n      - Actions and traces\n      summary: Get Pending Traces\n      operationId: api_v3_get_pending_traces\n      parameters:\n      - name: account\n        in: query\n        description: List of account addresses to get transactions. Can be sent in hex, base64 or base64url form.\n        schema:\n          type: string\n      - name: ext_msg_hash\n        in: query\n        description: Find trace by external hash\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/TracesResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/pendingTransactions:\n    get:\n      security: []\n      description: Get pending transactions by specified filter.\n      tags:\n      - Blockchain Data\n      summary: Get pending transactions\n      operationId: api_v3_get_pending_transactions\n      parameters:\n      - name: account\n        in: query\n        description: List of account addresses to get transactions. Can be sent in hex, base64 or base64url form.\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: trace_id\n        in: query\n        description: Find transactions by trace id.\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/TransactionsResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/runGetMethod:\n    post:\n      security: []\n      description: |-\n        Run get method of smart contract. Stack supports only `num`, `cell` and `slice` types:\n        ```\n        [\n        {\n        \"type\": \"num\",\n        \"value\": \"0x12a\"\n        },\n        {\n        \"type\": \"cell\",\n        \"value\": \"te6...\" // base64 encoded boc with cell\n        },\n        {\n        \"type\": \"slice\",\n        \"value\": \"te6...\" // base64 encoded boc with slice\n        }\n        ]\n        ```\n      tags:\n      - Api/v2\n      summary: Run Get-Method\n      operationId: api_v3_post_v2_rungetmethod\n      requestBody:\n        required: true\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/V2RunGetMethodRequest'\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/V2RunGetMethodRequest'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/topAccountsByBalance:\n    get:\n      security: []\n      description: Get list of accounts sorted descending by balance.\n      tags:\n      - Stats\n      summary: Get Top Accounts By Balance\n      operationId: api_v3_get_top_accounts_by_balance\n      parameters:\n      - name: limit\n        in: query\n        description: Limit number of queried rows. Use with *offset* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 10\n          minimum: 1\n          maximum: 1000\n      - name: offset\n        in: query\n        description: Skip first N rows. Use with *limit* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 0\n          minimum: 0\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  $ref: '#/components/schemas/AccountBalance'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/traces:\n    get:\n      security: []\n      description: Get traces by specified filter.\n      tags:\n      - Actions and traces\n      summary: Get Traces\n      operationId: api_v3_get_traces\n      parameters:\n      - name: account\n        in: query\n        description: List of account addresses to get transactions. Can be sent in hex, base64 or base64url form.\n        schema:\n          type: string\n      - name: trace_id\n        in: query\n        description: Find trace by trace id.\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: tx_hash\n        in: query\n        description: Find trace by transaction hash.\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: msg_hash\n        in: query\n        description: Find trace by message hash.\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: mc_seqno\n        in: query\n        description: Query traces that was completed in masterchain block with given seqno\n        schema:\n          type: integer\n          format: int32\n      - name: start_utime\n        in: query\n        description: Query traces, which was finished **after** given timestamp.\n        schema:\n          type: integer\n          format: int32\n          minimum: 0\n      - name: end_utime\n        in: query\n        description: Query traces, which was finished **before** given timestamp.\n        schema:\n          type: integer\n          format: int32\n          minimum: 0\n      - name: start_lt\n        in: query\n        description: Query traces with `end_lt >= start_lt`.\n        schema:\n          type: integer\n          format: int64\n          minimum: 0\n      - name: end_lt\n        in: query\n        description: Query traces with `end_lt <= end_lt`.\n        schema:\n          type: integer\n          format: int64\n          minimum: 0\n      - name: include_actions\n        in: query\n        description: Include trace actions.\n        schema:\n          type: boolean\n          default: false\n      - name: supported_action_types\n        in: query\n        description: Supported action types\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: limit\n        in: query\n        description: Limit number of queried rows. Use with *offset* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 10\n          minimum: 1\n          maximum: 1000\n      - name: offset\n        in: query\n        description: Skip first N rows. Use with *limit* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 0\n          minimum: 0\n      - name: sort\n        in: query\n        description: Sort traces by lt.\n        schema:\n          type: string\n          default: desc\n          enum:\n          - asc\n          - desc\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/TracesResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/transactions:\n    get:\n      security: []\n      description: Get transactions by specified filter.\n      tags:\n      - Blockchain Data\n      summary: Get transactions\n      operationId: api_v3_get_transactions\n      parameters:\n      - name: workchain\n        in: query\n        description: Block workchain.\n        schema:\n          type: integer\n          format: int32\n      - name: shard\n        in: query\n        description: 'Block shard id. Must be sent with *workchain*. Example: `8000000000000000`.'\n        schema:\n          type: string\n      - name: seqno\n        in: query\n        description: Block block seqno. Must be sent with *workchain* and *shard*.\n        schema:\n          type: integer\n          format: int32\n      - name: mc_seqno\n        in: query\n        description: Masterchain block seqno.\n        schema:\n          type: integer\n          format: int32\n      - name: account\n        in: query\n        description: List of account addresses to get transactions. Can be sent in hex, base64 or base64url form.\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: exclude_account\n        in: query\n        description: Exclude transactions on specified account addresses.\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: hash\n        in: query\n        description: Transaction hash.\n        schema:\n          type: string\n      - name: lt\n        in: query\n        description: Transaction lt.\n        schema:\n          type: integer\n          format: int64\n      - name: start_utime\n        in: query\n        description: Query transactions with generation UTC timestamp **after** given timestamp.\n        schema:\n          type: integer\n          format: int32\n          minimum: 0\n      - name: end_utime\n        in: query\n        description: Query transactions with generation UTC timestamp **before** given timestamp.\n        schema:\n          type: integer\n          format: int32\n          minimum: 0\n      - name: start_lt\n        in: query\n        description: Query transactions with `lt >= start_lt`.\n        schema:\n          type: integer\n          format: int64\n          minimum: 0\n      - name: end_lt\n        in: query\n        description: Query transactions with `lt <= end_lt`.\n        schema:\n          type: integer\n          format: int64\n          minimum: 0\n      - name: limit\n        in: query\n        description: Limit number of queried rows. Use with *offset* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 10\n          minimum: 1\n          maximum: 1000\n      - name: offset\n        in: query\n        description: Skip first N rows. Use with *limit* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 0\n          minimum: 0\n      - name: sort\n        in: query\n        description: Sort transactions by lt.\n        schema:\n          type: string\n          default: desc\n          enum:\n          - asc\n          - desc\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/TransactionsResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/transactionsByMasterchainBlock:\n    get:\n      security: []\n      description: Returns transactions from masterchain block and from all shards.\n      tags:\n      - Blockchain Data\n      summary: Get transactions by Masterchain block\n      operationId: api_v3_get_transactions_by_masterchain_block\n      parameters:\n      - name: seqno\n        in: query\n        description: Masterchain block seqno.\n        required: true\n        schema:\n          type: integer\n          format: int32\n      - name: limit\n        in: query\n        description: Limit number of queried rows. Use with *offset* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 10\n          minimum: 1\n          maximum: 1000\n      - name: offset\n        in: query\n        description: Skip first N rows. Use with *limit* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 0\n          minimum: 0\n      - name: sort\n        in: query\n        description: Sort transactions by lt.\n        schema:\n          type: string\n          default: desc\n          enum:\n          - asc\n          - desc\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/TransactionsResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/transactionsByMessage:\n    get:\n      security: []\n      description: Get transactions whose inbound/outbound message has the specified hash. \\\n      tags:\n      - Blockchain Data\n      summary: Get transactions by message\n      operationId: api_v3_get_transactions_by_message\n      parameters:\n      - name: msg_hash\n        in: query\n        description: Message hash. Acceptable in hex, base64 and base64url forms.\n        schema:\n          type: string\n      - name: body_hash\n        in: query\n        description: Hash of message body.\n        schema:\n          type: string\n      - name: opcode\n        in: query\n        description: Opcode of message in hex or signed 32-bit decimal form.\n        schema:\n          type: string\n      - name: direction\n        in: query\n        description: Direction of message.\n        schema:\n          type: string\n          enum:\n          - in\n          - out\n      - name: limit\n        in: query\n        description: Limit number of queried rows. Use with *offset* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 10\n          minimum: 1\n          maximum: 1000\n      - name: offset\n        in: query\n        description: Skip first N rows. Use with *limit* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 0\n          minimum: 0\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/TransactionsResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/vesting:\n    get:\n      security: []\n      description: Get vesting contracts by specified filters\n      tags:\n      - Vesting\n      summary: Get Vesting Contracts\n      operationId: api_v3_get_vesting_contracts\n      parameters:\n      - name: contract_address\n        in: query\n        description: 'Vesting contract address in any form. Max: 1000.'\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: wallet_address\n        in: query\n        description: 'Wallet address to filter by owner or sender. Max: 1000.'\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      - name: check_whitelist\n        in: query\n        description: Check if wallet address is in whitelist.\n        schema:\n          type: boolean\n          default: false\n      - name: limit\n        in: query\n        description: Limit number of queried rows. Use with *offset* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 10\n          minimum: 1\n          maximum: 1000\n      - name: offset\n        in: query\n        description: Skip first N rows. Use with *limit* to batch read.\n        schema:\n          type: integer\n          format: int32\n          default: 0\n          minimum: 0\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/VestingContractsResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/walletInformation:\n    get:\n      security: []\n      description: 'Get wallet smart contract information. The following wallets are supported: `v1r1`, `v1r2`, `v1r3`, `v2r1`,\n        `v2r2`, `v3r1`, `v3r2`, `v4r1`, `v4r2`, `v5beta`, `v5r1`. In case the account is not a wallet error code 409 is returned.'\n      tags:\n      - Api/v2\n      summary: Get Wallet Information\n      operationId: api_v3_get_wallet_information\n      parameters:\n      - name: address\n        in: query\n        description: Account address in any form.\n        required: true\n        schema:\n          type: string\n      - name: use_v2\n        in: query\n        description: Use method from api/v2. Not recommended\n        schema:\n          type: boolean\n          default: true\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/V2WalletInformation'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\n  /api/v3/walletStates:\n    get:\n      security: []\n      description: Query wallet information\n      tags:\n      - Accounts\n      summary: Get Wallet States\n      operationId: api_v3_get_wallet_states\n      parameters:\n      - name: address\n        in: query\n        description: List of addresses in any form. Maximum 1000 addresses allowed.\n        required: true\n        explode: true\n        schema:\n          type: array\n          items:\n            type: string\n      responses:\n        '200':\n          description: OK\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/WalletStatesResponse'\n        '400':\n          description: Bad Request\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/RequestError'\ncomponents:\n  schemas:\n    AccountBalance:\n      type: object\n      properties:\n        account:\n          type: string\n        balance:\n          type: string\n    AccountState:\n      type: object\n      properties:\n        account_status:\n          type: string\n        balance:\n          type: string\n        code_boc:\n          type: string\n        code_hash:\n          type: string\n        data_boc:\n          type: string\n        data_hash:\n          type: string\n        extra_currencies:\n          type: object\n          additionalProperties:\n            type: string\n        frozen_hash:\n          type: string\n        hash:\n          type: string\n    AccountStateFull:\n      type: object\n      properties:\n        account_state_hash:\n          type: string\n        address:\n          type: string\n        balance:\n          type: string\n        code_boc:\n          type: string\n        code_hash:\n          type: string\n        contract_methods:\n          type: array\n          items:\n            type: integer\n        data_boc:\n          type: string\n        data_hash:\n          type: string\n        extra_currencies:\n          type: object\n          additionalProperties:\n            type: string\n        frozen_hash:\n          type: string\n        interfaces:\n          type: array\n          items:\n            type: string\n        last_transaction_hash:\n          type: string\n        last_transaction_lt:\n          type: string\n          example: '0'\n        status:\n          type: string\n    AccountStatesResponse:\n      type: object\n      properties:\n        accounts:\n          type: array\n          items:\n            $ref: '#/components/schemas/AccountStateFull'\n        address_book:\n          $ref: '#/components/schemas/AddressBook'\n        metadata:\n          $ref: '#/components/schemas/Metadata'\n    Action:\n      type: object\n      properties:\n        accounts:\n          type: array\n          items:\n            type: string\n        action_id:\n          type: string\n        details: {}\n        end_lt:\n          type: string\n          example: '0'\n        end_utime:\n          type: integer\n        start_lt:\n          type: string\n          example: '0'\n        start_utime:\n          type: integer\n        success:\n          type: boolean\n        trace_end_lt:\n          type: string\n          example: '0'\n        trace_end_utime:\n          type: integer\n        trace_external_hash:\n          type: string\n        trace_external_hash_norm:\n          type: string\n        trace_id:\n          type: string\n        trace_mc_seqno_end:\n          type: integer\n        transactions:\n          type: array\n          items:\n            type: string\n        transactions_full:\n          type: array\n          items:\n            $ref: '#/components/schemas/Transaction'\n        type:\n          type: string\n    ActionPhase:\n      type: object\n      properties:\n        action_list_hash:\n          type: string\n        msgs_created:\n          type: integer\n        no_funds:\n          type: boolean\n        result_arg:\n          type: integer\n        result_code:\n          type: integer\n        skipped_actions:\n          type: integer\n        spec_actions:\n          type: integer\n        status_change:\n          type: string\n        success:\n          type: boolean\n        tot_actions:\n          type: integer\n        tot_msg_size:\n          $ref: '#/components/schemas/MsgSize'\n        total_action_fees:\n          type: string\n          example: '0'\n        total_fwd_fees:\n          type: string\n          example: '0'\n        valid:\n          type: boolean\n    ActionsResponse:\n      type: object\n      properties:\n        actions:\n          type: array\n          items:\n            $ref: '#/components/schemas/Action'\n        address_book:\n          $ref: '#/components/schemas/AddressBook'\n        metadata:\n          $ref: '#/components/schemas/Metadata'\n    AddressBook:\n      type: object\n      additionalProperties:\n        $ref: '#/components/schemas/AddressBookRow'\n    AddressBookRow:\n      type: object\n      properties:\n        domain:\n          type: string\n        interfaces:\n          type: array\n          items:\n            type: string\n        user_friendly:\n          type: string\n    AddressMetadata:\n      type: object\n      properties:\n        is_indexed:\n          type: boolean\n        token_info:\n          type: array\n          items:\n            $ref: '#/components/schemas/TokenInfo'\n    Block:\n      type: object\n      properties:\n        after_merge:\n          type: boolean\n        after_split:\n          type: boolean\n        before_split:\n          type: boolean\n        created_by:\n          type: string\n        end_lt:\n          type: string\n          example: '0'\n        file_hash:\n          type: string\n        flags:\n          type: integer\n        gen_catchain_seqno:\n          type: integer\n        gen_utime:\n          type: string\n          example: '0'\n        global_id:\n          type: integer\n        key_block:\n          type: boolean\n        master_ref_seqno:\n          type: integer\n        masterchain_block_ref:\n          $ref: '#/components/schemas/BlockId'\n        min_ref_mc_seqno:\n          type: integer\n        prev_blocks:\n          type: array\n          items:\n            $ref: '#/components/schemas/BlockId'\n        prev_key_block_seqno:\n          type: integer\n        rand_seed:\n          type: string\n        root_hash:\n          type: string\n        seqno:\n          type: integer\n        shard:\n          type: string\n          example: '0'\n        start_lt:\n          type: string\n          example: '0'\n        tx_count:\n          type: integer\n        validator_list_hash_short:\n          type: integer\n        version:\n          type: integer\n        vert_seqno:\n          type: integer\n        vert_seqno_incr:\n          type: boolean\n        want_merge:\n          type: boolean\n        want_split:\n          type: boolean\n        workchain:\n          type: integer\n    BlockId:\n      type: object\n      properties:\n        seqno:\n          type: integer\n        shard:\n          type: string\n          example: '0'\n        workchain:\n          type: integer\n    BlocksResponse:\n      type: object\n      properties:\n        blocks:\n          type: array\n          items:\n            $ref: '#/components/schemas/Block'\n    BouncePhase:\n      type: object\n      properties:\n        fwd_fees:\n          type: string\n          example: '0'\n        msg_fees:\n          type: string\n          example: '0'\n        msg_size:\n          $ref: '#/components/schemas/MsgSize'\n        req_fwd_fees:\n          type: string\n          example: '0'\n        type:\n          type: string\n    ComputePhase:\n      type: object\n      properties:\n        account_activated:\n          type: boolean\n        exit_arg:\n          type: integer\n        exit_code:\n          type: integer\n        gas_credit:\n          type: string\n          example: '0'\n        gas_fees:\n          type: string\n          example: '0'\n        gas_limit:\n          type: string\n          example: '0'\n        gas_used:\n          type: string\n          example: '0'\n        mode:\n          type: integer\n        msg_state_used:\n          type: boolean\n        reason:\n          type: string\n        skipped:\n          type: boolean\n        success:\n          type: boolean\n        vm_final_state_hash:\n          type: string\n        vm_init_state_hash:\n          type: string\n        vm_steps:\n          type: integer\n    CreditPhase:\n      type: object\n      properties:\n        credit:\n          type: string\n          example: '0'\n        credit_extra_currencies:\n          type: object\n          additionalProperties:\n            type: string\n        due_fees_collected:\n          type: string\n          example: '0'\n    DNSRecord:\n      type: object\n      properties:\n        dns_next_resolver:\n          type: string\n        dns_site_adnl:\n          type: string\n        dns_storage_bag_id:\n          type: string\n        dns_wallet:\n          type: string\n        domain:\n          type: string\n        nft_item_address:\n          type: string\n        nft_item_owner:\n          type: string\n    DNSRecordsResponse:\n      type: object\n      properties:\n        address_book:\n          $ref: '#/components/schemas/AddressBook'\n        records:\n          type: array\n          items:\n            $ref: '#/components/schemas/DNSRecord'\n    DecodeRequest:\n      type: object\n      properties:\n        bodies:\n          type: array\n          items:\n            type: string\n        opcodes:\n          type: array\n          items:\n            type: string\n    DecodeResponse:\n      type: object\n      properties:\n        bodies:\n          type: array\n          items:\n            type: object\n            additionalProperties: true\n        opcodes:\n          type: array\n          items:\n            type: string\n    JettonBurn:\n      type: object\n      properties:\n        amount:\n          type: string\n        custom_payload:\n          type: string\n        decoded_custom_payload:\n          type: array\n          items:\n            type: integer\n        jetton_master:\n          type: string\n        jetton_wallet:\n          type: string\n        owner:\n          type: string\n        query_id:\n          type: string\n        response_destination:\n          type: string\n        trace_id:\n          type: string\n        transaction_aborted:\n          type: boolean\n        transaction_hash:\n          type: string\n        transaction_lt:\n          type: string\n          example: '0'\n        transaction_now:\n          type: integer\n    JettonBurnsResponse:\n      type: object\n      properties:\n        address_book:\n          $ref: '#/components/schemas/AddressBook'\n        jetton_burns:\n          type: array\n          items:\n            $ref: '#/components/schemas/JettonBurn'\n        metadata:\n          $ref: '#/components/schemas/Metadata'\n    JettonMaster:\n      type: object\n      properties:\n        address:\n          type: string\n        admin_address:\n          type: string\n        code_hash:\n          type: string\n        data_hash:\n          type: string\n        jetton_content:\n          type: object\n          additionalProperties: true\n        jetton_wallet_code_hash:\n          type: string\n        last_transaction_lt:\n          type: string\n          example: '0'\n        mintable:\n          type: boolean\n        total_supply:\n          type: string\n    JettonMastersResponse:\n      type: object\n      properties:\n        address_book:\n          $ref: '#/components/schemas/AddressBook'\n        jetton_masters:\n          type: array\n          items:\n            $ref: '#/components/schemas/JettonMaster'\n        metadata:\n          $ref: '#/components/schemas/Metadata'\n    JettonTransfer:\n      type: object\n      properties:\n        amount:\n          type: string\n        custom_payload:\n          type: string\n        decoded_custom_payload:\n          type: array\n          items:\n            type: integer\n        decoded_forward_payload:\n          type: array\n          items:\n            type: integer\n        destination:\n          type: string\n        forward_payload:\n          type: string\n        forward_ton_amount:\n          type: string\n        jetton_master:\n          type: string\n        query_id:\n          type: string\n        response_destination:\n          type: string\n        source:\n          type: string\n        source_wallet:\n          type: string\n        trace_id:\n          type: string\n        transaction_aborted:\n          type: boolean\n        transaction_hash:\n          type: string\n        transaction_lt:\n          type: string\n          example: '0'\n        transaction_now:\n          type: integer\n    JettonTransfersResponse:\n      type: object\n      properties:\n        address_book:\n          $ref: '#/components/schemas/AddressBook'\n        jetton_transfers:\n          type: array\n          items:\n            $ref: '#/components/schemas/JettonTransfer'\n        metadata:\n          $ref: '#/components/schemas/Metadata'\n    JettonWallet:\n      type: object\n      properties:\n        address:\n          type: string\n        balance:\n          type: string\n        code_hash:\n          type: string\n        data_hash:\n          type: string\n        jetton:\n          type: string\n        last_transaction_lt:\n          type: string\n          example: '0'\n        mintless_info:\n          $ref: '#/components/schemas/JettonWalletMintlessInfo'\n        owner:\n          type: string\n    JettonWalletMintlessInfo:\n      type: object\n      properties:\n        amount:\n          type: string\n        custom_payload_api_uri:\n          type: array\n          items:\n            type: string\n        expire_at:\n          type: integer\n        start_from:\n          type: integer\n    JettonWalletsResponse:\n      type: object\n      properties:\n        address_book:\n          $ref: '#/components/schemas/AddressBook'\n        jetton_wallets:\n          type: array\n          items:\n            $ref: '#/components/schemas/JettonWallet'\n        metadata:\n          $ref: '#/components/schemas/Metadata'\n    MasterchainInfo:\n      type: object\n      properties:\n        first:\n          $ref: '#/components/schemas/Block'\n        last:\n          $ref: '#/components/schemas/Block'\n    Message:\n      type: object\n      properties:\n        bounce:\n          type: boolean\n        bounced:\n          type: boolean\n        created_at:\n          type: string\n          example: '0'\n        created_lt:\n          type: string\n          example: '0'\n        decoded_opcode:\n          type: string\n        destination:\n          type: string\n        extra_flags:\n          type: string\n        fwd_fee:\n          type: string\n          example: '0'\n        hash:\n          type: string\n        hash_norm:\n          type: string\n        ihr_disabled:\n          type: boolean\n        ihr_fee:\n          type: string\n          example: '0'\n        import_fee:\n          type: string\n          example: '0'\n        in_msg_tx_hash:\n          type: string\n        init_state:\n          $ref: '#/components/schemas/MessageContent'\n        message_content:\n          $ref: '#/components/schemas/MessageContent'\n        opcode:\n          type: integer\n        out_msg_tx_hash:\n          type: string\n        source:\n          type: string\n        value:\n          type: string\n          example: '0'\n        value_extra_currencies:\n          type: object\n          additionalProperties:\n            type: string\n    MessageContent:\n      type: object\n      properties:\n        body:\n          type: string\n        decoded:\n          type: object\n        hash:\n          type: string\n    MessagesResponse:\n      type: object\n      properties:\n        address_book:\n          $ref: '#/components/schemas/AddressBook'\n        messages:\n          type: array\n          items:\n            $ref: '#/components/schemas/Message'\n        metadata:\n          $ref: '#/components/schemas/Metadata'\n    Metadata:\n      type: object\n      additionalProperties:\n        $ref: '#/components/schemas/AddressMetadata'\n    MsgSize:\n      type: object\n      properties:\n        bits:\n          type: string\n          example: '0'\n        cells:\n          type: string\n          example: '0'\n    Multisig:\n      type: object\n      properties:\n        address:\n          type: string\n        code_hash:\n          type: string\n        data_hash:\n          type: string\n        last_transaction_lt:\n          type: string\n          example: '0'\n        next_order_seqno:\n          type: string\n        orders:\n          type: array\n          items:\n            $ref: '#/components/schemas/MultisigOrder'\n        proposers:\n          type: array\n          items:\n            type: string\n        signers:\n          type: array\n          items:\n            type: string\n        threshold:\n          type: integer\n    MultisigOrder:\n      type: object\n      properties:\n        actions:\n          type: array\n          items:\n            $ref: '#/components/schemas/index.OrderAction'\n        address:\n          type: string\n        approvals_mask:\n          type: string\n        approvals_num:\n          type: integer\n        code_hash:\n          type: string\n        data_hash:\n          type: string\n        expiration_date:\n          type: integer\n        last_transaction_lt:\n          type: string\n          example: '0'\n        multisig_address:\n          type: string\n        order_boc:\n          type: string\n        order_seqno:\n          type: string\n        sent_for_execution:\n          type: boolean\n        signers:\n          type: array\n          items:\n            type: string\n        threshold:\n          type: integer\n    MultisigOrderResponse:\n      type: object\n      properties:\n        address_book:\n          $ref: '#/components/schemas/AddressBook'\n        orders:\n          type: array\n          items:\n            $ref: '#/components/schemas/MultisigOrder'\n    MultisigResponse:\n      type: object\n      properties:\n        address_book:\n          $ref: '#/components/schemas/AddressBook'\n        multisigs:\n          type: array\n          items:\n            $ref: '#/components/schemas/Multisig'\n    NFTCollection:\n      type: object\n      properties:\n        address:\n          type: string\n        code_hash:\n          type: string\n        collection_content:\n          type: object\n          additionalProperties: true\n        data_hash:\n          type: string\n        last_transaction_lt:\n          type: string\n          example: '0'\n        next_item_index:\n          type: string\n        owner_address:\n          type: string\n    NFTCollectionsResponse:\n      type: object\n      properties:\n        address_book:\n          $ref: '#/components/schemas/AddressBook'\n        metadata:\n          $ref: '#/components/schemas/Metadata'\n        nft_collections:\n          type: array\n          items:\n            $ref: '#/components/schemas/NFTCollection'\n    NFTItem:\n      type: object\n      properties:\n        address:\n          type: string\n        auction_contract_address:\n          type: string\n        code_hash:\n          type: string\n        collection:\n          $ref: '#/components/schemas/NFTCollection'\n        collection_address:\n          type: string\n        content:\n          type: object\n          additionalProperties: true\n        data_hash:\n          type: string\n        index:\n          type: string\n        init:\n          type: boolean\n        last_transaction_lt:\n          type: string\n          example: '0'\n        on_sale:\n          type: boolean\n        owner_address:\n          type: string\n        real_owner:\n          type: string\n        sale_contract_address:\n          type: string\n    NFTItemsResponse:\n      type: object\n      properties:\n        address_book:\n          $ref: '#/components/schemas/AddressBook'\n        metadata:\n          $ref: '#/components/schemas/Metadata'\n        nft_items:\n          type: array\n          items:\n            $ref: '#/components/schemas/NFTItem'\n    NFTTransfer:\n      type: object\n      properties:\n        custom_payload:\n          type: string\n        decoded_custom_payload:\n          type: array\n          items:\n            type: integer\n        decoded_forward_payload:\n          type: array\n          items:\n            type: integer\n        forward_amount:\n          type: string\n        forward_payload:\n          type: string\n        new_owner:\n          type: string\n        nft_address:\n          type: string\n        nft_collection:\n          type: string\n        old_owner:\n          type: string\n        query_id:\n          type: string\n        response_destination:\n          type: string\n        trace_id:\n          type: string\n        transaction_aborted:\n          type: boolean\n        transaction_hash:\n          type: string\n        transaction_lt:\n          type: string\n          example: '0'\n        transaction_now:\n          type: integer\n    NFTTransfersResponse:\n      type: object\n      properties:\n        address_book:\n          $ref: '#/components/schemas/AddressBook'\n        metadata:\n          $ref: '#/components/schemas/Metadata'\n        nft_transfers:\n          type: array\n          items:\n            $ref: '#/components/schemas/NFTTransfer'\n    RequestError:\n      type: object\n      properties:\n        code:\n          type: integer\n        error:\n          type: string\n    SplitInfo:\n      type: object\n      properties:\n        acc_split_depth:\n          type: integer\n        cur_shard_pfx_len:\n          type: integer\n        sibling_addr:\n          type: string\n        this_addr:\n          type: string\n    StoragePhase:\n      type: object\n      properties:\n        status_change:\n          type: string\n        storage_fees_collected:\n          type: string\n          example: '0'\n        storage_fees_due:\n          type: string\n          example: '0'\n    TokenInfo:\n      type: object\n      properties:\n        description:\n          type: string\n        extra:\n          type: object\n          additionalProperties: true\n        image:\n          type: string\n        name:\n          type: string\n        nft_index:\n          type: string\n        symbol:\n          type: string\n        type:\n          type: string\n        valid:\n          type: boolean\n    Trace:\n      type: object\n      properties:\n        actions:\n          type: array\n          items:\n            $ref: '#/components/schemas/Action'\n        end_lt:\n          type: string\n          example: '0'\n        end_utime:\n          type: integer\n        external_hash:\n          type: string\n        is_incomplete:\n          type: boolean\n        mc_seqno_end:\n          type: string\n        mc_seqno_start:\n          type: string\n        start_lt:\n          type: string\n          example: '0'\n        start_utime:\n          type: integer\n        trace:\n          $ref: '#/components/schemas/TraceNode'\n        trace_id:\n          type: string\n        trace_info:\n          $ref: '#/components/schemas/TraceMeta'\n        transactions:\n          type: object\n          additionalProperties:\n            $ref: '#/components/schemas/Transaction'\n        transactions_order:\n          type: array\n          items:\n            type: string\n        warning:\n          type: string\n    TraceMeta:\n      type: object\n      properties:\n        classification_state:\n          type: string\n        messages:\n          type: integer\n        pending_messages:\n          type: integer\n        trace_state:\n          type: string\n        transactions:\n          type: integer\n    TraceNode:\n      type: object\n      properties:\n        children:\n          type: array\n          items:\n            $ref: '#/components/schemas/TraceNode'\n        in_msg:\n          $ref: '#/components/schemas/Message'\n        in_msg_hash:\n          type: string\n        transaction:\n          $ref: '#/components/schemas/Transaction'\n        tx_hash:\n          type: string\n    TracesResponse:\n      type: object\n      properties:\n        address_book:\n          $ref: '#/components/schemas/AddressBook'\n        metadata:\n          $ref: '#/components/schemas/Metadata'\n        traces:\n          type: array\n          items:\n            $ref: '#/components/schemas/Trace'\n    Transaction:\n      type: object\n      properties:\n        account:\n          type: string\n        account_state_after:\n          $ref: '#/components/schemas/AccountState'\n        account_state_before:\n          $ref: '#/components/schemas/AccountState'\n        block_ref:\n          $ref: '#/components/schemas/BlockId'\n        description:\n          $ref: '#/components/schemas/TransactionDescr'\n        emulated:\n          type: boolean\n        end_status:\n          type: string\n        hash:\n          type: string\n        in_msg:\n          $ref: '#/components/schemas/Message'\n        lt:\n          type: string\n          example: '0'\n        mc_block_seqno:\n          type: integer\n        now:\n          type: integer\n        orig_status:\n          type: string\n        out_msgs:\n          type: array\n          items:\n            $ref: '#/components/schemas/Message'\n        prev_trans_hash:\n          type: string\n        prev_trans_lt:\n          type: string\n          example: '0'\n        total_fees:\n          type: string\n          example: '0'\n        total_fees_extra_currencies:\n          type: object\n          additionalProperties:\n            type: string\n        trace_external_hash:\n          type: string\n        trace_id:\n          type: string\n    TransactionDescr:\n      type: object\n      properties:\n        aborted:\n          type: boolean\n        action:\n          $ref: '#/components/schemas/ActionPhase'\n        bounce:\n          $ref: '#/components/schemas/BouncePhase'\n        compute_ph:\n          $ref: '#/components/schemas/ComputePhase'\n        credit_first:\n          type: boolean\n        credit_ph:\n          $ref: '#/components/schemas/CreditPhase'\n        destroyed:\n          type: boolean\n        installed:\n          type: boolean\n        is_tock:\n          type: boolean\n        split_info:\n          $ref: '#/components/schemas/SplitInfo'\n        storage_ph:\n          $ref: '#/components/schemas/StoragePhase'\n        type:\n          type: string\n    TransactionsResponse:\n      type: object\n      properties:\n        address_book:\n          $ref: '#/components/schemas/AddressBook'\n        transactions:\n          type: array\n          items:\n            $ref: '#/components/schemas/Transaction'\n    V2AddressInformation:\n      type: object\n      properties:\n        balance:\n          type: string\n        code:\n          type: string\n        data:\n          type: string\n        frozen_hash:\n          type: string\n        last_transaction_hash:\n          type: string\n        last_transaction_lt:\n          type: string\n        status:\n          type: string\n    V2EstimateFeeRequest:\n      type: object\n      properties:\n        address:\n          type: string\n        body:\n          type: string\n        ignore_chksig:\n          type: boolean\n        init_code:\n          type: string\n        init_data:\n          type: string\n    V2EstimateFeeResult:\n      type: object\n      properties:\n        destination_fees:\n          type: array\n          items:\n            $ref: '#/components/schemas/V2EstimatedFee'\n        source_fees:\n          $ref: '#/components/schemas/V2EstimatedFee'\n    V2EstimatedFee:\n      type: object\n      properties:\n        fwd_fee:\n          type: integer\n        gas_fee:\n          type: integer\n        in_fwd_fee:\n          type: integer\n        storage_fee:\n          type: integer\n    V2RunGetMethodRequest:\n      type: object\n      properties:\n        address:\n          type: string\n        method:\n          type: string\n        stack:\n          type: array\n          items:\n            $ref: '#/components/schemas/V2StackEntity'\n    V2SendMessageRequest:\n      type: object\n      properties:\n        boc:\n          type: string\n    V2SendMessageResult:\n      type: object\n      properties:\n        message_hash:\n          type: string\n        message_hash_norm:\n          type: string\n    V2StackEntity:\n      type: object\n      properties:\n        type:\n          type: string\n        value: {}\n    V2WalletInformation:\n      type: object\n      properties:\n        balance:\n          type: string\n        last_transaction_hash:\n          type: string\n        last_transaction_lt:\n          type: string\n        seqno:\n          type: integer\n        status:\n          type: string\n        wallet_id:\n          type: integer\n        wallet_type:\n          type: string\n    VestingContractsResponse:\n      type: object\n      properties:\n        address_book:\n          $ref: '#/components/schemas/AddressBook'\n        vesting_contracts:\n          type: array\n          items:\n            $ref: '#/components/schemas/index.VestingInfo'\n    WalletState:\n      type: object\n      properties:\n        address:\n          type: string\n        balance:\n          type: string\n        code_hash:\n          type: string\n        extra_currencies:\n          type: object\n          additionalProperties:\n            type: string\n        is_signature_allowed:\n          type: boolean\n        is_wallet:\n          type: boolean\n        last_transaction_hash:\n          type: string\n        last_transaction_lt:\n          type: string\n          example: '0'\n        seqno:\n          type: integer\n        status:\n          type: string\n        wallet_id:\n          type: integer\n        wallet_type:\n          type: string\n    WalletStatesResponse:\n      type: object\n      properties:\n        address_book:\n          $ref: '#/components/schemas/AddressBook'\n        metadata:\n          $ref: '#/components/schemas/Metadata'\n        wallets:\n          type: array\n          items:\n            $ref: '#/components/schemas/WalletState'\n    OrderAction:\n      type: object\n      properties:\n        body_raw:\n          type: array\n          items:\n            type: integer\n        destination:\n          type: string\n        error:\n          type: string\n        parsed:\n          type: boolean\n        parsed_body: {}\n        parsed_body_type:\n          type: string\n        send_mode:\n          type: integer\n        value:\n          type: string\n    VestingInfo:\n      type: object\n      properties:\n        address:\n          type: string\n        cliff_duration:\n          type: integer\n        owner_address:\n          type: string\n        sender_address:\n          type: string\n        start_time:\n          type: integer\n        total_amount:\n          type: string\n        total_duration:\n          type: integer\n        unlock_period:\n          type: integer\n        whitelist:\n          type: array\n          items:\n            type: string\n  securitySchemes:\n    APIKeyHeader:\n      type: apiKey\n      name: X-Api-Key\n      in: header\n    APIKeyQuery:\n      type: apiKey\n      name: api_key\n      in: query\n"
  },
  {
    "path": "ecosystem/appkit/init.mdx",
    "content": "---\ntitle: \"How to initialize the TON Connect's AppKit\"\nsidebarTitle: \"Initialize the kit\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nIf there is a dApp that uses [TON Connect UI libraries](#relation-to-ton-connect-libraries), migrate that dApp to AppKit in a few steps:\n\n- [Migrate from `@tonconnect/ui-react` (React)](#migrate-from-%40tonconnect%2Fui-react)\n- [Migrate from `@tonconnect/ui` (Vanilla)](#migrate-from-%40tonconnect%2Fui)\n\n## Installation\n\nBefore initializing the TON Connect's AppKit, install it with the necessary peer dependencies:\n\n<CodeGroup>\n  ```shell title=\"React\" icon=\"react\"\n  #     AppKit React      TanStack Query        TON Connect          Core packages         # Buffer polyfill\n  npm i @ton/appkit-react @tanstack/react-query @tonconnect/ui-react @ton/core @ton/crypto buffer\n  ```\n\n  ```shell title=\"TypeScript\" icon=\"globe\"\n  #     AppKit      TanStack Query       TON Connect    Core packages         # Buffer polyfill\n  npm i @ton/appkit @tanstack/query-core @tonconnect/ui @ton/core @ton/crypto buffer\n  ```\n</CodeGroup>\n\nCore packages require a `Buffer` [polyfill](https://en.wikipedia.org/wiki/Polyfill_\\(programming\\)). Extend the module bundle configuration according to the bundler in use:\n\n<CodeGroup>\n  ```ts title=\"Vite\"\n  // vite.config.js\n  import { defineConfig } from 'vite';\n  export default defineConfig({\n    // ...prior options...\n    resolve: {\n      alias: {\n        buffer: 'buffer/',\n      },\n    },\n    define: {\n      Buffer: ['buffer', 'Buffer'],\n    },\n    // ...later options...\n  });\n  ```\n\n  ```ts title=\"Webpack\"\n  // webpack.config.js\n  const webpack = require('webpack');\n  module.exports = {\n    // ...prior options...\n    resolve: {\n      fallback: {\n        buffer: require.resolve('buffer/'),\n      }\n    },\n    plugins: [\n      new webpack.ProvidePlugin({\n        Buffer: ['buffer', 'Buffer'],\n      })\n    ],\n    // ...later options...\n  }\n  ```\n</CodeGroup>\n\n## Initialization\n\n<Aside type=\"tip\">\n  Jump to a [complete and exhaustive setup](#complete-setup).\n</Aside>\n\nThe basic kit initialization does not require any configuration options.\n\n<CodeGroup>\n  ```tsx title=\"React\" icon=\"react\"\n  import { AppKit, AppKitProvider } from '@ton/appkit-react';\n  import '@ton/appkit-react/styles.css';\n\n  const kit = new AppKit({});\n\n  // Wrap application in `AppKitProvider` and pass the `AppKit` instance.\n  export function App() {\n    return <AppKitProvider appKit={kit}>{/* ...app... */}</AppKitProvider>;\n  };\n  ```\n\n  ```ts title=\"TypeScript\" icon=\"globe\"\n  import { AppKit } from '@ton/appkit';\n\n  const kit = new AppKit({});\n  ```\n</CodeGroup>\n\nTo communicate with the blockchain, AppKit uses [TON Center APIs](/ecosystem/api/toncenter/introduction) by default. In particular, operations with assets require many API calls — [obtain a key to access higher limits](/ecosystem/api/toncenter/get-api-key) and prevent [frequent rate limit 429 errors](/ecosystem/api/toncenter/rate-limit).\n\nAlternative API clients and their configuration options can be supplied per network:\n\n```ts\n// Or @ton/appkit-react for React\nimport { AppKit, Network } from '@ton/appkit';\n\nconst kit = new AppKit({\n  // Configure networks and API clients.\n  networks: {\n    // Mainnet is TON's production network.\n    // All contracts and funds are real.\n    [Network.mainnet().chainId]: {\n      apiClient: {\n        // Most commonly used, official API client.\n        url: 'https://toncenter.com',\n\n        // A key to access higher RPS limits.\n        // Get it from https://t.me/toncenter\n        key: '<MAINNET_API_KEY>',\n      },\n    },\n  },\n});\n```\n\n### Connectors\n\nThe [basic setup](#initialization) allows for direct API requests but is insufficient for connecting TON wallets via the TON Connect protocol. For that, configure a connector and host a public [app manifest file](/ecosystem/ton-connect/manifest#app-manifest) adjusted to the needs of a given dApp.\n\nFor local development and testing, use the [manifest file from this demo dApp](https://tonconnect-sdk-demo-dapp.vercel.app/tonconnect-manifest.json).\n\n<CodeGroup>\n  ```tsx title=\"React\" icon=\"react\" expandable\n  import {\n    AppKit,\n    AppKitProvider,\n    // Enables TON wallet connections\n    TonConnectConnector,\n  } from '@ton/appkit-react';\n  import '@ton/appkit-react/styles.css';\n\n  const kit = new AppKit({\n    connectors: [\n      new TonConnectConnector({\n        tonConnectOptions: {\n          // Public link to the application manifest JSON file.\n          // For local development and testing, use the one from a demo dApp:\n          manifestUrl: 'https://tonconnect-sdk-demo-dapp.vercel.app/tonconnect-manifest.json',\n        },\n      }),\n    ],\n  });\n\n  // Wrap application in `AppKitProvider` and pass the `AppKit` instance.\n  export function App() {\n    return <AppKitProvider appKit={kit}>{/* ...app... */}</AppKitProvider>;\n  };\n  ```\n\n  ```ts title=\"TypeScript\" icon=\"globe\" expandable\n  import {\n    AppKit,\n    // Enables TON wallet connections\n    TonConnectConnector,\n  } from '@ton/appkit';\n\n  const kit = new AppKit({\n    connectors: [\n      new TonConnectConnector({\n        tonConnectOptions: {\n          // Public link to the application manifest JSON file.\n          // For local development and testing, use the one from a demo dApp:\n          manifestUrl: 'https://tonconnect-sdk-demo-dapp.vercel.app/tonconnect-manifest.json',\n        },\n      }),\n    ],\n  });\n  ```\n</CodeGroup>\n\n### Providers\n\nThe [setup with connectors](#connectors) connects to TON wallets via services such as [Tonkeeper](/ecosystem/wallet-apps/tonkeeper). To enable advanced DeFi operations like asset swaps, configure DeFi providers.\n\n[Omniston](https://ston.fi/omniston) is the primary swap provider. To set it up:\n\n<Steps>\n  <Step\n    title=\"Install the SDK\"\n  >\n    ```shell\n    npm i @ston-fi/omniston-sdk\n    ```\n  </Step>\n\n  <Step\n    title=\"Set up the swap provider\"\n  >\n    ```ts\n    // Or @ton/appkit-react for React\n    import { AppKit, Network } from '@ton/appkit';\n\n    // Omniston as a swap provider\n    import { OmnistonSwapProvider } from '@ton/appkit/swap/omniston';\n\n    const kit = new AppKit({\n      // Set up a swap provider\n      providers: [new OmnistonSwapProvider({\n        /* custom configuration options */\n      })],\n    });\n    ```\n  </Step>\n</Steps>\n\n### Queries and mutations\n\n[TanStack Query](https://tanstack.com/query/latest) is an opinionated library that simplifies fetching, caching, synchronizing and updating server state in web applications.\n\nTo enable [it for React](https://tanstack.com/query/latest/docs/framework/react/overview), wrap the application inside `AppKitProvider` in the `QueryClientProvider` from `@tanstack/react-query`:\n\n```tsx\n// Additional imports\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\n\n// Query client\nconst queryClient = new QueryClient({\n  defaultOptions: {\n    queries: {\n      // Do not refetch when window is refocused\n      refetchOnWindowFocus: false,\n    },\n  },\n});\n\n// ...AppKit initialization as shown prior...\n\n// Modified entrypoint\nexport function App() {\n  return (\n    <AppKitProvider appKit={kit}>\n      <QueryClientProvider client={queryClient}>\n        {/* ...app... */}\n      </QueryClientProvider>\n    </AppKitProvider>\n  );\n}\n```\n\n### Complete setup\n\nThe following initialization example sets up everything at once:\n\n<CodeGroup>\n  ```tsx title=\"React\" icon=\"react\"\n  // AppKit\n  import {\n    AppKit,\n    AppKitProvider,\n    Network,\n    // Wallet connector\n    TonConnectConnector,\n  } from '@ton/appkit-react';\n\n  // Styles\n  import '@ton/appkit-react/styles.css';\n\n  // DeFi provider\n  import { OmnistonSwapProvider } from '@ston-fi/omniston-sdk';\n\n  // TanStack Query\n  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';\n\n  // Query client\n  const queryClient = new QueryClient({\n    defaultOptions: {\n      queries: {\n        // Do not refetch when window is refocused\n        refetchOnWindowFocus: false,\n      },\n    },\n  });\n\n  // Initialization\n  const kit = new AppKit({\n    // 1. Configure networks and API clients.\n    networks: {\n      // Production network. All contracts and funds are real.\n      [Network.mainnet().chainId]: {\n        apiClient: {\n          // Most commonly used, official API client.\n          url: 'https://toncenter.com',\n\n          // A key to access higher RPS limits.\n          // Get it from https://t.me/toncenter\n          key: '<MAINNET_API_KEY>',\n        },\n      },\n    },\n    // 2. Configure connectors.\n    connectors: [\n      // Enables connections with TON wallet services, such as Tonkeeper or MyTonWallet.\n      new TonConnectConnector({\n        tonConnectOptions: {\n          // Public link to the application manifest JSON file.\n          // For local development and testing, use the one from a demo dApp:\n          manifestUrl: 'https://tonconnect-sdk-demo-dapp.vercel.app/tonconnect-manifest.json',\n        },\n      }),\n    ],\n    // 3. Configure DeFi providers.\n    providers: [new OmnistonSwapProvider()],\n  });\n\n  // 4. Wrap the rest of the app in a QueryClientProvider and an AppKitProvider.\n  export function App() {\n    return (\n      <AppKitProvider appKit={kit}>\n        <QueryClientProvider client={queryClient}>\n          {/* ...app... */}\n        </QueryClientProvider>\n      </AppKitProvider>\n    )\n  };\n  ```\n\n  ```ts title=\"TypeScript\" icon=\"globe\"\n  // AppKit\n  import {\n    AppKit,\n    Network,\n    // Wallet connector\n    TonConnectConnector,\n  } from '@ton/appkit';\n\n  // DeFi provider\n  import { OmnistonSwapProvider } from '@ston-fi/omniston-sdk';\n\n  // Initialization\n  const kit = new AppKit({\n    // 1. Configure networks and API clients.\n    networks: {\n      // Production network. All contracts and funds are real.\n      [Network.mainnet().chainId]: {\n        apiClient: {\n          // Most commonly used, official API client.\n          url: 'https://toncenter.com',\n\n          // A key to access higher RPS limits.\n          // Get it from https://t.me/toncenter\n          key: '<MAINNET_API_KEY>',\n        },\n      },\n    },\n    // 2. Configure connectors.\n    connectors: [\n      // Enables connections with TON wallet services, such as Tonkeeper or MyTonWallet.\n      new TonConnectConnector({\n        tonConnectOptions: {\n          // Public link to the application manifest JSON file.\n          // For local development and testing, use the one from a demo dApp:\n          manifestUrl: 'https://tonconnect-sdk-demo-dapp.vercel.app/tonconnect-manifest.json',\n        },\n      }),\n    ],\n    // 3. Configure DeFi providers.\n    providers: [new OmnistonSwapProvider()],\n  });\n  ```\n</CodeGroup>\n\n## Dynamic configuration\n\nAppKit instance can be dynamically extended with new [connectors](#connectors) and [providers](#providers).\n\n### Add new connectors\n\nTo add a new connector, call the `.addConnector()` method on the initialized AppKit object:\n\n```ts\nkit.addConnector(connector);\n```\n\n### Add new providers\n\nTo add a new provider, call the `.registerProvider()` method on the initialized AppKit object:\n\n```ts\nkit.registerProvider(provider);\n```\n\nTo specifically add a swap provider, register it via `kit.swapManager`:\n\n```ts\nkit.swapManager.registerProvider(swapProvider);\n```\n\n## Configuration parameters\n\n<ParamField\n  path=\"networks\"\n  type=\"Record<CHAIN, NetworkConfig>\"\n>\n  For one or more TON networks, configure their respective API or RPC providers to interact with.\n\n  ```ts title=\"TypeScript\" icon=\"globe\"\n  // Or @ton/appkit-react for React\n  import { Network } from '@ton/appkit';\n\n  new AppKit({\n    networks: {\n      // Production network. All contracts and funds are real.\n      [Network.mainnet().chainId]: { // \"-239\"\n        apiClient: {\n          // Most commonly used, official API client.\n          //\n          // To self-host, see:\n          // * Real-time API: https://github.com/toncenter/ton-http-api-cpp\n          // * Indexer: https://github.com/toncenter/ton-indexer\n          // It is important to put real-time API under `/api/v2` route and indexer API under `/api/v3` route.\n          url: 'https://toncenter.com',\n\n          // Optional key to access higher RPS limits.\n          key: '<MAINNET_API_KEY>',\n        },\n      },\n      // Testing network. For experiments, beta tests, and feature previews.\n      [Network.testnet().chainId]: { // \"-3\"\n        apiClient: {\n          url: 'https://testnet.toncenter.com',\n          key: '<TESTNET_API_KEY>',\n        },\n      },\n    },\n    // ...later fields...\n  });\n  ```\n\n  It is also possible to provide an entirely custom provider with its own `ApiClient` interface implementation.\n\n  ```ts title=\"TypeScript\" icon=\"globe\"\n  // Or @ton/appkit-react for React\n  import { Network } from '@ton/appkit';\n\n  new AppKit({\n    networks: {\n      [Network.testnet().chainId]: { // \"-3\"\n        apiClient: /*  A complete ApiClient interface implementation */,\n      },\n    },\n    // ...later fields...\n  });\n  ```\n</ParamField>\n\n<ParamField\n  path=\"connectors\"\n  type=\"Connector[] | undefined\"\n>\n  Array of connectors that enable wallet connections. The primary connector is `TonConnectConnector`.\n\n  Each connector must expose the following methods:\n\n  - `initialize()` — creates the connector, restores connections, sets up event listeners.\n  - `destroy()` — cleans up connector resources.\n  - `connectWallet()` — connects a wallet through the UI.\n  - `disconnectWallet()` — disconnects a wallet.\n  - `getConnectedWallets()` — lists connected wallets.\n\n  Additionally, each connector has metadata that can be displayed in the UI:\n\n  ```ts\n  interface ConnectorMetadata {\n    /**\n     * Connector name\n     */\n    name: string;\n    /**\n     * Connector icon URL\n     */\n    iconUrl?: string;\n  }\n  ```\n</ParamField>\n\n<ParamField\n  path=\"providers\"\n  type=\"Providers[] | undefined\"\n>\n  Array of DeFi providers that enable additional functionality, such as asset swaps via [Omniston](https://ston.fi/omniston).\n</ParamField>\n\n## Relation to TON Connect libraries\n\nLower-level TON Connect libraries, such as `@tonconnect/ui-react` and `@tonconnect/ui`, only give access to wallet services via the TON Connect protocol and basic facilities to query connected TON wallets with direct API calls.\n\nAppKit builds on the foundation provided by these libraries and extends functionality with convenient components, hooks, and functions. It enables balance tracking and asset management, gives ready-made React UI components for common cases, handles API-related state management, and even registers DeFi integrations for advanced use cases.\n\nIf there is an existing dApp that uses either `@tonconnect/ui-react` or `@tonconnect/ui`, consider migrating to AppKit to simplify development and reduce boilerplate.\n\n### Migrate from `@tonconnect/ui-react`\n\nBefore migrating, [install AppKit and peer packages](#installation) and add necessary polyfills.\n\n<Steps>\n  <Step\n    title=\"Ensure the TON Connect UI package is of the latest version\"\n  >\n    Ensure that TON Connect packages are of the latest version:\n\n    ```shell\n    npm up @tonconnect/ui-react --save\n    ```\n  </Step>\n\n  <Step\n    title=\"Initialize AppKit and replace TonConnectUIProvider\"\n  >\n    Use `AppKitProvider` in place of the `TonConnectUIProvider`:\n\n    ```tsx\n    import {\n      AppKit,\n      // Replaces <TonConnectUIProvider>\n      AppKitProvider,\n      // Wallet connector\n      TonConnectConnector,\n    } from '@ton/appkit-react';\n    import '@ton/appkit-react/styles.css';\n\n    const kit = new AppKit({\n      connectors: [\n        new TonConnectConnector({\n          // In place of props on the TonConnectUIProvider\n          tonConnectOptions: {\n            // Public link to the application manifest JSON file.\n            // For local development and testing, use the one from a demo dApp:\n            manifestUrl: 'https://tonconnect-sdk-demo-dapp.vercel.app/tonconnect-manifest.json',\n          },\n        }),\n      ],\n    });\n\n    export function App() {\n      return (\n        // In place of the TonConnectUIProvider\n        <AppKitProvider appKit={kit}>\n          {/* ...rest of the app... */}\n        </AppKitProvider>\n      );\n    }\n    ```\n\n    Refer to the [complete initialization setup](#complete-setup) for all the possible AppKit configuration options.\n  </Step>\n\n  <Step\n    title=\"Keep existing hooks as is\"\n  >\n    The `AppKitProvider` bridges to TON Connect under the hood. Existing few `@tonconnect/ui-react` hooks, such as `useTonAddress()`, `useTonWallet()`, and others, will continue to work inside the `AppKitProvider` automatically.\n  </Step>\n</Steps>\n\n### Migrate from `@tonconnect/ui`\n\nBefore migrating, [install AppKit and peer packages](#installation) and add necessary polyfills.\n\n<Steps>\n  <Step\n    title=\"Ensure the TON Connect UI package is of the latest version\"\n  >\n    ```shell\n    npm up @tonconnect/ui --save\n    ```\n  </Step>\n\n  <Step\n    title=\"Initialize AppKit and reuse TonConnectUI object\"\n  >\n    It is possible to reuse the existing `TonConnectUI` object when configuring AppKit [connectors](#connectors):\n\n    ```ts\n    import {\n      AppKit,\n      TonConnectConnector,\n    } from '@ton/appkit';\n\n    const kit = new AppKit({\n      connectors: [\n        new TonConnectConnector({\n          // Pass the existing TonConnectUI instance object\n          tonConnectUI\n        }),\n      ]\n    });\n    ```\n\n    One can also extend the existing AppKit instance dynamically:\n\n    ```ts\n    // Passing the existing TonConnectUI instance object\n    kit.addConnector(new TonConnectConnector({ tonConnectUI }));\n    ```\n\n    Refer to the [complete initialization setup](#complete-setup) for all the possible AppKit configuration options.\n  </Step>\n\n  <Step\n    title=\"Replace method calls with exported functions\"\n  >\n    Instead of consolidating everything within the instantiated `TonConnectUI` object, AppKit offers several tree-shakable functions that enhance and expand the capabilities of the existing `TonConnectUI` functionality. Refer to [relevant how-to pages](/ecosystem/appkit/overview#quick-start) for concrete examples.\n  </Step>\n</Steps>\n\n## Next steps\n\n<Columns cols={2}>\n  <Card\n    title=\"Work with Toncoin\"\n    icon=\"gem\"\n    horizontal=\"true\"\n    href=\"/ecosystem/appkit/toncoin\"\n  />\n</Columns>\n\n## See also\n\n- [AppKit overview](/ecosystem/appkit/overview)\n- [TON Connect's app manifest](/ecosystem/ton-connect/manifest#app-manifest)\n- [TON Connect overview](/ecosystem/ton-connect/overview)\n"
  },
  {
    "path": "ecosystem/appkit/jettons.mdx",
    "content": "---\ntitle: \"How to work with Jettons using AppKit\"\nsidebarTitle: \"Work with Jettons\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside>\n  [Initialize the AppKit](/ecosystem/appkit/init) before using examples on this page.\n</Aside>\n\n[Jettons](/standard/tokens/jettons/overview) are fungible tokens on TON, similar to ERC-20 tokens on Ethereum. Unlike Toncoin, which is the native TON currency used in all transfers, each jetton has a separate master (minter) contract and an individual wallet contract for each holder.\n\nFor example, USDT on TON is implemented as a jetton, and its minter contract address is `EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs`. By providing this address and the recipient's TON wallet contract address, AppKit knows which tokens to send and to whom.\n\n<Aside type=\"note\">\n  To deploy and mint a new jetton on the mainnet without writing code, use the dedicated official tool: [TON MINTER](https://minter.ton.org).\n</Aside>\n\n## Metadata\n\nRetrieve metadata about a specific jetton, such as its name, symbol, and decimals:\n\n<CodeGroup>\n  ```tsx title=\"React\" icon=\"react\"\n  import { useJettonInfo } from '@ton/appkit-react';\n\n  export const JettonCard = ({ jettonAddress }) => {\n    const {\n      data: info,\n      isLoading,\n      error,\n    } = useJettonInfo({\n      // Jetton master (minter) contract address\n      address: jettonAddress,\n    });\n\n    if (isLoading) {\n      return <div>Loading...</div>;\n    }\n\n    if (error) {\n      return <div>Error: {error.message}</div>;\n    }\n\n    return (\n      <div>\n        <p><em>Jetton info</em></p>\n        <p>Name: {info?.name}</p>\n        <p>Symbol: {info?.symbol}</p>\n        <p>Decimals: {info?.decimals}</p>\n      </div>\n    );\n  };\n  ```\n\n  ```ts title=\"TypeScript\" icon=\"globe\"\n  import { type AppKit, getJettonInfo } from '@ton/appkit';\n\n  async function fetchJettonInfo(\n    /** Initialized AppKit instance */\n    kit: AppKit,\n    /** Jetton master (minter) contract address */\n    jettonAddress: string,\n  ) {\n    const info = await getJettonInfo(kit, {\n      address: jettonAddress,\n    });\n    console.log('Jetton info:', info);\n  }\n  ```\n</CodeGroup>\n\n### Jetton wallet address\n\nEach jetton holder has a dedicated jetton wallet contract. To resolve its address for a given owner:\n\n<CodeGroup>\n  ```tsx title=\"React\" icon=\"react\" expandable\n  import {\n    useJettonWalletAddress,\n    useSelectedWallet,\n  } from '@ton/appkit-react';\n\n  export const JettonWalletAddressCard = ({ jettonAddress }) => {\n    const [wallet, _] = useSelectedWallet();\n    const {\n      data: walletAddress,\n      isLoading,\n      error,\n    } = useJettonWalletAddress({\n      // TON wallet address of the jetton holder\n      ownerAddress: wallet?.getAddress() ?? '<TON_WALLET_ADDRESS>',\n\n      // Jetton master (minter) contract address\n      jettonAddress,\n    });\n\n    if (isLoading) {\n      return <div>Loading...</div>;\n    }\n\n    if (error) {\n      return <div>Error: {error.message}</div>;\n    }\n\n    return <div>Jetton wallet address: {walletAddress?.toString()}</div>;\n  };\n  ```\n\n  ```ts title=\"TypeScript\" icon=\"globe\" expandable\n  import {\n    type AppKit,\n    getJettonWalletAddress,\n    getSelectedWallet,\n  } from '@ton/appkit';\n\n  async function fetchJettonWalletAddress(\n    /** Initialized AppKit instance */\n    kit: AppKit,\n    /** Jetton master (minter) contract address */\n    jettonAddress: string,\n  ) {\n    const selectedWallet = getSelectedWallet(kit);\n    const address = await getJettonWalletAddress(kit, {\n      jettonAddress,\n      // TON wallet address of the jetton holder\n      ownerAddress: selectedWallet?.getAddress() ?? '<TON_WALLET_ADDRESS>',\n    });\n    console.log('Jetton wallet address:', address);\n  }\n  ```\n</CodeGroup>\n\n## Balance\n\nSimilar to Toncoin balance checks, [discrete one-off checks](#on-demand-balance-check) have limited value on their own and [continuous monitoring](#continuous-balance-monitoring) should be used for UI display.\n\nUnlike Toncoin, the balance units and decimal places vary between jettons — use the `decimals` field from the [jetton's metadata](#metadata) to interpret raw amounts correctly.\n\nUSDT has a decimal precision of 6, meaning that the fractional balance string `'0.1'` represents a balance of 0.1 USDT, or 100000 micro USDT (raw units).\n\n### On-demand balance check\n\n<Aside\n  type=\"caution\"\n>\n  Do not store the balance check results anywhere in the wallet service's state, as they become outdated quickly. For UI purposes, do [continuous balance monitoring](#continuous-balance-monitoring).\n</Aside>\n\n#### Single jetton\n\nCheck the balance of a specific jetton for the connected TON wallet or an arbitrary address:\n\n<CodeGroup>\n  ```tsx title=\"React\" icon=\"react\"\n  import {\n    useJettonBalanceByAddress,\n    useSelectedWallet,\n  } from '@ton/appkit-react';\n\n  export const JettonBalanceCard = ({ jettonAddress }) => {\n    const [wallet, _] = useSelectedWallet();\n    const {\n      data: balance,\n      isLoading,\n      error,\n    } = useJettonBalanceByAddress({\n      // TON wallet address of the jetton holder\n      ownerAddress: wallet?.getAddress() ?? '<TON_WALLET_ADDRESS>',\n\n      // Jetton master (minter) contract address\n      jettonAddress,\n\n      // Jetton decimals to calculate raw unit amounts\n      jettonDecimals: 6,\n    });\n\n    if (isLoading) {\n      return <div>Loading...</div>;\n    }\n\n    if (error) {\n      return <div>Error: {error.message}</div>;\n    }\n\n    return <div>Jetton balance: {balance ?? '0'}</div>;\n  };\n  ```\n\n  ```ts title=\"TypeScript\" icon=\"globe\"\n  import {\n    type AppKit,\n    getJettonBalance,\n    getSelectedWallet,\n  } from '@ton/appkit';\n\n  async function fetchJettonBalance(\n    /** Initialized AppKit instance */\n    kit: AppKit,\n    /** Jetton master (minter) contract address */\n    jettonAddress: string,\n    /** Jetton decimals to calculate raw unit amounts */\n    jettonDecimals: number = 6,\n  ) {\n    const selectedWallet = getSelectedWallet(kit);\n    const balance = await getJettonBalance(kit, {\n      jettonAddress,\n      // TON wallet address of the jetton holder\n      ownerAddress: selectedWallet?.getAddress() ?? '<TON_WALLET_ADDRESS>',\n    });\n    console.log('Jetton balance:', balance ?? '0');\n  }\n  ```\n</CodeGroup>\n\n#### All jettons\n\nRetrieve every jetton held by the connected TON wallet or an arbitrary address:\n\n<CodeGroup>\n  ```tsx title=\"React\" icon=\"react\"\n  import {\n    useJettonsByAddress,\n    useSelectedWallet,\n    // Helper function targeting the connected wallet\n    useJettons,\n  } from '@ton/appkit-react';\n\n  export const JettonListByAddress = () => {\n    const [wallet, _] = useSelectedWallet();\n    const {\n      data: jettons,\n      isLoading,\n      error,\n    } = useJettonsByAddress({\n      // TON wallet address of the jetton holder\n      address: wallet?.getAddress() ?? '<TON_WALLET_ADDRESS>',\n    });\n\n    // Alternatively, query the connected wallet directly\n    // const { data: jettons, isLoading, error } = useJettons();\n\n    if (isLoading) {\n      return <div>Loading...</div>;\n    }\n\n    if (error) {\n      return <div>Error: {error.message}</div>;\n    }\n\n    return (\n      <div>\n        <p>Jettons</p>\n        <ul>\n          {jettons?.jettons.map((jetton) => (\n            <li key={jetton.walletAddress}>\n              {jetton.info.name}: {jetton.balance ?? '0'}\n            </li>\n          ))}\n        </ul>\n      </div>\n    );\n  };\n  ```\n\n  ```ts title=\"TypeScript\" icon=\"globe\"\n  import {\n    type AppKit,\n    getJettonsByAddress,\n    getSelectedWallet,\n    // Helper function targeting the connected wallet\n    getJettons,\n  } from '@ton/appkit';\n\n  async function fetchJettonsByAddress(\n    /** AppKit instance */\n    kit: AppKit,\n  ) {\n    const selectedWallet = getSelectedWallet(kit);\n    const response = await getJettonsByAddress(kit, {\n      address: selectedWallet?.getAddress() ?? '<TON_WALLET_ADDRESS>',\n    });\n\n    // Alternatively, query the connected wallet directly\n    // const response = await getJettons();\n\n    console.log('Jettons by address:', response.jettons.length);\n    response.jettons.forEach((j) =>\n      console.log(`- ${j.info.name}: ${j.balance ?? '0'}`),\n    );\n  }\n  ```\n</CodeGroup>\n\n### Continuous balance monitoring\n\nPoll the balance at regular intervals to keep the displayed value up to date. Use an appropriate interval based on UX requirements — shorter intervals provide fresher data but increase API usage.\n\nModify the following example according to the application logic:\n\n<CodeGroup>\n  ```tsx title=\"React\" icon=\"react\"\n  import {\n    useJettonBalanceByAddress,\n    useSelectedWallet,\n  } from '@ton/appkit-react';\n\n  export const JettonBalanceCard = ({ jettonAddress }) => {\n    const [wallet, _] = useSelectedWallet();\n    const {\n      data: balance,\n      isLoading,\n      error,\n      refetch,\n    } = useJettonBalanceByAddress({\n      // TON wallet address of the jetton holder\n      ownerAddress: wallet?.getAddress() ?? '<TON_WALLET_ADDRESS>',\n\n      // Jetton master (minter) contract address\n      jettonAddress,\n    });\n\n    if (isLoading) {\n      return <div>Loading...</div>;\n    }\n\n    if (error) {\n      return (\n        <div>\n          <p>Error: {error.message}</p>\n          <button onClick={() => refetch()}>Try again</button>\n        </div>\n      );\n    }\n\n    return <div>Jetton balance: {balance ?? '0'}</div>;\n  };\n  ```\n\n  ```ts title=\"TypeScript\" icon=\"globe\" expandable\n  // Not runnable: implement the updateUI()\n  import {\n    type AppKit,\n    getJettonBalance,\n    getSelectedWallet,\n  } from '@ton/appkit';\n\n  /**\n   * Starts the monitoring of a specific jetton balance for the connected wallet,\n   * calling `onBalanceUpdate()` every `intervalMs` milliseconds\n   *\n   * @returns a function to stop monitoring\n   */\n  export function startJettonBalanceMonitoring(\n    kit: AppKit,\n    jettonAddress: string,\n    onBalanceUpdate: (balance: string) => void,\n    intervalMs: number = 10_000,\n  ): () => void {\n    let isRunning = true;\n\n    const poll = async () => {\n      while (isRunning) {\n        const selectedWallet = getSelectedWallet(kit);\n        if (selectedWallet) {\n          const balance = await getJettonBalance(kit, {\n            jettonAddress,\n            // TON wallet address of the jetton holder\n            ownerAddress: selectedWallet?.getAddress() ?? '<TON_WALLET_ADDRESS>',\n          });\n          onBalanceUpdate(balance);\n        }\n        await new Promise((resolve) => setTimeout(resolve, intervalMs));\n      }\n    };\n\n    // Start monitoring\n    poll();\n\n    // Return a cleanup function to stop monitoring\n    return () => {\n      isRunning = false;\n    };\n  }\n\n  // Usage\n  const stopMonitoring = startJettonBalanceMonitoring(\n    kit,\n    // Jetton master (minter) contract address\n    // E.g., USDT on TON mainnet:\n    'EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs',\n    // The updateUI() function is exemplary and should be replaced by\n    // an app function that refreshes the state of the balance displayed\n    // in the interface\n    (balance) => updateUI(balance),\n  );\n\n  // Stop monitoring once it is no longer needed\n  stopMonitoring();\n  ```\n</CodeGroup>\n\n## Transfers\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  Each jetton stores the `decimals` parameter in its [metadata](#metadata). Transferring without accounting for decimals can result in sending drastically more or fewer tokens than intended.\n\n  Mitigation: Verify the correct `decimals` value before calculating transfer amounts. For USDTs, the decimals value is 6.\n</Aside>\n\nModify the following examples according to the application logic:\n\n<CodeGroup>\n  ```tsx title=\"React (component)\" icon=\"react\"\n  // Pre-built UI component for sending jetton transactions by clicking a button.\n  // It handles success and error states while being customizable.\n  import { SendJettonButton } from '@ton/appkit-react';\n\n  export const SendJetton = () => {\n    // For example: 'UQ...'\n    const recipientAddress = '<TON_WALLET_ADDRESS>';\n    // For example, '0.1' or '1' jetton\n    const jettonAmount = '<FRACTIONAL_JETTON_AMOUNT>';\n    // For example, 'EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs'\n    const jettonAddress = '<JETTON_MINTER_ADDRESS>';\n\n    return (\n      <SendJettonButton\n        // New owner of the sent jettons\n        recipientAddress={recipientAddress}\n\n        // Jetton amount in fractional units\n        amount={jettonAmount}\n\n        // What kind of jettons to send\n        jetton={{\n          // Jetton master (minter) contract address\n          address: jettonAddress,\n\n          // Short ticker name\n          symbol: 'USDT',\n\n          // Jetton decimals to calculate raw unit amounts\n          // For example, USDT defaults to 6, while Toncoin to 9:\n          decimals: 6,\n        }}\n\n        // (optional) Comment\n        comment=\"Hello from AppKit!\"\n\n        // (optional) Add custom button title\n        text=\"Send some jetton\"\n\n        // (optional) Handle successes\n        onSuccess={(result) => console.log('Transaction sent:', result)}\n\n        // (optional) Handle errors\n        onError={(error) => console.error('Transaction failed:', error)}\n\n        // (optional) Add custom CSS classes\n        className=''\n\n        // (optional) When set to `true`, the button is disabled\n        disabled={false}\n      />\n    );\n  };\n  ```\n\n  ```tsx title=\"React (hook)\" icon=\"react\"\n  import { useTransferJetton } from '@ton/appkit-react';\n\n  export const SendJetton = ({ recipientAddress, jettonAddress }) => {\n    const { mutate: transfer, isPending, error, data } = useTransferJetton();\n\n    const handleTransfer = () => {\n      transfer({\n        // New owner of the sent jettons.\n        // For example: 'UQ...'\n        recipientAddress,\n\n        // Jetton amount string in fractional units.\n        // For example, '0.1' or '1' jetton\n        amount: '<FRACTIONAL_JETTON_AMOUNT>',\n\n        // Jetton master (minter) contract address.\n        jettonAddress,\n\n        // Jetton decimals to calculate raw unit amounts.\n        // For example, USDT defaults to 6, while Toncoin to 9:\n        jettonDecimals: 6,\n\n        // (optional) Comment string. Defaults to none if not provided.\n        comment: 'Hello from AppKit!',\n      });\n    };\n\n    return (\n      <div>\n        <button onClick={handleTransfer} disabled={isPending}>\n          {isPending ? 'Transferring...' : 'Transfer jetton'}\n        </button>\n        {error && <div>Error: {error.message}</div>}\n        {data && (\n          <div>\n            <p>Transfer successful: {data.boc}</p>\n          </div>\n        )}\n      </div>\n    );\n  };\n  ```\n\n  ```ts title=\"TypeScript\" icon=\"globe\"\n  import {\n    type AppKit,\n    type Base64String,\n    // Single-call transfer\n    transferJetton,\n    // Two-step transfer: create a transaction object separately from sending it\n    createTransferJettonTransaction,\n    sendTransaction,\n  } from '@ton/appkit';\n\n  async function sendJetton(\n    /** Initialized AppKit instance */\n    kit: AppKit,\n    /** Recipient's TON wallet address as a string */\n    recipientAddress: string,\n    /**\n     * Jetton amount string in fractional units\n     * E.g., '0.1' or '1' jetton\n     */\n    amount: string,\n    /** Jetton decimals to calculate raw unit amounts */\n    jettonDecimals: number = 6,\n    /** Jetton master (minter) contract address */\n    jettonAddress: string,\n    /** Optional comment string */\n    comment?: string,\n  ) {\n    // Sign and send via TON Connect\n    const result = await transferJetton(kit, {\n      recipientAddress,\n      amount,\n      jettonDecimals,\n      jettonAddress,\n      ...(comment && { comment }),\n    });\n    console.log('Transaction sent:', result.boc);\n\n    // Alternatively, build the transaction first with createTransferJettonTransaction,\n    // then pass the resulting object to the sendTransaction function.\n  }\n  ```\n</CodeGroup>\n\n## See also\n\nJettons:\n\n- [Jettons overview](/standard/tokens/jettons/overview)\n- [Jetton transfers](/standard/tokens/jettons/transfer)\n- [Token metadata and decimals](/standard/tokens/metadata#decimals)\n\nGeneral:\n\n- [Transaction fees](/foundations/fees)\n- [AppKit overview](/ecosystem/appkit/overview)\n- [TON Connect overview](/ecosystem/ton-connect)\n"
  },
  {
    "path": "ecosystem/appkit/overview.mdx",
    "content": "---\ntitle: \"AppKit: SDK for decentralized applications (dApps)\"\nsidebarTitle: \"Overview\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nTON Connect's **AppKit** is an open-source SDK that integrates web2 and web3 applications with TON. It enables wallet connection, authorization, balance tracking, asset transfers, and data signing.\n\n<Aside\n  type=\"caution\"\n>\n  AppKit is currently in a public <Badge size=\"xs\">alpha</Badge> version. Some behaviors and APIs might change in the future.\n</Aside>\n\n## Features\n\n- TON Connect protocol compliance: integrate with the standard wallet infrastructure for TON.\n- Wallet management: access connected TON wallets from registered providers.\n- Asset support: work with Toncoin (TON), jettons (tokens, i.e., USDT), and NFTs.\n- React: use hooks and ready-made UI components for common cases.\n- DeFi: make on-chain Toncoin and jetton swaps through different providers.\n\n## Use cases\n\n- Web2 apps that need to use TON for authorization, payments, NFT rewards, or other common needs.\n- Web3 apps that need to integrate TON wallets.\n- Telegram Mini Apps that utilize TON Blockchain to provide services for Telegram users.\n\n## Quick start\n\n<Columns cols={3}>\n  <Card\n    title=\"Initialize the kit\"\n    icon=\"wrench\"\n    horizontal=\"true\"\n    href=\"/ecosystem/appkit/init\"\n  />\n\n  <Card\n    title=\"Work with Toncoin\"\n    icon=\"gem\"\n    horizontal=\"true\"\n    href=\"/ecosystem/appkit/toncoin\"\n  />\n\n  <Card\n    title=\"Work with Jettons\"\n    icon=\"coins\"\n    horizontal=\"true\"\n    href=\"/ecosystem/appkit/jettons\"\n  />\n</Columns>\n\n## See also\n\nThe [TON Connect overview](/ecosystem/ton-connect/overview) explains the protocol and its core concepts.\n\nSkim the reference pages with more in-depth information:\n\n- [TON Connect manifests](/ecosystem/ton-connect/manifest)\n- [`@tonconnect/protocol`, external API reference](https://ton-connect.github.io/sdk/modules/_tonconnect_protocol.html)\n"
  },
  {
    "path": "ecosystem/appkit/toncoin.mdx",
    "content": "---\ntitle: \"How to work with Toncoin using AppKit\"\nsidebarTitle: \"Work with Toncoin\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside>\n  [Initialize the AppKit](/ecosystem/appkit/init) before using examples on this page.\n</Aside>\n\n## Balance\n\nBlockchain state changes constantly as new blocks are produced. This has implications for when and how to check TON wallet contract balances:\n\n- [Discrete one-off checks](#on-demand-balance-check) have almost no value on their own — the state might change immediately after the query completes, invalidating its results. Thus, such checks are only practical when making outgoing transfers.\n- [Continuous monitoring](#continuous-balance-monitoring) is useful for UI display, showing the most recent balance to users, but should not be used for transaction confirmations.\n\nNotice that both cases require querying the blockchain data via the API client set during the [AppKit initialization](/ecosystem/appkit/init). Obtain and provide the key from the selected client to access higher requests-per-second limits.\n\n### On-demand balance check\n\nBalances are returned as strings representing fractional Toncoin units. For example, `'0.1'` is a balance of 0.1 Toncoin or 100000000 nanoToncoin. Decimal precision of Toncoin is 9 digits, so the smallest possible balance is `'0.000000001'` Toncoin or 1 nanoToncoin.\n\n<Aside\n  type=\"caution\"\n>\n  Do not store the balance check results anywhere in the wallet service's state, as they become outdated quickly. For UI purposes, do [continuous balance monitoring](#continuous-balance-monitoring).\n</Aside>\n\n<CodeGroup>\n  ```tsx title=\"React\" icon=\"react\"\n  import { useBalance } from '@ton/appkit-react';\n\n  export const BalanceCard = () => {\n    const { data: balance } = useBalance();\n\n    return (\n      <p>TON wallet balance in fractional Toncoin: {balance ?? '0'}</p>\n    );\n  };\n  ```\n\n  ```ts title=\"TypeScript\" icon=\"globe\"\n  import { getBalance } from '@ton/appkit';\n\n  const balance = await getBalance(kit);\n  if (balance) {\n    console.log('TON wallet balance in fractional Toncoin:', balance);\n  }\n  ```\n</CodeGroup>\n\n### Continuous balance monitoring\n\nPoll the balance at regular intervals to keep the displayed value up to date. Use an appropriate interval based on UX requirements — shorter intervals provide fresher data but increase API usage.\n\nModify the following examples according to the application logic:\n\n<CodeGroup>\n  ```tsx title=\"React\" icon=\"react\" expandable\n  import { useBalance } from '@ton/appkit-react';\n\n  export const BalanceCard = () => {\n    const {\n      data: balance,\n      isLoading: isBalanceLoading,\n      isError: isBalanceError,\n      refetch: onRefresh,\n    } = useBalance();\n\n    if (isBalanceError) {\n      return (\n        <div>\n          <p>Error retrieving balance</p>\n          <button onClick={() => onRefresh()}>Try again</button>\n        </div>\n      );\n    }\n\n    return (\n      <div>\n        {isBalanceLoading ? (\n          <p>Loading the balance...</p>\n        ) : (\n          <p>TON wallet balance in fractional Toncoin: {balance ?? '0'}</p>\n        )}\n      </div>\n    );\n  };\n  ```\n\n  ```ts title=\"TypeScript\" icon=\"globe\" expandable\n  // Not runnable: implement the updateUI()\n  import { type AppKit, getBalance } from '@ton/appkit';\n\n  /**\n   * Starts the monitoring of the currently connected wallet,\n   * calling `onBalanceUpdate()` every `intervalMs` milliseconds\n   *\n   * @returns a function to stop monitoring\n   */\n  export function startBalanceMonitoring(\n    kit: AppKit,\n    onBalanceUpdate: (balance: string) => void,\n    intervalMs: number = 10_000,\n  ): () => void {\n    let isRunning = true;\n\n    const poll = async () => {\n      while (isRunning) {\n        const balance = await getBalance(kit);\n        if (balance) {\n          onBalanceUpdate(balance);\n        }\n        await new Promise((resolve) => setTimeout(resolve, intervalMs));\n      }\n    };\n\n    // Start monitoring\n    poll();\n\n    // Return a cleanup function to stop monitoring\n    return () => {\n      isRunning = false;\n    };\n  }\n\n  // Usage\n  const stopMonitoring = startBalanceMonitoring(\n    kit,\n    // The updateUI() function is exemplary and should be replaced by\n    // an app function that refreshes the state of the balance displayed\n    // in the interface\n    (balance) => updateUI(balance),\n  );\n\n  // Stop monitoring once it is no longer needed\n  stopMonitoring();\n  ```\n</CodeGroup>\n\n## Transfers\n\nModify the following examples according to the application logic:\n\n<CodeGroup>\n  ```tsx title=\"React (component)\" icon=\"react\"\n  // Pre-built UI component for sending Toncoin transactions by clicking a button.\n  // It handles success and error states while being customizable.\n  import { SendTonButton } from '@ton/appkit-react';\n\n  export const SendToncoin = () => {\n    // For example: 'UQ...'\n    const recipientAddress = '<TON_WALLET_ADDRESS>';\n    // For example, '0.1' or '1' Toncoin.\n    const toncoin = '<FRACTIONAL_AMOUNT>';\n\n    return (\n      <SendTonButton\n        // Where to send Toncoin to\n        recipientAddress={recipientAddress}\n\n        // Toncoin amount\n        amount={toncoin}\n\n        // (optional) Comment string\n        comment=\"Hello from AppKit!\"\n\n        // (optional) Add custom button title\n        // Defaults to Send X TON, where X is Toncoin amount\n        text=\"Send TON\"\n\n        // (optional) Handle successes\n        onSuccess={(result) => console.log('Transaction sent:', result)}\n\n        // (optional) Handle errors\n        onError={(error) => console.error('Transaction failed:', error)}\n\n        // (optional) Add custom CSS classes\n        className=''\n\n        // (optional) When set to `true`, the button is disabled\n        disabled={false}\n      />\n    );\n  };\n  ```\n\n  ```tsx title=\"React (hook)\" icon=\"react\"\n  import { useTransferTon } from '@ton/appkit-react';\n\n  export const SendToncoin = () => {\n    const { mutate: transfer, isPending, error, data } = useTransferTon();\n\n    const handleTransfer = () => {\n      transfer({\n        // Where to send Toncoin to.\n        // For example: 'UQ...'\n        recipientAddress: '<TON_WALLET_ADDRESS>',\n\n        // Fractional Toncoin amount string.\n        // For example, '0.1' or '10' Toncoin.\n        amount: '<FRACTIONAL_AMOUNT>',\n\n        // (optional) Comment string. Defaults to none if not provided.\n        comment: 'Hello from AppKit!',\n\n        // (optional) Payload data encoded as a Base64 string.\n        //            Overrides the `comment`, if provided.\n        payload: '<PAYLOAD>',\n\n        // (optional) Initial state (code and data) for deploying a new contract,\n        //            encoded as a Base64 string\n        stateInit: '<STATE_INIT>',\n      });\n    };\n\n    return (\n      <div>\n        <button onClick={handleTransfer} disabled={isPending}>\n          {isPending ? 'Transferring...' : 'Transfer TON'}\n        </button>\n        {error && <div>Error: {error.message}</div>}\n        {data && (\n          <div>\n            <p>Transfer successful: {data.boc}</p>\n          </div>\n        )}\n      </div>\n    );\n  };\n  ```\n\n  ```ts title=\"TypeScript\" icon=\"globe\"\n  import {\n    type AppKit,\n    type Base64String,\n    // Single-call transfer\n    transferTon,\n    // Two-step transfer: create a transaction object separately from sending it\n    createTransferTonTransaction,\n    sendTransaction,\n  } from '@ton/appkit';\n\n  async function sendToncoin(\n    /** Initialized AppKit instance */\n    kit: AppKit,\n    /** Recipient's TON wallet address as a string */\n    recipientAddress: string,\n    /** Amount in fractional Toncoin */\n    amount: string,\n    /** Optional comment string */\n    comment?: string,\n    /** Optional payload body as a BoC in Base64-encoded string */\n    payload?: Base64String,\n    /**\n     * Optional initial state (code and data) for deploying a new contract,\n     * stored as a BoC in Base64-encoded string\n     */\n    stateInit?: Base64String,\n  ) {\n    // Sign and send via TON Connect\n    const result = await transferTon(kit, {\n      recipientAddress,\n      amount,\n      // Optional comment OR payload, not both\n      ...(comment && { comment }),\n      ...(payload && { payload }),\n      ...(stateInit && { stateInit }),\n    });\n    console.log('Transaction sent:', result.boc);\n\n    // Alternatively, build the transaction first with createTransferTonTransaction,\n    // then pass the resulting object to the sendTransaction function.\n  }\n  ```\n</CodeGroup>\n\n## Confirm transaction delivery\n\nTON achieves transaction [finality](https://en.wikipedia.org/wiki/Blockchain#Finality) after a single masterchain block confirmation, where new blocks are produced approximately every 3 seconds. Once a transaction appears in a masterchain block, it becomes irreversible.\n\nTherefore, to reliably confirm the transaction delivery and status, one needs to check whether a transaction has achieved masterchain finality using the selected API client. Applications should not block the UI while waiting for such confirmation. With [continuous balance monitoring](#continuous-balance-monitoring) and subsequent transaction requests, users will receive the latest information either way.\n\nConfirmations are only needed to reliably display a list of past transactions, including the most recent ones. For detailed transaction tracking and message lookups, the [message lookup guide](/ecosystem/ton-connect/message-lookup) covers finding transactions by external message hash, waiting for confirmations, and applying message normalization.\n\n## Next steps\n\n<Columns cols={2}>\n  <Card\n    title=\"Work with jettons\"\n    icon=\"coins\"\n    horizontal=\"true\"\n    href=\"/ecosystem/appkit/jettons\"\n  />\n</Columns>\n\n## See also\n\n- [Transaction fees](/foundations/fees)\n- [AppKit overview](/ecosystem/appkit/overview)\n- [TON Connect overview](/ecosystem/ton-connect)\n"
  },
  {
    "path": "ecosystem/bridges.mdx",
    "content": "---\ntitle: \"Bridges\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nIn the TON ecosystem, bridges allow users to transfer assets and data between TON and other major blockchains like Ethereum, BNB Chain, and Polygon.\n\nIn this article, we will explore cross-chain bridges on TON.\n\n## What are Cross-Chain Bridges?\n\nCross-chain bridges are protocols that allow users to transfer cryptocurrencies, tokens, and sometimes arbitrary data from one blockchain to another. They act as connectors between otherwise isolated blockchain networks, enabling a multi-chain ecosystem where assets can move freely across different platforms.\n\nBridges typically work by locking assets on the source blockchain and minting equivalent wrapped tokens on the destination blockchain. When users want to move assets back, the wrapped tokens are burned on the destination chain, and the original assets are unlocked on the source chain.\n\n### Types of Cross-Chain Bridges\n\n#### 1. Trustless vs. Custodial Bridges\n\nTrustless Bridges:\n\n- Use smart contracts and cryptographic proofs for validation\n- No single point of failure\n- Decentralized verification mechanisms\n\nCentralized Bridges:\n\n- Rely on trusted entities or multi-signature wallets\n- Single point of failure risk\n- Generally, they are easier to implement\n\n#### 2. Asset Transfer Methods\n\nLock-and-Mint Bridges:\n\n- Lock original assets on the source chain\n- Mint wrapped tokens on the destination chain\n- Most common bridge type\n\nBurn-and-Mint Bridges:\n\n- Burn tokens on the source chain\n- Mint new tokens on the destination chain\n- Used for native multi-chain tokens\n\n## Bridges on TON\n\nThe TON blockchain has a bridge ecosystem that connects it to major EVM-compatible networks. There are several kinds of bridge providers on TON.\n\n### Legacy: Official TON Bridges\n\n<Aside\n  type=\"caution\"\n>\n  During the early development of TON ecosystem (2021-2023) there were a few official TON bridges, supported at the protocol level. Now, they are considered legacy and not recommended for usage since they can be deprecated at any moment.\n</Aside>\n\nTON blockchain supports several official bridges configured at the protocol level:\n\n#### Outbound Bridges (Config parameters 71-73)\n\nThese bridges wrap TON into other networks:\n\n- **ETH-TON Bridge** ([Config Parameter 71](/foundations/config#param-71-73%3A-outbound-bridges))\n- **BNB-TON Bridge** ([Config Parameter 72](/foundations/config#param-71-73%3A-outbound-bridges))\n- **Polygon-TON Bridge** ([Config Parameter 73](/foundations/config#param-71-73%3A-outbound-bridges))\n\n#### Inbound Bridges (Config parameters 79, 81-82)\n\nThese bridges wrap tokens from other networks into TON:\n\n- **ETH-TON Bridge** ([Config Parameter 79](/foundations/config#param-79%2C-81-and-82%3A-inbound-bridges))\n- **BNB-TON Bridge** ([Config Parameter 81](/foundations/config#param-79%2C-81-and-82%3A-inbound-bridges))\n- **Polygon-TON Bridge** ([Config Parameter 82](/foundations/config#param-79%2C-81-and-82%3A-inbound-bridges))\n\nYou can read more about these bridge configuration parameters on the [TON Config page](/foundations/config).\n\n### Third-Party Bridge Ecosystem\n\nThe TON ecosystem features multiple bridge providers offering different features and supported networks. You can read more about them in [TON Bridges page](https://ton.org/en/bridges).\n\nYou can see existing bridges statistics on [TON Foundation Bridge Dashboard](https://dune.com/ton_foundation/bridges).\n"
  },
  {
    "path": "ecosystem/explorers/overview.mdx",
    "content": "---\ntitle: \"Overview\"\n---\n\nExplorers are web tools for reading blockchain data. They let you look up accounts, transactions, blocks, and smart contracts, making it easy to verify activity and debug issues.\n\n### Explorer\n\nA blockchain explorer is a website that indexes on‑chain data and presents it in a searchable user interface (UI). In TON, explorers commonly show account balances, recent transactions, jettons and non‑fungible tokens (NFTs), contract code and state, and links to related blocks and messages.\n\n### What explorers show\n\n- Balances and assets: TON, jettons, and NFTs held by an address\n- Transactions and messages: history, fees, phases, and traces\n- Blocks and validators: block contents, masterchain and shardchain details\n- Smart contracts: code, state, disassembly, and known contract type\n- Analytics: top entities, volumes, gas, fees, and network health\n\n### Indexers\n\nIndexers continuously read blocks from nodes, parse messages and transactions, and store them in a database optimized for queries. Explorers rely on these indexers to provide fast search, traces, higher‑level events, and historical views beyond what a single node exposes by default.\n\n### Explorers comparison\n\n| Explorer     | Type            | Mainnet                                               | Testnet                                      | Official |\n| ------------ | --------------- | ----------------------------------------------------- | -------------------------------------------- | -------- |\n| Tonviewer    | General‑purpose | [tonviewer.com](https://tonviewer.com/)               | [Testnet](https://testnet.tonviewer.com/)    | No       |\n| Tonscan.org  | General‑purpose | [tonscan.org](https://tonscan.org/)                   | [Testnet](https://testnet.tonscan.org/)      | No       |\n| Tonscan.com  | General‑purpose | [tonscan.com](https://tonscan.com/)                   | -                                            | No       |\n| TON Explorer | Low‑level/core  | [explorer.toncoin.org](https://explorer.toncoin.org/) | [Testnet](https://test-explorer.toncoin.org) | Yes      |\n\n> Official: maintained by the TON Foundation or an affiliated team\n\nThe [verifier tool](https://verifier.ton.org/) powers contract code verification.\n"
  },
  {
    "path": "ecosystem/explorers/tonviewer.mdx",
    "content": "---\ntitle: \"Using Tonviewer\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\nimport { Image } from '/snippets/image.jsx';\n\nTonviewer is a TON Blockchain explorer that allows you to inspect blocks, transactions, contracts, and tokens, as well as analyze activity.\n\n## High-level entities\n\nHigh-level entities provide the foundation for exploring TON Blockchain, understanding and tracking operations.\nThey are essential for identifying transactions and tracing data flow across the network.\n\n- [Accounts](/foundations/status) — the primary entities representing actors on the blockchain.\n- [Addresses](/foundations/addresses/overview) — unique identifiers for accounts, showing balances and activity in Tonviewer.\n- [Messages](/foundations/messages/overview) — instructions sent between addresses. In explorers, they reveal what actions are initiated and how they lead to transactions.\n- [Transactions](/foundations/messages/ordinary-tx) — records of executed messages. Explorers display their details linked to a specific address.\n- Blocks — containers of transactions. In explorers, they expose block metadata and configuration parameters, allowing you to trace activity and understand how the blockchain operates.\n\n## Reading traces\n\n### Traces\n\nIn Tonviewer, operations are visualized through traces.\nA trace is a directed acyclic graph (DAG) where:\n\n- transactions are nodes on an account's address\n- messages are edges between addresses\n\n<Image\n  src=\"/resources/images/tonviewer/trace.svg\"\n  darkSrc=\"/resources/images/tonviewer/trace-dark.svg\"\n  alt=\"Trace overview\"\n/>\n\n### Using the UI\n\nTonviewer provides a visual interface for exploring traces:\n\n- Hover over a \"node\" to see details about the account where a transaction succeeded or failed.\n- Hover over an \"edge\" to inspect the message contents.\n- Use \"Show details\" to examine full transaction and message information.\n\n<Aside>\n  The UI may change, but the approach to reading traces remains consistent.\n</Aside>\n\n<Image\n  src=\"/resources/images/tonviewer/ui-overview.png\"\n  darkSrc=\"/resources/images/tonviewer/ui-overview-dark.png\"\n  alt=\"UI overview\"\n/>\n\n### Steps to read a trace\n\n1. **Determine the operation**\n\nThe external-in message initiates the trace and defines the operation, such as a transfer, swap, or staking action.\n\n2. **Clarify accounts' roles**\n\nExamine the accounts involved — wallet addresses, jetton wallets, jetton master wallets, and DEX contracts. It clarifies the role of each account in the operation flow.\n\n3. **Read messages**\n\nExamine each message (edge in the trace). Its payload defines the intended actions and the transferred value:\n\n- value — amount of TON or jettons transferred\n- opcode — instruction type\n- payload — instructions\n\n4. **Check transaction phases**\n\nEach transaction executes in phases. In the compute and action phases, an exit code of 0 indicates success; a non-zero code signals an error. This identifies which action succeeded and which failed.\n\n5. **Find the failure point**\n\nSome failures can occur even if all transactions are successful. Examine messages and payloads to identify where an operation was constrained or prevented from proceeding.\n\n## Failed use cases\n\nThe following examples illustrate traces where operations did not complete as intended, even when transactions appear successful. They demonstrate a general approach to reading traces and identifying the point of failure.\n\n### Jetton transfer\n\nAnalyze a [jetton transfer](https://tonviewer.com/transaction/d5d50c3e5bde493ddc7853f784bdff75a37bf89473e77ba8d04615323c7c8117) attempt.\n\n<Image\n  src=\"/resources/images/tonviewer/jetton-transfer.png\"\n  darkSrc=\"/resources/images/tonviewer/jetton-transfer-dark.png\"\n  alt=\"Jetton transfer\"\n/>\n\n1. **Determine the operation**\n\nAt point **A** (mintmachine.ton), an external-in message initiates the operation, instructing _a jetton transfer_.\n\n2. **Clarify accounts' roles**\n\n- A — sender’s wallet contract (mintmachine.ton), initiates the transfer.\n- B — jetton wallet contract governed by the jetton master, holds the tokens and executes the transfer.\n\n3. **Read messages**\n\n- A → B: jetton transfer message with 0.2 TON attached to cover execution fees.\n\n4. **Check transaction phases**\n\nThe transaction at **B** failed during execution, with a non-zero exit code.\n\n5. **Find the failure point**\n\nExit code `48` per [jetton contract logic](https://github.com/ton-blockchain/jetton-contract/blob/main/contracts/op-codes.fc#L33) indicates that there isn't enough gas to complete the transfer.\nThe attached TON was insufficient to cover execution and forwarding, so the contract aborted the transfer.\n\n### NFT transfer\n\nAnalyze an [NFT transfer](https://tonviewer.com/transaction/d8b5dbfe1c115178f47b486d03982159ec8abe684cdbe1c75587293e877564d4) attempt.\n\n<Image\n  src=\"/resources/images/tonviewer/nft-transfer.png\"\n  darkSrc=\"/resources/images/tonviewer/nft-transfer-dark.png\"\n  alt=\"NFT transfer\"\n/>\n\n1. **Determine the operation**\n\nAt point **A** (address `UQDj…D0lN`), the user’s wallet sends an external-in message to _transfer an NFT_.\n\n2. **Clarify accounts' roles**\n\n- A — the user's wallet, initiates the transfer.\n- B — the NFT contract at address `EQCo…gJdV`, validates ownership and executes the transfer.\n\n3. **Read messages**\n\n- A → B: NFT transfer message with 0.04 TON attached.\n- B → A: bounce returning 0.036514 TON.\n\n4. **Check transaction phases**\n\nThe transaction at **B** failed in the compute phase, with an exit code of `401`.\n\n5. **Find the failure point**\n\nAccording to the [NFT standard](https://github.com/ton-blockchain/token-contract/blob/main/nft/nft-item.fc#L65), exit code `401`  means that the sender is not the owner of the NFT.\nBecause the ownership check failed, the contract rejected the transfer and returned the unused funds to **A**.\n\n### DEX swap\n\nAnalyze a [token swap](https://tonviewer.com/transaction/fa8e119f8911d20bb078b9b81a3fc1f8ff2bcc723eda3ac7e873e97f455812e7) attempt from **DYX** to **pTON**.\n\n<Image\n  src=\"/resources/images/tonviewer/dex-swap.png\"\n  darkSrc=\"/resources/images/tonviewer/dex-swap-dark.png\"\n  alt=\"DEX swap\"\n/>\n\n1. **Determine the operation**\n\nThe trace begins at point **A** (the user’s `mintmachine.ton` contract). An external-in message initiates the _token swap attempt_.\n\n2. **Clarify accounts' roles**\n\n- A — user's mintmachine.ton account, sending the initial funds.\n- B — user's jetton wallet, holds the tokens.\n- C — DEX jetton wallet, forwards tokens to the DEX.\n- D — DEX smart contract executing the swap.\n- E — jetton master (minter), authorizes token operations.\n\n3. **Read messages**\n\n- A → B: 0.3 TON transferred via a jetton transfer.\n- B → C: jetton internal transfer to the DEX wallet.\n- C → D: swap request sent to the DEX contract.\n- C → A: return of excess funds.\n- D → E: request to the jetton master.\n- E → D: reply with `exit_code: 962605456 (0x39603190)`.\n\n4. **Check transaction phases**\n\nTransactions in A, B, C, D, and E all completed with exit code 0. No phase errors were reported.\n\n5. **Find the failure point**\n\nThe issue appears in the payload of **E → D**. According to [STON.fi docs](https://docs.ston.fi/developer-section/dex/smart-contracts/v2/op-codes#transfer-exit-codes), the `exit_code: 962605456` corresponds to _Swap out token amount is less than provided minimum value_.\n\nThis explains why, despite all transactions succeeding, the swap reverted: the output did not satisfy the minimum slippage tolerance.\n\n## Successful use case\n\nAnalyze a [token swap](https://tonviewer.com/transaction/b1dce2881224590a7c60e61594c68bd477f84fe81519b373da8fbed9c0269565) from **REDO** to **TON**.\n\n<Image\n  src=\"/resources/images/tonviewer/dex-swap-successful.png\"\n  darkSrc=\"/resources/images/tonviewer/dex-swap-successful-dark.png\"\n  alt=\"DEX swap successful case\"\n/>\n\n1. **Determine the operation**\n\nAn **external-in** message arrives at point **A** (mintmachine.ton), initiating the _token swap_.\n\n2. **Clarify accounts' roles**\n\n- A — mintmachine.ton account, provides initial funds for the swap.\n- B — user's jetton wallet, holds the tokens.\n- C — DEX jetton wallet, forwards tokens to the DEX.\n- D — DEX smart contract executing the swap.\n- E — jetton master (minter), authorizes token operations.\n- F — DEX payout account (mergesort.t.me), receives the swapped tokens.\n\n3. **Read messages**\n\n- A → B: 0.2 TON transferred via a jetton transfer.\n- B → C: internal jetton transfer to the DEX wallet.\n- C → D: valid amount forwarded to the DEX contract for swap execution.\n- C → A: return of excess funds.\n- D → E: request to the jetton master (minter) to mint/settle token movements.\n- E → external-out: issues an **external-out message** — confirmation that the operation succeeded.\n- E → F: sends an internal message to the payout pool account.\n- F → A: forwards the swap result to the initiator (`mintmachine.ton`).\n\n4. **Check transaction phases**\n\nAll transactions along the trace completed their phases without error, no warning markers; exit codes are `0`. There are no bounces, failed compute or action phases reported in the nodes.\n\n5. **Find the failure point**\n\nNo failure point — the operation completed successfully.\n\n## Debugging with retracer\n\nSometimes, reading messages and transaction phases is not enough.\nA transaction may show _successful compute and action phases, exit codes of `0`, and no errors in messages_ — yet still produce no effect on-chain.\n\nIn such cases, you need to trace the **TVM execution path**.\n[Retracer](https://retracer.ton.org/) lets you replay the transaction and inspect what happened inside the virtual machine.\n\nSee [Debugging with TVM Retracer](/contract-dev/debug#debugging-with-tvm-retracer) for details.\n"
  },
  {
    "path": "ecosystem/nodes/cpp/integrating-with-prometheus.mdx",
    "content": "---\ntitle: \"Integrate MyTonCtrl with Prometheus\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\n\n[MyTonCtrl](/ecosystem/nodes/cpp/setup-mytonctrl) pushes metrics to a [Prometheus](https://prometheus.io/) [Pushgateway](https://prometheus.io/docs/instrumenting/pushing/) so Prometheus (and [Grafana](https://grafana.com/), if used) can scrape them without exposing the node directly.\n\n## Prerequisites\n\n- [Docker](https://www.docker.com/) and [Docker Compose](https://docs.docker.com/compose/) are installed on the host that runs Prometheus.\n- MyTonCtrl installed and running on the node that emits metrics.\n\n## Deploy Prometheus and Pushgateway\n\n1. In an empty directory, create `docker-compose.yml`:\n\n```yaml\nservices:\n pushgateway:\n   image: prom/pushgateway:v1.4.0\n   restart: unless-stopped\n   ports:\n     - \"9091:9091\"\n\n prometheus:\n   image: prom/prometheus:v2.52.0\n   restart: unless-stopped\n   volumes:\n     - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro\n   command:\n     - \"--config.file=/etc/prometheus/prometheus.yml\"\n   ports:\n     - \"9090:9090\"\n```\n\n1. Create `prometheus.yml` alongside it:\n\n```yaml\nglobal:\n scrape_interval: 15s\n\nscrape_configs:\n - job_name: \"mytonctrl_pushgateway\"\n   static_configs:\n     - targets: [\"pushgateway:9091\"]\n```\n\n1. Start the stack and confirm the container status:\n\n```bash\ndocker compose up -d\ndocker compose ps\n```\n\n## Configure MyTonCtrl to push metrics\n\n1. Open the MyTonCtrl console:\n\n```bash\nmytonctrl\n```\n\n2. Enable Prometheus mode:\n\n```bash\nMyTonCtrl> enable_mode prometheus\n```\n\n3. Point MyTonCtrl to the Pushgateway (include a job name):\n\n```bash\nMyTonCtrl> set prometheus_url http://<PUSHGATEWAY_HOST>:9091/metrics/job/<JOB_NAME>\n```\n\n`<PUSHGATEWAY_HOST>` — host running the Pushgateway (use `127.0.0.1` when MyTonCtrl and Docker run on the same machine).\n`<JOB_NAME>` — unique label for this node, for example `validator1`.\n\n<Aside\n  type=\"caution\"\n  title=\"Use unique job names\"\n>\n  Do not reuse the same `JOB_NAME` across nodes when scraped by one Prometheus instance, or metrics collide.\n</Aside>\n\n## Verify metrics\n\n- Pushgateway: open `http://<PUSHGATEWAY_HOST>:9091` and confirm metrics appear under `<JOB_NAME>`.\n- Prometheus targets: open `http://<PROMETHEUS_HOST>:9090/targets` and check that `mytonctrl_pushgateway` shows `UP`.\n- Prometheus graph: query `mytonctrl_synced` or other MyTonCtrl metrics at `http://<PROMETHEUS_HOST>:9090/graph`.\n"
  },
  {
    "path": "ecosystem/nodes/cpp/mytonctrl/alerting.mdx",
    "content": "---\ntitle: \"Telegram alerting\"\n---\n\n**MyTonCtrl Private Alerting Bot** is a tool for receiving notifications about node status via Telegram Bot.\n\nThe bot is designed to send notification messages to Telegram only. It **does not** manage the validator or process any commands.\n\nThis bot is part of the MyTonCtrl toolset and is compatible with both validators and liteservers. Create a separate private bot in Telegram and configure it within MyTonCtrl.\n\nYou can use one bot to monitor multiple nodes.\n\n## Setup\n\nTo set up the MyTonCtrl Alerting Bot, follow these steps:\n\n### Prepare a bot\n\n1. Visit [@BotFather](https://t.me/BotFather) and create a bot by using the command `/newbot`. After creating a bot, copy the bot token under the \"Use this token to access the HTTP API:\" line.\n\n1. Go to the bot and press the `Start` button. This action will allow the bot to send messages.\n\n1. The bot can send messages to either private messages or groups. To receive messages from the bot in a group chat, make sure to add the bot to that group.\n\n1. Visit [`@getmyid_bot`](https://t.me/getmyid_bot) and press the **Start** button. The bot will reply with a chat ID; use this ID to receive messages from the bot.\n\nTo receive messages in a group, add [`@getmyid_bot`](https://t.me/getmyid_bot) to the group, and it will provide the chat ID of this group.\n\n### Activate the alert bot in MyTonCtrl\n\n1. Enable the `alert-bot` using the following command:\n\n   ```bash\n   MyTonCtrl> enable_mode alert-bot\n   ```\n\n1. Execute the command:\n\n   ```bash\n   MyTonCtrl> setup_alert_bot <bot_token> <chat_id>\n   ```\n\nIn case of a successful setup, the bot sends a welcome message listing all available alerts.\n\n## Operational notes\n\n- Alerts cover wallet balance thresholds, database usage, validator efficiency/blocks, synchronization, ADNL health, stake acceptance, slashes, and other key metrics.\n- Each alert has an associated cooldown (`timeout`) to prevent spam. Info-level ok alerts reset state without sound notifications.\n- The bot requires network access to the Telegram API. Ensure outbound HTTPS is permitted from the server.\n- When validator mode is enabled, the alert bot automatically includes wallet and ADNL context in messages. In collator-only or other modes, some alerts may be skipped because prerequisites are missing.\n\n## setup\\_alert\\_bot\n\n**Purpose:** Configure the alert bot with the Telegram bot token and chat ID, then start sending events.\n\n**Syntax**\n\n```mytonctrl\nsetup_alert_bot <bot_token> <chat_id>\n```\n\n**Behavior**\n\n- Takes the Telegram bot token and chat ID as positional parameters. Run it right after enabling `alert-bot` mode.\n- Immediately attempts to send the welcome message that lists every alert. Success proves the bot has permission to write to the chat.\n- On success, saves `BotToken` and `ChatId` in the local database (`myLocal.db`) so the scheduler can emit alerts. On failure, logs the Telegram error (and hints if the bot is missing from the chat).\n\n## list\\_alerts\n\n**Purpose:** Show all predefined alerts and whether they are currently enabled.\n\n**Syntax**\n\n```mytonctrl\nlist_alerts\n```\n\n**Behavior**\n\n- Lists every alert key (for example: `low_wallet_balance`, `db_usage_80`, `out_of_sync`) along with the enabled flag and the UNIX timestamp when it was last sent.\n- Helps you audit which alerts are muted and whether recent warnings have fired.\n\n## enable\\_alert\n\n**Purpose:** Re-enable a previously muted alert.\n\n**Syntax**\n\n```mytonctrl\nenable_alert <alert_name>\n```\n\n**Behavior**\n\n- Accepts any alert key defined in the alert module (for example: `low_efficiency`, `service_down`, `validator_slashed`).\n- Sets the alert’s `enabled` flag to `true` so future events can trigger notifications.\n\n**Example**\n\n```mytonctrl\nenable_alert low_wallet_balance\n```\n\n## disable\\_alert\n\n**Purpose:** Temporarily suppress a specific alert.\n\n**Syntax**\n\n```mytonctrl\ndisable_alert <alert_name>\n```\n\n**Behavior**\n\n- Marks the alert as disabled; the scheduler skips sending messages for it until re-enabled.\n- Use when you expect noisy conditions (e.g., during planned maintenance) but still want other alerts to deliver.\n\n**Example**\n\n```mytonctrl\ndisable_alert service_down\n```\n\n## test\\_alert\n\n**Purpose:** Send a simple message through the configured alert channel to verify connectivity.\n\n**Syntax**\n\n```mytonctrl\ntest_alert\n```\n\n**Behavior**\n\n- Requires successful initialization (bot token and chat ID saved). If initialization hasn’t run yet, the command triggers it.\n- Sends `Test alert` with `info` severity so you can confirm the chat receives notifications.\n\n### Available alerts\n\n- `low_wallet_balance`: Validator wallet balance below 10 TON while the node is working and in sync.\n- `low_wallet_balance_ok`: Balance recovered to ≥10 TON after a low-balance alert.\n- `db_usage_80`: TON database usage exceeded 80% (but ≤95%).\n- `db_usage_95`: TON database usage exceeded 95%.\n- `db_usage_ok`: Database usage dropped back below 80% after a high-usage alert.\n- `low_efficiency`: Validator efficiency fell below 90% once ≥80% of the round elapsed.\n- `out_of_sync`: Node stayed more than 20 seconds behind the masterchain while otherwise running.\n- `sync_ok`: Node resynced to less than 20 seconds lag after an out-of-sync alert.\n- `service_down`: Validator service stopped reporting as working (outside of initial sync).\n- `service_down_ok`: Validator service resumed normal operation after downtime.\n- `adnl_connection_failed`: Remote ADNL connectivity checks failed for all probe hosts.\n- `adnl_connection_ok`: ADNL check succeeded again after a failure.\n- `zero_block_created`: No blocks produced in roughly the last half validation period (\\~8h on mainnet).\n- `zero_block_created_ok`: Block production resumed after a zero-block alert.\n- `validator_slashed`: Validator was slashed in the previous validation round.\n- `stake_not_accepted`: Election stake submission was rejected (validator missing from the current validator list).\n- `stake_accepted`: Election stake was accepted (validator present in the current validator list).\n- `stake_returned`: Elector returned the stake during the post-freeze payout window.\n- `stake_not_returned`: Stake was not returned during the expected post-freeze payout window.\n- `voting`: Governance offers with ≥50% approval remain unvoted by this validator.\n- `voting_ok`: All actionable governance offers have been voted on (no outstanding votes).\n- `initial_sync_completed`: Initial blockchain sync finished successfully.\n- `shard_collators_offline`: All registered collators for at least one shard are offline.\n- `shard_collators_ok`: Collators for previously offline shards reported back online.\n"
  },
  {
    "path": "ecosystem/nodes/cpp/mytonctrl/backups.mdx",
    "content": "---\ntitle: \"Backup\"\ndescription: \"MyTonCtrl bundles helper scripts for creating and restoring node backups.\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\n\n<Aside type=\"caution\">Exporting and restoring backups exposes private keys and validator configuration. Keep backups securely.</Aside>\n\n## Operational notes\n\n- Backups capture MyTonCtrl data, validator config, and keyring files. Always store backup archives securely (they contain private keys).\n- Restoration overwrites existing configuration. Ensure the donor node is offline before restoring its backup to avoid data divergence.\n- Both scripts expect `sudo` or equivalent privileges when manipulating system files. Use the `-u` flag to match the original install user if necessary.\n\n## Validator automated backups\n\nTo enable automated backups (only in `validator` mode), call `set auto_backup true` on the MyTonCtrl console. These backups will be performed immediately after the node participates in the elections, ensuring that all data needed for the upcoming validation cycle is preserved. By default, automated backups are saved to `/tmp/mytoncore/auto_backups/`. Call `set auto_backup_path <path>` to change this path.\n\nAutomated backups older than 7 days are deleted automatically.\n\n## Standby node\n\nIt is recommended to maintain at least one standby node that can take over validation duties if the main machine fails.\n\nThe standby machine should be hosted at a different physical location/ISP. It should have MyTonCtrl installed in full node mode and be synchronized with the TON Blockchain network. Hardware sizing should match main validator configuration.\n\nUse `create_backup` and `restore_backup` commands described below to transfer validator config to the standby machine.\n\nBefore transferring the validator configuration to the standby machine, make sure to stop or disable the TON node on the donor machine for approximately 20 minutes. Failure to follow this step may lead to connectivity issues and crashes on both the donor and target machines.\n\nCreate and retain a backup of standby node's original configuration before applying or restoring a backup package from another machine. This backup is needed to revert the standby node back to standby mode.\n\n## create\\_backup\n\n**Purpose:** Generate a compressed archive containing MyTonCtrl configuration, keyring, and validator data.\n\n**Syntax**\n\n```mytonctrl\ncreate_backup [filename] [-u <user>]\n```\n\n**Behavior**\n\n- Creates a snapshot of the following data:\n\n  - Node configuration file located at (`/var/ton-work/db/config.json`)\n\n  - Node keyring found in (`/var/ton-work/db/keyring`)\n\n  - Node liteserver and console keys stored in (`/var/ton-work/keys`)\n\n  - MyTonCtrl configuration database and related files located at (`~/.local/share/mytoncore`)\n\n  - Wallet and pool data\n\n- Validates the snapshot (ensures the config and database files deserialize) before compressing it into a `.tar.gz`; defaults to `mytonctrl_backup_<hostname>_<timestamp>.tar.gz` unless `filename` specified.\n\n- Sets archive ownership back to the requested user (`-u`) and removes the temporary snapshot when done, printing `create_backup - OK` or `... - Error` based on the helper script exit code.\n\n**Examples**\n\n```mytonctrl\ncreate_backup\ncreate_backup mynode-backup-2024-05-01.tar -u validator\n```\n\n## restore\\_backup\n\n**Purpose:** Restore a previously created backup archive into the current node environment.\n\n**Syntax**\n\n```mytonctrl\nrestore_backup <filename> [-y] [--skip-create-backup] [-u <user>]\n```\n\n**Behavior**\n\n- Requires the backup archive filename. Optional flags:\n  - `-y` skips the interactive confirmation prompt.\n  - `--skip-create-backup` prevents MyTonCtrl from making a safety backup of the current state before restoring.\n  - `-u <user>` runs the restore operations as the specified system user (defaults to the current user).\n- Unless `--skip-create-backup` passed, first runs `create_backup` so the state can be rolled back if the restore fails.\n- Stops `validator` and `mytoncore` services, and restores data from the backup, except for IP address, which will be updated accordingly.\n- On success, reloads MyTonCtrl’s local database, reinstalls BTC Teleport if validator mode is active, prints `restore_backup - OK`, and exits so MyTonCtrl can be restarted with the restored state.\n\n**Examples**\n\n```mytonctrl\nrestore_backup mynode-backup-2024-05-01.tar\nrestore_backup mynode-backup-2024-05-01.tar -y --skip-create-backup -u validator\n```\n"
  },
  {
    "path": "ecosystem/nodes/cpp/mytonctrl/btc-teleport.mdx",
    "content": "---\ntitle: \"BTC Teleport\"\ndescription: \"The BTC Teleport module manages the optional Bitcoin bridge (Teleport) client shipped with MyTonCtrl. Use these commands to inspect proposals, vote on them, or remove the Teleport installation when no longer needed.\"\n---\n\n## Operational notes\n\n- Teleport installation happens automatically when validator mode is enabled unless `btcTeleportDisabled` is set. Use these commands to check governance participation or clean up.\n- Voting attaches 1.5 TON from the validator wallet. Ensure the wallet has sufficient balance before sending votes.\n- The module caches proposals it has voted on (`saveOffersBtcTeleport`) to avoid duplicate submissions.\n\n## `remove_btc_teleport`\n\n**Purpose:** Uninstall the Teleport binaries, keystore, and system service.\n\n**Syntax**\n\n```mytonctrl\nremove_btc_teleport [--force]\n```\n\n<Caution>`--force` removes Teleport binaries and service configuration.\nRisk: loss of Teleport state; service downtime.\nScope: this node’s Teleport installation (binaries, keystore, systemd unit).\nRollback/Mitigation: reinstall Teleport or restore from a backup of `/usr/src/ton-teleport-btc-periphery` and related configs.\nEnvironment: applies to both TON Testnet and TON Mainnet nodes.</Caution>\n\n**Behavior**\n\n- Runs `scripts/remove_btc_teleport.sh` to delete the Teleport repository (`/usr/src/ton-teleport-btc-periphery`), keystore, and systemd service.\n- By default, it refuses to run if the validator is currently a masterchain participant. Use `--force` only when the node is not producing masterchain blocks or after exiting the validator set.\n- Prints an error if the removal script fails.\n\n**Example**\n\n```mytonctrl\nremove_btc_teleport --force\n```\n"
  },
  {
    "path": "ecosystem/nodes/cpp/mytonctrl/collator.mdx",
    "content": "---\ntitle: \"Collator\"\ndescription: \"Collator mode lets a node produce blocks for selected shardchains without running the full validator stack. The commands below help you configure local collators, adjust the validator allowlist, and manage collator-specific configuration JSON.\"\n---\n\n## Operational notes\n\n- Collator mode cannot be enabled while validator mode is active (`enable_mode collator` requires `disable_mode validator` first).\n- `setup_collator` relies on validator-console RPCs and the underlying node arguments; ensure `mytoninstaller` utilities are present and the node runs with permissions to edit `/etc/ton/validator-engine.conf`.\n- Shard identifiers follow TON conventions: `workchain` is `-1` for masterchain or `0` for basechain, and `<SHARD_HEX>` must be a 16-character hex prefix (e.g., `2000000000000000`).\n- Keep your validator wallet and ADNL keys backed up. Removing collators will delete console mappings, but does not revoke keys created with `CreateNewKey`.\n\n## Collator lifecycle commands\n\n### `setup_collator`\n\n**Purpose:** Register a local collator for one or more shards and update node arguments accordingly.\n\n**Syntax**\n\n```mytonctrl\nsetup_collator [--force] [--adnl <ADNL_ID>] <WORKCHAIN>:<SHARD_HEX> [<ADDITIONAL_SHARDS>...]\n```\n\n**Behavior**\n\n- Requires at least one shard identifier in `<WORKCHAIN>:<SHARD_HEX>` format (for example `0:2000000000000000`).\n- Creates a new ADNL key automatically unless you pass an existing one with `--adnl` (value must be base64 as returned by `newkey`).\n- Ensures `--add-shard` entries exist in the validator-engine arguments. When the node already monitors shards and `-M` is enabled, the command verifies coverage. Use `--force` to bypass this safety check if you intentionally widen monitoring.\n- Calls the validator console (`add-collator`) for each shard and appends the necessary node arguments via `mytoninstaller set_node_argument`.\n- Logs follow-up commands (`add_collator <ADNL> <SHARD>`) that validators should run to accept the collator.\n\n**Example**\n\n```mytonctrl\nsetup_collator 0:2000000000000000 0:4000000000000000\n```\n\n### `stop_collator`\n\n**Purpose:** Remove one collator or all local collators from validator-console tracking.\n\n**Syntax**\n\n```mytonctrl\nstop_collator\nstop_collator <ADNL_HEX> <WORKCHAIN>:<SHARD_HEX>\n```\n\n**Behavior**\n\n- Without arguments: prompts for confirmation, then deletes every local collator by iterating over the validator configuration.\n- With specific arguments, targets a single collator. `<ADNL_HEX>` must be the hex-encoded ADNL ID (as shown by `print_local_collators`).\n- Issues `del-collator` commands to the validator console and reports errors if any removal fails.\n\n**Examples**\n\n```mytonctrl\nstop_collator\nstop_collator 2F3C7A...B91 0:2000000000000000\n```\n\n### `print_local_collators`\n\n**Purpose:** List the collators currently registered on this node.\n\n**Syntax**\n\n```mytonctrl\nprint_local_collators\n```\n\n**Behavior**\n\n- Reads the validator configuration and prints a table with each collator’s ADNL (hex) and shard identifier.\n- Returns “No collators found” when none are configured.\n\n## Collation allowlist management\n\n### `add_validator_to_collation_wl`\n\n**Purpose:** Enable and populate the validator allowlist that is allowed to receive collated blocks.\n\n**Syntax**\n\n```mytonctrl\nadd_validator_to_collation_wl <ADNL_HEX> [<ADDITIONAL_ADNL>...]\n```\n\n**Behavior**\n\n- Ensures the allowlist is active (`collator-whitelist-enable 1`) and then adds each ADNL (hex) via `collator-whitelist-add`.\n- Throws an error if the validator console rejects any entry.\n- Accepts one or more ADNL IDs in a single invocation.\n\n**Example**\n\n```mytonctrl\nadd_validator_to_collation_wl 2F3C7A...B91 6AD1CE...004\n```\n\n### `delete_validator_from_collation_wl`\n\n**Purpose:** Remove validators from the allowlist.\n\n**Syntax**\n\n```mytonctrl\ndelete_validator_from_collation_wl <ADNL_HEX> [<ADDITIONAL_ADNL>...]\n```\n\n**Behavior**\n\n- Calls `collator-whitelist-del` for each provided ADNL (hex) and raises an error if any deletion fails.\n- Does not disable the allowlist itself; use `disable_collation_wl` for that.\n\n**Example**\n\n```mytonctrl\ndelete_validator_from_collation_wl 6AD1CE...004\n```\n\n### `disable_collation_wl`\n\n**Purpose:** Turn off the allowlist, allowing any validator to accept blocks.\n\n**Syntax**\n\n```mytonctrl\ndisable_collation_wl\n```\n\n**Behavior**\n\n- Sends `collator-whitelist-enable 0` to the validator console.\n- Requires no arguments; prints an error if the console command fails.\n\n### `print_collation_whitelist`\n\n**Purpose:** Show the current contents of the collation allowlist as reported by the validator console.\n\n**Syntax**\n\n```mytonctrl\nprint_collation_whitelist\n```\n\n**Behavior**\n\n- Runs `collator-whitelist-show` and outputs the raw console response, including whether the allowlist is enabled and the listed ADNL IDs.\n\n## Collator configuration JSON commands\n\n### `set_collation_config`\n\n**Purpose:** Store the preferred collator options JSON location and apply it to the validator console.\n\n**Syntax**\n\n```mytonctrl\nset_collation_config <PATH_OR_URL>\n```\n\n**Behavior**\n\n- Accepts either a local filesystem path or an HTTP(S) URL returning JSON.\n- Fetches and validates the document, saves the location to the MyTonCtrl database, and calls `setcollatoroptionsjson` on the validator console using a temporary file.\n- Reports detailed errors if the file cannot be loaded or the console rejects the update.\n\n**Example**\n\n```mytonctrl\nset_collation_config https://raw.githubusercontent.com/ton-blockchain/ton-blockchain.github.io/main/default_collator_options.json\n```\n\n### `update_collation_config`\n\n**Purpose:** Reapply the stored collator options without changing the source location.\n\n**Syntax**\n\n```mytonctrl\nupdate_collation_config\n```\n\n**Behavior**\n\n- Reads the previously saved location (defaulting to `https://raw.githubusercontent.com/ton-blockchain/ton-blockchain.github.io/main/default_collator_options.json` if none was set).\n- Downloads the JSON again and calls `setcollatoroptionsjson` so changes on the remote source take effect.\n\n### `print_collation_config`\n\n**Purpose:** Display the current collator options location and the validator console’s active configuration.\n\n**Syntax**\n\n```mytonctrl\nprint_collation_config\n```\n\n**Behavior**\n\n- Prints the remembered location, fetches the live configuration with `getcollatoroptionsjson`, and shows the JSON payload formatted for readability.\n- Useful for verifying whether a recent `set_collation_config` or `update_collation_config` call succeeded.\n"
  },
  {
    "path": "ecosystem/nodes/cpp/mytonctrl/core.mdx",
    "content": "---\ntitle: \"Core\"\ndescription: \"Inspecting node health, managing modes and settings, maintaining the software stack, and running diagnostics.\"\n---\n\n## about\n\n**Purpose:** Show a mode's description, whether it is currently enabled, and the settings that belong to the mode.\n\n**Syntax**\n\n```mytonctrl\nabout <mode_name>\n```\n\n**Behavior**\n\n- Accepts exactly one mode name from: `validator`, `nominator-pool`, `single-nominator`, `liquid-staking`, `liteserver`, `collator`, `alert-bot`, `prometheus`.\n- Fails with a clear message if the mode name is unknown.\n- Prints a header, the human-readable mode description, and the current enablement status.\n- Lists every setting attached to the mode, including a short description and the default value. When a mode has no dedicated settings, the command explicitly states that.\n\n**Available modes**\n\n| Mode               | Description                                                            |\n| ------------------ | ---------------------------------------------------------------------- |\n| `validator`        | Validator functions. Activates participating in elections and staking. |\n| `nominator-pool`   | Standard nominator pools.                                              |\n| `single-nominator` | Orbs' single nominator pools.                                          |\n| `liquid-staking`   | Liquid staking controllers.                                            |\n| `liteserver`       | For liteserver usage only without validator.                           |\n| `collator`         | Blocks collator-only module.                                           |\n| `alert-bot`        | Telegram bot alerts                                                    |\n| `prometheus`       | Prometheus format data exporter                                        |\n\n**Example**\n\n```mytonctrl\nabout validator\n```\n\n## benchmark\n\n**Purpose:** Measure local disk performance to verify the node meets TON validator requirements.\n\n**Syntax**\n\n```mytonctrl\nbenchmark\n```\n\n**Behavior**\n\n- Runs a bundled benchmark script with elevated privileges. The script executes two I/O scenarios (random 4K with queue depths 64 and 1) and a RocksDB stress test.\n- The run takes up to \\~200 seconds; the console blocks until completion.\n- Results are printed as a table with read/write throughput, IOPS, and RocksDB random operations. On failure, the command prints the captured error log.\n\n## disable\\_mode\n\n**Purpose:** Deactivate one of the pluggable modes (validator, nominator-pool, single-nominator, liquid-staking, liteserver, collator, alert-bot, prometheus).\n\n**Syntax**\n\n```mytonctrl\ndisable_mode <mode_name>\n```\n\n**Behavior**\n\n- Turns the selected mode off and persists the change immediately. Valid mode names: `validator`, `nominator-pool`, `single-nominator`, `liquid-staking`, `liteserver`, `collator`, `alert-bot`, `prometheus`.\n- Refuses to run when the mode name is unknown or when the mode’s own safety checks disallow disabling it (for example, modules may prevent leaving the validator network while critical processes are active).\n- After a successful change, the console session exits so that dependent services can restart with the new configuration.\n\n**Example**\n\n```mytonctrl\ndisable_mode liteserver\n```\n\n## enable\\_mode\n\n**Purpose:** Activate a mode that is currently disabled.\n\n**Syntax**\n\n```mytonctrl\nenable_mode <mode_name>\n```\n\n**Behavior**\n\n- Validates the requested mode, enforces dependency rules, and enables supplementary components when required. Valid mode names: `validator`, `nominator-pool`, `single-nominator`, `liquid-staking`, `liteserver`, `collator`, `alert-bot`, `prometheus`. Examples: enabling `validator` forces `liteserver` to be disabled first; enabling `liquid-staking` makes sure the TON HTTP API is configured; enabling `validator` automatically installs BTC Teleport unless you disabled it via settings.\n- Persists the change right away and terminates the console session once the command finishes.\n\n**Example**\n\n```mytonctrl\nenable_mode validator\n```\n\n## Settings commands\n\n**Purpose:** Manage MyTonCtrl configuration values and review their current state.\n\n### `get`\n\n**Syntax**\n\n```mytonctrl\nget <setting-name>\n```\n\n**Behavior**\n\n- Reads the requested setting from the local database and prints it as pretty-printed JSON.\n- Accepts any supported setting key (see list below); unknown keys return `null`.\n- Strings, numbers, booleans, and objects are displayed exactly as stored.\n\n**Example**\n\n```mytonctrl\nget sendTelemetry\n```\n\n### `set`\n\n**Syntax**\n\n```mytonctrl\nset <setting-name> <setting-value> [--force]\n```\n\n**Behavior**\n\n- Updates a stored setting. Values are parsed as JSON when possible; otherwise, the raw string is saved.\n- Validates that the key exists and that its parent mode is enabled. Use `--force` to bypass these checks when preparing a configuration ahead of enabling a mode or when intentionally writing custom keys.\n- Rejects deprecated aliases such as `usePool` and `useController` and points you to `enable_mode` instead.\n- Saves immediately and backs up the database on each change.\n\n**Examples**\n\n```mytonctrl\nset auto_backup true\nset liquid_pool_addr \"0:abc123...\"\nset auto_backup_path /mnt/backups --force\n```\n\n### `status_settings`\n\n**Syntax**\n\n```mytonctrl\nstatus_settings\n```\n\n**Behavior**\n\n- Prints a table listing every supported setting alongside its description, owning mode, default value, and the active value stored in the local database.\n- Useful for auditing overrides before upgrades or for verifying configuration after scripted changes.\n\n### Supported settings\n\n- **`stake`** (mode `validator`, default `null`) — Stake amount submitted during elections when defined.\n- **`stakePercent`** (mode `validator`, default `99`) — Percentage of the validator wallet to stake when `stake` is not provided.\n- **`isSlashing`** (mode `validator`, default `null`) — Enables automatic complaint submission against misbehaving validators.\n- **`validatorWalletName`** (mode `validator`, default `wallet_001`) — Local wallet identifier used for validator operations.\n- **`maxFactor`** (mode `validator`, default `null`) — Overrides the `maxFactor` sent to the Elector; falls back to config 17 when unset.\n- **`participateBeforeEnd`** (mode `validator`, default `null`) — Seconds before the round end when the validator should join elections.\n- **`liquid_pool_addr`** (mode `liquid-staking`, default `null`) — Address of the liquid staking pool used for controller operations.\n- **`min_loan`** (mode `liquid-staking`, default `41000`) — Minimum loan size in nanoTON for liquid staking borrowing.\n- **`max_loan`** (mode `liquid-staking`, default `43000`) — Maximum loan size in nanoTON for liquid staking borrowing.\n- **`max_interest_percent`** (mode `liquid-staking`, default `10`) — Interest ceiling (percent) applied to liquid staking loans.\n- **`duplicateSendfile`** (mode `null`, default `true`) — Duplicates external messages to public lite servers for redundancy.\n- **`sendTelemetry`** (mode `null`, default `true`) — Enables periodic telemetry submission to TON community services.\n- **`telemetryLiteUrl`** (mode `null`, default `https://telemetry.toncenter.com/report_status`) — Endpoint used when telemetry is enabled.\n- **`overlayTelemetryUrl`** (mode `null`, default `https://telemetry.toncenter.com/report_overlays`) — Endpoint for overlay network telemetry reports.\n- **`duplicateApi`** (mode `null`, default `sendTelemetry`) — Controls whether to forward external messages via TON Center; default follows the `sendTelemetry` flag.\n- **`duplicateApiUrl`** (mode `null`, default `https://[testnet.]toncenter.com/api/v2/sendBoc`) — API endpoint used when `duplicateApi` is active.\n- **`checkAdnl`** (mode `null`, default `sendTelemetry`) — Checks local UDP port and ADNL connectivity; default follows the `sendTelemetry` flag.\n- **`liteclient_timeout`** (mode `null`, default `3`) — Default timeout, in seconds, for lite-client calls.\n- **`console_timeout`** (mode `null`, default `3`) — Default timeout, in seconds, for validator console interactions.\n- **`fift_timeout`** (mode `null`, default `3`) — Default timeout, in seconds, for Fift executions.\n- **`useDefaultCustomOverlays`** (mode `null`, default `true`) — Joins the predefined custom overlays when the node is eligible.\n- **`defaultCustomOverlaysUrl`** (mode `null`, default `https://ton-blockchain.github.io/fallback_custom_overlays.json`) — Source for the fallback custom overlay configuration.\n- **`debug`** (mode `null`, default `false`) — Enables verbose console debugging with Python tracebacks.\n- **`subscribe_tg_channel`** (mode `validator`, default `false`) — Suppresses reminders about subscribing to the TON STATUS Telegram channel.\n- **`auto_backup`** (mode `validator`, default `null`) — Enables automatic validator backups every election when set truthy.\n- **`auto_backup_path`** (mode `validator`, default `/tmp/mytoncore/auto_backups/`) — Destination folder for automatic backups.\n- **`prometheus_url`** (mode `prometheus`, default `null`) — Pushgateway URL for Prometheus metrics.\n- **`onlyNode`** (mode `null`, default `null`) — When true, restricts MyTonCtrl to telemetry collection without elections.\n- **`importGc`** (mode `null`, default `null`) — When enabled, removes imported archive block files after use; requires MyTonCtrl restart.\n- **`btcTeleportDisabled`** (mode `validator`, default `false`) — Prevents automatic BTC Teleport installation during validator setup.\n\n## installer\n\n**Purpose:** Launch the MyTonInstaller utility from inside MyTonCtrl.\n\n**Syntax**\n\n```mytonctrl\ninstaller\ninstaller <installer_command> [installer_args...]\n```\n\n**Behavior**\n\n- With no arguments, opens the interactive MyTonInstaller console so you can walk through node provisioning tasks.\n- When you pass arguments, MyTonCtrl forwards them to MyTonInstaller’s `-c` command mode. This lets you trigger individual installer actions without entering the interactive shell. Arguments are concatenated into a single command string and executed exactly as if you had typed them into MyTonInstaller.\n- Common quick commands include `installer clcf` (create a local config file), `installer status`, or `installer enable JR` (enable JSON-RPC support).\n\n**Examples**\n\n```mytonctrl\ninstaller\ninstaller clcf\ninstaller enable THA\n```\n\n## rollback\n\n**Purpose:** Revert MyTonCtrl to the legacy `MTC1` configuration format.\n\n**Syntax**\n\n```mytonctrl\nrollback\n```\n\n**Behavior**\n\n- Prompts for confirmation before running because the operation is destructive and intended for recovery scenarios only.\n- Restores the old `usePool`/`useController` flags in the local database, removes the new `modes` map, and runs the bundled rollback migration script.\n- On success, the console exits so you can restart MyTonCtrl with the downgraded layout.\n\n## status\n\n**Purpose:** Display a full health report for the node.\n\n**Syntax**\n\n```mytonctrl\nstatus\nstatus fast\n```\n\n**Behavior**\n\n- Without arguments, the command aggregates live data from the validator, lite-client, system metrics, and Git repositories. It prints:\n  - Network overview: network name, validator participation counts, shard count, outstanding offers/complaints, current election status.\n  - Local node metrics: validator index and efficiency, ADNL addresses, wallet balances, CPU/memory/swap/disk utilization, network throughput, service uptimes (mytoncore, validator, `btc_teleport` when applicable), virtualization detection, version information for MyTonCtrl, TON binaries, and optional BTC Teleport.\n  - Additional election metadata for validator nodes, including config parameters and the expected validation/election timeline.\n- `status fast` skips remote calls that enumerate validators and offers, which is useful on constrained connections or when you only need the local section.\n- If the node is out of sync, the report focuses on local health and prints warnings instead of global network data.\n\n**Examples**\n\n```mytonctrl\nstatus\nstatus fast\n```\n\n## status\\_modes\n\n**Purpose:** Review the enablement state of every mode.\n\n**Syntax**\n\n```mytonctrl\nstatus_modes\n```\n\n**Behavior**\n\n- Prints a table with mode names, whether each is enabled, and a one-line description. Modes reported: `validator`, `nominator-pool`, `single-nominator`, `liquid-staking`, `liteserver`, `collator`, `alert-bot`, `prometheus`.\n- Covers core modes (validator, liteserver, nominator-pool, single-nominator) and optional services (alert-bot, prometheus, collator, liquid-staking) so you can review the full stack at once.\n- Handy for auditing which modules are active before enabling or disabling more features.\n\n## update\n\n**Purpose:** Update the MyTonCtrl codebase.\n\n**Syntax**\n\n```mytonctrl\nupdate\nupdate <branch>\nupdate https://github.com/<author>/<repo>/tree/<branch>\nupdate https://github.com/<author>/<repo>/tree/<branch> <branch>\n```\n\n**Behavior**\n\n- With no arguments, pulls the latest commits for the repository and branch currently checked out under `/usr/src/mytonctrl`.\n- Supplying a branch name switches the update target to that branch on the existing remote.\n- Supplying a full GitHub URL lets you update from a different fork or repository. You can add a trailing branch argument to override the branch parsed from the URL.\n- The command validates that the requested branch exists remotely before running. If you are already tracking a non-standard origin or branch, MyTonCtrl asks you to specify the remote explicitly.\n- Runs the bundled `update.sh` script with root privileges and exits the console when it completes. Success and failure are clearly reported.\n\n**Examples**\n\n```mytonctrl\nupdate\nupdate develop\nupdate https://github.com/example/mytonctrl/tree/feature-x feature-x\n```\n\n## upgrade\n\n**Purpose:** Update TON node binaries and supporting components.\n\n**Syntax**\n\n```mytonctrl\nupgrade [<branch>]\nupgrade --btc-teleport [<branch>] [-u <user>]\n```\n\n**Behavior**\n\n- By default, upgrades the TON sources located in `/usr/src/ton` to the specified branch (or the currently checked-out branch when none is provided). The command fixes legacy file paths, updates lite-client and validator-console settings, checks your installed Clang version, and warns if it is older than 16 before continuing.\n- After the TON build completes, validator nodes automatically refresh the BTC Teleport service unless you disabled it through settings.\n- The `--btc-teleport` variant reinstalls or updates only the BTC Teleport service. You can optionally provide a branch to fetch (defaults to `master`) and `-u <user>` to control which system user owns the service.\n- All operations run through the `upgrade.sh` helper with elevated privileges. The command prints `Upgrade - OK` or `Upgrade - Error` based on the exit status.\n\n**Examples**\n\n```mytonctrl\nupgrade\nupgrade develop\nupgrade --btc-teleport\nupgrade --btc-teleport release-2024-05 -u teleport\n```\n"
  },
  {
    "path": "ecosystem/nodes/cpp/mytonctrl/custom-overlays.mdx",
    "content": "---\ntitle: \"Custom overlays\"\ndescription: \"Sets up a custom overlay to speed up synchronization for a group of nodes.\"\n---\n\n## Operational notes\n\n- Overlays require MyTonCtrl to run in `validator` mode with an accessible validator console; the commands rely on console RPCs (`addcustomoverlay`, `showcustomoverlays`, `delcustomoverlay`).\n- Keep ADNL IDs in the configuration consistent with the node’s current validator keys. The helper refuses to deploy static overlays when the node lacks the necessary IDs.\n- Dynamic overlays are re-evaluated each election. MyTonCtrl automatically removes stale overlays tied to old election IDs and creates new ones as rounds roll over.\n\n## add\\_custom\\_overlay\n\n**Purpose:** Register a custom overlay configuration and deploy it to the validator console.\n\n**Syntax**\n\n```mytonctrl\nadd_custom_overlay <overlay-name> <path-to-config>\n```\n\n**Behavior**\n\n- `<overlay-name>` is an arbitrary label used inside MyTonCtrl and as the validator-console overlay name.\n- `<path-to-config>` must point to a JSON file describing overlay nodes. Each key is an ADNL address (hex) and each value specifies whether the node is a `block_sender` or `msg_sender` (`msg_sender` entries may include a `msg_sender_priority`).\n- Configuration files can include an `@validators` key to denote dynamic overlays. In that case, MyTonCtrl stores the config and schedules validator-console updates for the current and next election rounds.\n- Static overlays are converted immediately via `addcustomoverlay` and require that your node owns the listed ADNL IDs; otherwise, the command prints an error.\n- MyTonCtrl caches the config in its database, so overlays persist across restarts.\n\n**Example**\n\n```mytonctrl\nadd_custom_overlay telemetry-overlay /etc/mytonctrl/overlays/telemetry.json\n```\n\n### Sample config structure\n\n```json\n{\n  \"3b53...d1\": { \"block_sender\": true },\n  \"@validators\": [\"0a1f...bc\", \"292e...7a\"],\n  \"7c9d...4e\": { \"msg_sender\": true, \"msg_sender_priority\": 5 }\n}\n```\n\n- Keys other than `@validators` must be ADNL IDs in hex form.\n- For `msg_sender` entries, set `msg_sender` to `true` and optionally include `msg_sender_priority` (higher numbers mean higher priority).\n- Include `@validators` only when you want the overlay to track the current validator set automatically.\n\n## list\\_custom\\_overlays\n\n**Purpose:** Inspect every overlay definition stored by MyTonCtrl.\n\n**Syntax**\n\n```mytonctrl\nlist_custom_overlays\n```\n\n**Behavior**\n\n- Prints each overlay name and the JSON configuration saved in the local database.\n- Highlights whether an overlay is dynamic (`@validators` present) or static.\n- Helpful for auditing definitions before deploying them on another node.\n\n## delete\\_custom\\_overlay\n\n**Purpose:** Remove a stored overlay and, when possible, detach it from the validator console.\n\n**Syntax**\n\n```mytonctrl\ndelete_custom_overlay <overlay-name>\n```\n\n**Behavior**\n\n- Deletes `<overlay-name>` from the MyTonCtrl database.\n- If the overlay was dynamic (tracked via `@validators`), the validator console updates within \\~1 minute to remove it automatically.\n- For static overlays, MyTonCtrl issues `delcustomoverlay <overlay-name>` so the validator console stops broadcasting it immediately. If the console rejects the operation, the command reports an error so you can intervene manually.\n\n**Example**\n\n```mytonctrl\ndelete_custom_overlay telemetry-overlay\n```\n"
  },
  {
    "path": "ecosystem/nodes/cpp/mytonctrl/installer.mdx",
    "content": "---\ntitle: \"Installer\"\ndescription: \"MyTonInstaller complements MyTonCtrl by bootstrapping and maintaining TON node components.\"\n---\n\nRun these commands from the installer context of mytonctrl:\n\n```mytonctrl\nMyTonCtrl> installer\nInstaller>\n```\n\n## status\n\n**Purpose:** Inspect whether required TON services and credentials are in place, and review the current node arguments.\n\n**Syntax**\n\n```mytonctrl\nstatus\n```\n\n**Behavior**\n\n- Checks for the presence of validator, mytoncore, console, and liteserver artifacts under `/var/ton-work` and reports each as enabled/disabled.\n- Loads the active node argument list (from `set_node_argument`) and prints every flag with its stored values.\n- Does not modify any files, making it safe to rerun as a health check.\n\n## set\\_node\\_argument\n\n**Purpose:** Add, update, or remove TON validator/validator-engine command-line arguments.\n\n**Syntax**\n\n```mytonctrl\nset_node_argument <arg-name> [arg-value] [-d]\n```\n\n**Behavior**\n\n- Requires at least the argument name (for example, `--archive-ttl`, `-M`, `--add-shard`).\n- When additional values are provided, they are concatenated and passed to the helper script `set_node_argument.py`, which edits `/etc/ton/validator-engine.conf`-style settings.\n- Use `-d` as the final flag to delete the argument instead of setting a value.\n- Runs with root privileges to ensure the validator configuration is writable.\n\n**Examples**\n\n```mytonctrl\nset_node_argument --archive-ttl 86400\nset_node_argument --add-shard 0:2000000000000000 0:a000000000000000\nset_node_argument --archive-ttl -d\n```\n\n## enable\n\n**Purpose:** Provision or activate bundled components such as the validator console, liteserver, or auxiliary services.\n\n**Syntax**\n\n```mytonctrl\nenable <code>\n```\n\n**Behavior**\n\n- Accepts one of the codes listed below and invokes the corresponding setup routine through `mytoninstaller -e enable<code>`.\n- If you enable the TON HTTP API (`THA`), the installer first generates a local liteserver config by running `clcf` automatically.\n- All routines run with elevated privileges because they create system users, service units, configuration files, or keys.\n\n**Supported codes**\n\n| Code  | Component            | Purpose                                                                                                                   | Key tasks                                                                                                                                                                                       |\n| ----- | -------------------- | ------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `FN`  | First node bootstrap | Prepare a fresh validator environment so MyTonCtrl can manage a node end-to-end.                                          | Creates the validator system user, installs the validator engine as a systemd service, generates the initial `config.json`, downloads blockchain dumps, and performs the first validator start. |\n| `VC`  | Validator console    | Provide secure CLI access to the validator engine for MyTonCtrl and operators.                                            | Generates server/client key pairs, wires them into `validator.config.json`, updates MyTonCore with console credentials, and restarts validator + MyTonCore to apply.                            |\n| `LS`  | liteserver           | Enable the local liteserver endpoint used by tooling and APIs.                                                            | Creates liteserver keys, registers them in `validator.config.json`, updates MyTonCore’s lite-client section, and restarts services to expose the port locally.                                  |\n| `DS`  | DHT server           | Run a standalone DHT node so the validator can advertise itself through the ADNL network.                                 | Installs and enables the TON DHT service, provisions keys, selects public ports, generates/prints the ADNL address list, and starts the daemon under systemd.                                   |\n| `JR`  | JSON-RPC frontend    | Install [MyTonCtrl’s JSON-RPC bridge](https://github.com/igroman787/mtc-jsonrpc) for programmatic control.                | Executes `jsonrpcinstaller.sh` with root privileges to deploy the service, wiring it for the current node user.                                                                                 |\n| `THA` | TON HTTP API         | Expose the [TON HTTP API](https://github.com/toncenter/ton-http-api) backed by the local liteserver for REST-like access. | Generates a fresh liteserver config when needed and runs `ton_http_api_installer.sh` to install and configure the HTTP API service.                                                             |\n| `LSP` | ls-proxy             | Proxy the liteserver connection for safer remote access and load balancing.                                               | Installs the ls-proxy binary, creates a systemd unit, bootstraps the config with local liteserver credentials, and starts the proxy service.                                                    |\n| `TS`  | TON Storage          | Provide local TON Storage capabilities for block archives and state downloads.                                            | Deploys `tonutils-storage`, configures public UDP/API ports and external IP, persists the config, registers connectivity details in MyTonCore, and starts the storage daemon.                   |\n\n**Example**\n\n```mytonctrl\nenable FN\n```\n\n## update\n\n**Purpose:** Rerun enablement routines for installed components to pull updates or repair their configuration.\n\n**Syntax**\n\n```mytonctrl\nupdate <code>\n```\n\n**Behavior**\n\n- Shares the same code list and internal handler as `enable`, but intended for repeat executions when you need to refresh binaries or regenerate configs (for example, after package updates).\n- `update JR` is the common shorthand for reinstalling or updating the JSON-RPC service.\n- Requires the same elevated privileges as `enable` because it delegates to the same installer events.\n\n**Example**\n\n```mytonctrl\nupdate JR\n```\n\n## plsc\n\n**Purpose:** Print the current liteserver configuration JSON.\n\n**Syntax**\n\n```mytonctrl\nplsc\n```\n\n**Behavior**\n\n- Reads the configuration produced by `GetLiteServerConfig` (typically `/usr/bin/ton/local.config.json`) and prints it as pretty JSON.\n- Useful for verifying that liteserver keys, ports, and peers match expectations after running `enable LS` or `clcf`.\n\n## clcf\n\n**Purpose:** Create or refresh the liteserver local configuration file.\n\n**Syntax**\n\n```mytonctrl\nclcf [-u <user>]\n```\n\n**Behavior**\n\n- Fetches the latest init block via TON API; if unavailable, falls back to the bundled `global.config.json`.\n- Base64-encodes the init block and invokes `mytoninstaller -e clc -i <base64>` under the specified user (defaults to the installer’s current user).\n- Writes `/usr/bin/ton/local.config.json` and related liteserver files so that services like TON HTTP API can start.\n\n**Examples**\n\n```mytonctrl\nclcf\nclcf -u validator\n```\n\n## print\\_ls\\_proxy\\_config\n\n**Purpose:** Display the active ls-proxy configuration file.\n\n**Syntax**\n\n```mytonctrl\nprint_ls_proxy_config\n```\n\n**Behavior**\n\n- Reads `/var/ls_proxy/ls-proxy-config.json` (via `get_ls_proxy_config`) and prints it in formatted JSON.\n- Allows quick inspection of proxy targets after running `enable LSP`.\n\n## create\\_ls\\_proxy\\_config\\_file\n\n**Purpose:** Placeholder for generating an ls-proxy config file.\n\n**Syntax**\n\n```mytonctrl\ncreate_ls_proxy_config_file\n```\n\n**Behavior**\n\n- Outputs `TODO` because the implementation is not there yet.\n- Use `print_ls_proxy_config` or edit `/var/ls_proxy/ls-proxy-config.json` manually until this command is implemented.\n\n## `drvcf`\n\n**Purpose:** Rebuild `config.json` for the validator engine using existing key material (dangerous recovery).\n\n**Syntax**\n\n```mytonctrl\ndrvcf\n```\n\n**Behavior**\n\n- Calls `DangerousRecoveryValidatorConfigFile`, which scans `/var/ton-work/db/keyring`, recent election dumps, and mytoncore settings to reconstruct validator, liteserver, control, DHT, and ADNL entries.\n- Prints the reconstructed configuration and any unused keys so you can review the output before applying it manually.\n- Intended for disaster recovery scenarios; it does not overwrite files automatically.\n\n## setwebpass\n\n**Purpose:** Set or change the password for the MyTonCtrl web administration (JSON-RPC) interface.\n\n**Syntax**\n\n```mytonctrl\nsetwebpass\n```\n\n**Behavior**\n\n- Runs `/usr/src/mtc-jsonrpc/mtc-jsonrpc.py -p`, prompting for the new password and updating the credential store.\n- No arguments are accepted; rerun whenever you need to rotate web admin credentials.\n"
  },
  {
    "path": "ecosystem/nodes/cpp/mytonctrl/liquid-staking.mdx",
    "content": "---\ntitle: \"Liquid staking\"\ndescription: \"Liquid staking mode orchestrates controller deployment and maintenance for jetton-based staking pools. The commands below cover controller lifecycle management, funding flows, validator-set updates, and diagnostic helpers.\"\n---\n\n## Operational notes\n\n- Liquid staking controllers rely on the validator wallet and liquid pool contracts. Keep the wallet funded and the pool address (`liquid_pool_addr`) set via `set liquid_pool_addr <address>` before deploying controllers.\n- Pending withdrawals are stored in the local database when a controller is busy (non-zero `state`). MyTonCtrl processes them automatically as soon as the controller returns to the ready state.\n- The jetton pool contracts must be available under `/usr/src/mytonctrl/contracts/jetton_pool/`. The first run of `create_controllers` downloads them if necessary.\n- Commands interacting with the TON HTTP API assume the service listens on `127.0.0.1:8801` (the default when this mode is enabled).\n\n## Controller deployment and discovery\n\n### `create_controllers`\n\n**Purpose:** Deploy the two standard controllers for the configured liquid staking pool if they are missing or outdated.\n\n**Syntax**\n\n```mytonctrl\ncreate_controllers\n```\n\n**Behavior**\n\n- Compares the controller addresses returned by the pool (`GetControllers`) with the addresses stored in the local database.\n- If they differ, downloads the jetton pool deployment scripts (on first run), signs the deployment BoCs with the validator wallet, and sends them to the liquid pool with a small attach value.\n- Stores the newly active controllers under `using_controllers` so subsequent staking and voting commands target the fresh contracts.\n\n### `update_controllers`\n\n**Purpose:** Re-run the controller deployment workflow to synchronize with changes on the pool side.\n\n**Syntax**\n\n```mytonctrl\nupdate_controllers\n```\n\n**Behavior**\n\n- Alias for `create_controllers`; useful after pool upgrades or migration, forcing MyTonCtrl to redeploy controllers when the contract-address mapping changes.\n\n### `controllers_list`\n\n**Purpose:** Inspect every controller list tracked locally.\n\n**Syntax**\n\n```mytonctrl\ncontrollers_list\n```\n\n**Behavior**\n\n- Prints tables for the active (`using`), newly detected, previously used (`old`), and user-specified controller lists.\n- Each entry includes address, on-chain status, balance, approval flag, and controller state as reported by `get_validator_controller_data`.\n- Allows operators to verify whether a controller is approved, funded, or stopped.\n\n### `add_controller`\n\n**Purpose:** Mark an additional controller address as user-managed so MyTonCtrl considers it for operations.\n\n**Syntax**\n\n```mytonctrl\nadd_controller <controller-addr>\n```\n\n**Behavior**\n\n- Adds `<controller-addr>` to the `user_controllers` list and removes it from the stop list if present, enabling future staking or updates through MyTonCtrl.\n- Accepts base64 controller addresses.\n\n**Example**\n\n```mytonctrl\nadd_controller EQDf...9A\n```\n\n## Funding and withdrawals\n\n### `deposit_to_controller`\n\n**Purpose:** Top up a controller contract with Toncoin from the validator wallet.\n\n**Syntax**\n\n```mytonctrl\ndeposit_to_controller <controller-addr> <amount-ton>\n```\n\n**Behavior**\n\n- Signs the `top-up.boc` script with the validator wallet and sends `<amount-ton>` TON to `<controller-addr>`.\n- Use decimal TON amounts; the command handles the nanoTON conversion internally.\n\n**Example**\n\n```mytonctrl\ndeposit_to_controller EQDf...9A 2000\n```\n\n### `withdraw_from_controller`\n\n**Purpose:** Withdraw funds from a controller back to the validator wallet.\n\n**Syntax**\n\n```mytonctrl\nwithdraw_from_controller <controller-addr> [amount-ton]\n```\n\n**Behavior**\n\n- Requests an immediate withdrawal when the controller state permits it; otherwise, it queues a pending withdrawal that is handled automatically later.\n- If `[amount-ton]` is omitted, MyTonCtrl withdraws nearly the entire balance (leaving \\~10 TON to cover rent).\n\n**Examples**\n\n```mytonctrl\nwithdraw_from_controller EQDf...9A\nwithdraw_from_controller EQDf...9A 750\n```\n\n### `stop_controller`\n\n**Purpose:** Flag a controller so MyTonCtrl stops using it for future staking operations.\n\n**Syntax**\n\n```mytonctrl\nstop_controller <controller-addr>\n```\n\n**Behavior**\n\n- Adds `<controller-addr>` to the local stop list and removes it from the user or active lists. The contract remains on-chain but is ignored by automated workflows.\n\n**Example**\n\n```mytonctrl\nstop_controller EQDf...9A\n```\n\n### `stop_and_withdraw_controller`\n\n**Purpose:** Stop a controller and withdraw its funds in a single step.\n\n**Syntax**\n\n```mytonctrl\nstop_and_withdraw_controller <controller-addr> [amount-ton]\n```\n\n**Behavior**\n\n- Flags the controller as stopped (same as `stop_controller`).\n- Triggers a withdrawal for `[amount-ton]` TON; when omitted, withdraws almost the full balance (balance minus \\~10.1 TON to keep the contract alive).\n\n**Example**\n\n```mytonctrl\nstop_and_withdraw_controller EQDf...9A\n```\n\n## Validator-set maintenance\n\n### `controller_update_validator_set`\n\n**Purpose:** Refresh the validator set stored on a controller contract.\n\n**Syntax**\n\n```mytonctrl\ncontroller_update_validator_set <controller-addr>\n```\n\n**Behavior**\n\n- Calls the controller’s `update_validator_set` method so it picks up the latest validator ADNL IDs from the pool.\n- Use after elections or whenever the pool indicates mismatched validator sets.\n\n**Example**\n\n```mytonctrl\ncontroller_update_validator_set EQDf...9A\n```\n\n### `check_liquid_pool`\n\n**Purpose:** Scan recent liquid pool transactions and update controller validator sets automatically.\n\n**Syntax**\n\n```mytonctrl\ncheck_liquid_pool\n```\n\n**Behavior**\n\n- Looks through the liquid pool’s account history, detects controller addresses interacting with the pool, and calls `controller_update_validator_set` for each detected controller.\n- Useful as a catch-up step after manual interventions or pool upgrades.\n\n## Controller diagnostics\n\n### `get_controller_data`\n\n**Purpose:** Dump the full controller status JSON for inspection.\n\n**Syntax**\n\n```mytonctrl\nget_controller_data <controller-addr>\n```\n\n**Behavior**\n\n- Runs the controller’s `get_validator_controller_data` method and prints the resulting fields (for example: state, approval, borrowed amount, and stake timing).\n- Ideal for debugging controllers stuck in a non-zero state or verifying approval.\n\n**Example**\n\n```mytonctrl\nget_controller_data EQDf...9A\n```\n\n### `calculate_annual_controller_percentage`\n\n**Purpose:** Convert the per-round interest rate into an annualized percentage.\n\n**Syntax**\n\n```mytonctrl\ncalculate_annual_controller_percentage [percent-per-round]\n```\n\n**Behavior**\n\n- Uses the validators' election cycle length from config 15 to compute how many rounds fit into a year, and then scales the provided (or configured `max_interest_percent`) rate.\n- Prints intermediate values and the final yearly percentage.\n\n**Examples**\n\n```mytonctrl\ncalculate_annual_controller_percentage\ncalculate_annual_controller_percentage 1.25\n```\n\n### `test_calculate_loan_amount`\n\n**Purpose:** Test the on-chain helper that calculates controller loan amounts.\n\n**Syntax**\n\n```mytonctrl\ntest_calculate_loan_amount\n```\n\n**Behavior**\n\n- Sends a local HTTP request to the TON HTTP API (`/runGetMethod`) using the configured loan parameters (`min_loan`, `max_loan`, `max_interest_percent`).\n- Prints the raw response (nanoTON value) used to size controller loans.\n"
  },
  {
    "path": "ecosystem/nodes/cpp/mytonctrl/overview.mdx",
    "content": "---\ntitle: \"Overview\"\n---\n\nMyTonCtrl is a tool to run and maintain a TON node (validators and liteservers).\n\n## Install MyTonCtrl\n\nRun the installer as the non-root operator who will manage the node. The command below fetches dependencies, downloads the script, and starts the interactive setup wizard:\n\n```bash\nsudo apt update\nsudo apt install -y curl wget git ca-certificates python3-pip\nwget https://raw.githubusercontent.com/ton-blockchain/mytonctrl/master/scripts/install.sh\nsudo bash install.sh\n```\n\nThe wizard walks you through hardware validation, TON binary installs, and MyTonCtrl configuration. Use flags to pre-select options or automate deployments:\n\n| Flag                                                                                                         | What it does                                                    | Typical use                                                            |\n| ------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------- | ---------------------------------------------------------------------- |\n| `-d`, `--dump`                                                                                               | Downloads a packaged blockchain dump before first start.        | Speeds up the initial sync (omit to sync from peers only).             |\n| `-m`, `--mode validator\\|liteserver\\|collator`                                                               | Pre-enables the target mode.                                    | Skip switching modes manually after install.                           |\n| `-n`, `--network mainnet\\|testnet`                                                                           | Switches global config URL and minimum hardware thresholds.     | Point the node to testnet without editing configs later.               |\n| `-t`, `--telemetry`                                                                                          | Disables telemetry uploads during install.                      | Comply with policies that forbid sharing validator stats.              |\n| `-i`, `--ignore-reqs`                                                                                        | Ignores the CPU/RAM minimum check.                              | Lab hardware or cloud instances that fall below defaults.              |\n| `-c <PATH>`, `--config <PATH>`                                                                               | Supplies a custom `config.json` for TON installer steps.        | Use a vetted mirror instead of the default URL.                        |\n| `-g <URL>`, `--node-repo <URL>`                                                                              | Points the TON node build to a different Git repository.        | Test patched node sources or mirror Git access.                        |\n| `-v <VERSION>`, `--node-version <VERSION>`                                                                   | Pins the TON node to a branch, tag, or commit.                  | Lock to a specific release when validating upgrades.                   |\n| `-u <USER>`, `--user <USER>`                                                                                 | Forces the operator account that owns MyTonCtrl.                | Keep ownership correct when running the script from automation.        |\n| `-e <PATH>`, `--env-file <PATH>`                                                                             | Loads installer parameters (see below) from an env file.        | Pre-seed values like `ARCHIVE_TTL`, shard lists, or ports for CI jobs. |\n| `-a <AUTHOR>`, `--author <AUTHOR>`<br />`-r <REPO>`, `--repo <REPO>`<br />`-b <BRANCH>`, `--branch <BRANCH>` | Override the Git source for MyTonCtrl and installer scripts.    | Test forks or feature branches.                                        |\n| `-p <FILE>`, `--backup <FILE>`                                                                               | Restore from a MyTonCtrl backup archive.                        | Reinstall on fresh hardware using an existing backup.                  |\n| `-o`, `--only-mtc`                                                                                           | Install only MyTonCtrl assets (requires `-p`).                  | Use to interact with a node remotely.                                  |\n| `-l`, `--only-node`                                                                                          | Install only the TON node binaries and services.                | Pair a fresh node with an existing MyTonCtrl instance elsewhere.       |\n| `--print-env`                                                                                                | Prints the resolved install command and env values, then exits. | Dry-runs CLI answers before performing a real install.                 |\n| `-h`, `--help`                                                                                               | Prints installer help and exits.                                | Basic check of available options.                                      |\n\nLeaving out `-m` and `-p` the installer in the interactive CLI, which prompts for network selection, telemetry, and mode enablement.\n\n### Environment variables\n\nSet these variables before running `install.sh` (for example, `ARCHIVE_TTL=864000 sudo bash install.sh`) to preconfigure node behavior:\n\n| Variable         | Effect                                                              | Notes                                                                                                          |\n| ---------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |\n| `ARCHIVE_TTL`    | Overrides the retention (in seconds) passed to `--archive-ttl`.     | Defaults to `2592000` for liteserver mode and `86400` otherwise; set `-1` for effectively permanent retention. |\n| `STATE_TTL`      | Sets `--state-ttl` and shortens the archive TTL by the same amount. | Use with `ARCHIVE_TTL` to keep a smaller state cache.                                                          |\n| `ADD_SHARD`      | Adds one or more `--add-shard` arguments.                           | Provide shard IDs separated by spaces (for example `0:2000000000000000 0:a000000000000000`).                   |\n| `ARCHIVE_BLOCKS` | Downloads archive data via TON Storage during bootstrap.            | Accepts a single block/UTC date or a range (`<from> <to>`); dates must be `YYYY-MM-DD`.                        |\n| `COLLATE_SHARD`  | Configures collator shards during `collator` mode installs.         | Space-separated shard IDs; defaults to `0:8000000000000000` if unset.                                          |\n\n## Command reference\n\n| Reference                                                                 | What it covers                                                                                              |\n| ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |\n| [Core Commands](/ecosystem/nodes/cpp/mytonctrl/core)                      | Everyday console operations: updating MyTonCtrl, enabling modes, viewing status, and managing settings.     |\n| [Installer Commands](/ecosystem/nodes/cpp/mytonctrl/installer)            | Running the MyTonInstaller module to configure node services, enable components, and adjust node arguments. |\n| [Wallet Commands](/ecosystem/nodes/cpp/mytonctrl/wallet)                  | Creating, importing, exporting, and funding wallets managed by MyTonCtrl.                                   |\n| [Validator Commands](/ecosystem/nodes/cpp/mytonctrl/validator)            | Election voting, complaint handling, efficiency checks, and collator registry management for validators.    |\n| [Collator Commands](/ecosystem/nodes/cpp/mytonctrl/collator)              | Configuring collator shards, allowlists, and JSON options when operating in collator mode.                  |\n| [Pool Commands](/ecosystem/nodes/cpp/mytonctrl/pools)                     | Deploying and operating nominator pools or Orbs single-nominator pools.                                     |\n| [Liquid Staking Commands](/ecosystem/nodes/cpp/mytonctrl/liquid-staking)  | Managing liquid staking controllers, validator-set refreshes, and loan calculations.                        |\n| [Custom Overlay Commands](/ecosystem/nodes/cpp/mytonctrl/custom-overlays) | Adding, listing, and removing custom overlays for validator-console telemetry.                              |\n| [Utilities Commands](/ecosystem/nodes/cpp/mytonctrl/utilities)            | Account inspection, bookmark management, governance offer utilities, and validator list reporting.          |\n| [Alerting Commands](/ecosystem/nodes/cpp/mytonctrl/alerting)              | Configuring the MyTonCtrl alert bot, toggling alert keys, and testing notifications.                        |\n| [Backups Commands](/ecosystem/nodes/cpp/mytonctrl/backups)                | Creating and restoring configuration backups, including keyring exports.                                    |\n| [BTC Teleport Commands](/ecosystem/nodes/cpp/mytonctrl/btc-teleport)      | Reviewing Teleport proposals, voting, and uninstalling the Teleport bundle.                                 |\n\n## Pick the right guide\n\n- **Provisioning a new node?** Start with [Setup MyTonCtrl](/ecosystem/nodes/cpp/setup-mytonctrl) and then use the [Core](/ecosystem/nodes/cpp/mytonctrl/core) and [Installer](/ecosystem/nodes/cpp/mytonctrl/installer) references for ongoing maintenance.\n- **Operating pools or liquid staking?** Combine the [Pools](/ecosystem/nodes/cpp/mytonctrl/pools) or [Liquid Staking](/ecosystem/nodes/cpp/mytonctrl/liquid-staking) guides with the relevant validator or wallet sections.\n- **Keeping eyes on production nodes?** Review [Alerting](/ecosystem/nodes/cpp/mytonctrl/alerting), [Backups](/ecosystem/nodes/cpp/mytonctrl/backups), and [Utilities](/ecosystem/nodes/cpp/mytonctrl/utilities) so you can monitor and recover your infrastructure quickly.\n\n## Related resources\n\n- [Setup MyTonCtrl](/ecosystem/nodes/cpp/setup-mytonctrl)\n- [Baseline install & sync checklist](/ecosystem/nodes/cpp/setup-mytonctrl#baseline-setup-install-and-sync)\n- [Official MyTonCtrl repository](https://github.com/ton-blockchain/mytonctrl)\n"
  },
  {
    "path": "ecosystem/nodes/cpp/mytonctrl/pools.mdx",
    "content": "---\ntitle: \"Nominator pools\"\ndescription: \"Pool-focused commands help you manage validator-run nominator pools and Orbs single-nominator pools. The console exposes utilities that create local pool descriptors, deploy the contracts on-chain, and move stake in or out.\"\n---\n\n## Shared pool utilities\n\n### `pools_list`\n\n**Purpose:** Display every pool tracked locally along with its status on-chain.\n\n**Syntax**\n\n```mytonctrl\npools_list\n```\n\n**Behavior**\n\n- Queries the MyTonCtrl database for all pool descriptors stored under `/var/ton-work/pools`.\n- Resolves each pool’s smart-contract account status and balance; if an account is inactive, it falls back to the deployment (init) address.\n- Prints a table with columns `Name`, `Status`, `Balance`, `Version`, and `Address` so you can quickly audit which pools are deployed and funded.\n\n### `import_pool`\n\n**Purpose:** Register an existing pool by saving its address inside the local pools directory.\n\n**Syntax**\n\n```mytonctrl\nimport_pool <pool-name> <pool-addr>\n```\n\n**Behavior**\n\n- Accepts a local alias (`<pool-name>`) and the pool’s base64 (bounceable) smart-contract address.\n- Creates `<pool-name>.addr` in the pools directory so other commands (activation, deposits, withdrawals) can reference it.\n- Downloads the pool contract scripts on demand if they are not present yet.\n\n**Example**\n\n```mytonctrl\nimport_pool my-pool EQC02...fa8\n```\n\n### `delete_pool`\n\n**Purpose:** Remove the local metadata for a pool you no longer manage.\n\n**Syntax**\n\n```mytonctrl\ndelete_pool <pool-name>\n```\n\n**Behavior**\n\n- Deletes the BoC/address files created for `<pool-name>` from the pools directory; on-chain contracts remain untouched.\n- Useful when you migrate a pool to another host or retire a test deployment.\n\n**Example**\n\n```mytonctrl\ndelete_pool my-pool\n```\n\n## Nominator pool operations (`nominator-pool` mode)\n\n### `new_pool`\n\n**Purpose:** Generate deployment artifacts for a standard nominator pool before broadcasting it.\n\n**Syntax**\n\n```mytonctrl\nnew_pool <pool-name> <validator-reward-share-percent> <max-nominators-count> <min-validator-stake-ton> <min-nominator-stake-ton>\n```\n\n**Behavior**\n\n- Creates `<pool-name>.addr` and `<pool-name>-query.boc` using the official nominator pool Fift scripts.\n- `<validator-reward-share-percent>` is the operator commission (e.g., `10.5` for 10.5%).\n- `<max-nominators-count>` is the maximum number of nominators the pool will accept.\n- `<min-validator-stake-ton>` and `<min-nominator-stake-ton>` define the minimum validator self-stake and delegator stake in TON (whole-ton values are expected; convert to nanoTON before use if you need fractional amounts).\n- Validates that no other local pool shares the same derived address.\n- Does not submit anything to the blockchain; run `activate_pool` afterward.\n\n**Example**\n\n```mytonctrl\nnew_pool mypool 12.5 100 300000 1000\n```\n\n### `activate_pool`\n\n**Purpose:** Deploy the nominator pool contract created via `new_pool` or `import_pool`.\n\n**Syntax**\n\n```mytonctrl\nactivate_pool <pool-name>\n```\n\n**Behavior**\n\n- Loads `<pool-name>-query.boc` and ensures the validator wallet is active.\n- If the pool account is still empty, it signs and broadcasts the deployment message; if it is already active, it logs a warning and exits without changes.\n- Leaves the deployment BoC in place so you can retry if the transaction fails.\n\n**Example**\n\n```mytonctrl\nactivate_pool mypool\n```\n\n### `update_validator_set`\n\n**Purpose:** Refresh the validator address list stored in the pool contract after elections or operator changes.\n\n**Syntax**\n\n```mytonctrl\nupdate_validator_set <pool-addr>\n```\n\n**Behavior**\n\n- Uses the validator wallet to call the pool’s `update_validator_set` method.\n- `<pool-addr>` must be the pool’s bounceable address as reported by `pools_list` or `status`.\n- Typically run after activating the pool or when the validator ADNL set changes.\n\n**Example**\n\n```mytonctrl\nupdate_validator_set EQB1e...6g\n```\n\n### `deposit_to_pool`\n\n**Purpose:** Stake Toncoin from the validator wallet into the pool contract.\n\n**Syntax**\n\n```mytonctrl\ndeposit_to_pool <pool-addr> <amount-ton>\n```\n\n**Behavior**\n\n- Builds a validator deposit query, signs it with the validator wallet, and sends it to `<pool-addr>`.\n- `<amount-ton>` is a TON-denominated float or integer. Internally, the command converts it to the correct nanoTON amount.\n- Useful for seeding the validator share or topping up the pool’s liquidity.\n\n**Example**\n\n```mytonctrl\ndeposit_to_pool EQB1e...6g 1000\n```\n\n### `withdraw_from_pool`\n\n**Purpose:** Withdraw Toncoin from a nominator pool back to the validator wallet.\n\n**Syntax**\n\n```mytonctrl\nwithdraw_from_pool <pool-addr> <amount-ton>\n```\n\n**Behavior**\n\n- Checks the pool state; if withdrawals are currently unlocked, it performs an immediate withdrawal, otherwise it submits a pending withdrawal request that will execute once the pool cycle allows it.\n- `<amount-ton>` is specified in TON.\n- Requires that the validator wallet has the authority to trigger the withdrawal.\n\n**Example**\n\n```mytonctrl\nwithdraw_from_pool EQB1e...6g 250\n```\n\n## Single nominator pool operations (`single-nominator` mode)\n\n### `new_single_pool`\n\n**Purpose:** Prepare deployment assets for an Orbs single-nominator pool.\n\n**Syntax**\n\n```mytonctrl\nnew_single_pool <pool-name> <owner-address>\n```\n\n**Behavior**\n\n- Generates `<pool-name>.addr` and `<pool-name>-query.boc` using the bundled Orbs single-nominator contract templates.\n- `<owner-address>` is the delegator’s smart-contract or wallet address (bounceable base64 or workchain:hex format supported by TON tools).\n- The validator wallet address is embedded automatically as the operator.\n- Ensures no other local pool produces the same address.\n\n**Example**\n\n```mytonctrl\nnew_single_pool vip-client EQCrn...u3\n```\n\n### `activate_single_pool`\n\n**Purpose:** Broadcast the state-init produced by `new_single_pool` to deploy the contract.\n\n**Syntax**\n\n```mytonctrl\nactivate_single_pool <pool-name>\n```\n\n**Behavior**\n\n- Checks that `<pool-name>-query.boc` still exists (indicating the pool is not already active).\n- Signs the deploy message with the validator wallet and posts it to the network.\n- Warns and exits without changes if the BoC is missing because the pool was already activated.\n\n**Example**\n\n```mytonctrl\nactivate_single_pool vip-client\n```\n\n### `withdraw_from_single_pool`\n\n**Purpose:** Withdraw Toncoin from a single-nominator pool back to the validator wallet or owner as configured.\n\n**Syntax**\n\n```mytonctrl\nwithdraw_from_single_pool <pool-addr> <amount-ton>\n```\n\n**Behavior**\n\n- Issues an immediate withdrawal request against `<pool-addr>` for `<amount-ton>` TON.\n- Uses `WithdrawFromPoolProcess`, which executes in the current cycle without creating a pending queue.\n- Primarily used to return delegated funds or distribute rewards.\n\n**Example**\n\n```mytonctrl\nwithdraw_from_single_pool EQCsd...9k 50\n```\n\n## Activation and funding prerequisites\n\n- Enable the appropriate mode (`enable_mode nominator-pool` or `enable_mode single-nominator`) before using these commands; each mode mounts its own command set.\n- Ensure your validator wallet is active and funded because deployment, deposits, and withdrawals all originate from it.\n- For new pools, review the generated `.addr` and `-query.boc` files and keep secure backups—deletion removes these local artifacts.\n"
  },
  {
    "path": "ecosystem/nodes/cpp/mytonctrl/utilities.mdx",
    "content": "---\ntitle: \"Utilities\"\ndescription: \"Utility commands provide quick inspection and helper tools for accounts, bookmarks, governance artifacts, and validator data.\"\n---\n\n## Account inspection\n\n### `vas`\n\n**Purpose:** View the latest account status, code hash, and recent messages.\n\n**Syntax**\n\n```mytonctrl\nvas <account-addr|bookmark>\n```\n\n**Behavior**\n\n- Resolves bookmarks automatically and fetches the account via the lite-client.\n- Prints a status table (address, state, balance, detected contract version), the raw code hash, and the last 10 inbound/outbound messages with relative timestamps.\n- Useful for verifying that deployments succeeded or funds arrived.\n\n**Example**\n\n```mytonctrl\nvas EQBf...nw\n```\n\n### `vah`\n\n**Purpose:** Print a paginated message history for an account.\n\n**Syntax**\n\n```mytonctrl\nvah <account-addr|bookmark> <limit>\n```\n\n**Behavior**\n\n- Shows the most recent `<limit>` messages, marking direction (`>>>` for outgoing, `<<<` for incoming), amount, and counterparty addresses in base64.\n- Handy when you need deeper history than the default `vas` preview.\n\n**Example**\n\n```mytonctrl\nvah EQBf...nw 25\n```\n\n## Bookmark management\n\n### `nb`\n\n**Purpose:** Create a bookmark for frequently used addresses.\n\n**Syntax**\n\n```mytonctrl\nnb <bookmark-name> <account-addr>\n```\n\n**Behavior**\n\n- Validates that `<account-addr>` is a correct TON address and stores it under `<bookmark-name>` for future commands (e.g., `mg`, `vas`).\n\n**Example**\n\n```mytonctrl\nnb treasury EQBf...nw\n```\n\n### `bl`\n\n**Purpose:** List all stored bookmarks.\n\n**Syntax**\n\n```mytonctrl\nbl\n```\n\n**Behavior**\n\n- Prints a table with each bookmark name, address, and any cached metadata (balance or expiration date if available).\n\n### `db`\n\n**Purpose:** Delete a bookmark by name.\n\n**Syntax**\n\n```mytonctrl\ndb <bookmark-name>\n```\n\n**Behavior**\n\n- Removes the bookmark from MyTonCtrl storage. Future commands must use the raw address unless you recreate the bookmark.\n\n**Example**\n\n```mytonctrl\ndb treasury\n```\n\n## Governance and configuration helpers\n\n### `ol`\n\n**Purpose:** Display open governance offers (configuration proposals).\n\n**Syntax**\n\n```mytonctrl\nol [--json] [hash]\n```\n\n**Behavior**\n\n- Without flags, prints a table showing hash (trimmed unless you pass the literal `hash` argument), config ID, votes, win/loss tally, approval percentage, and pass status.\n- `--json` outputs the raw offer list in JSON format.\n\n**Examples**\n\n```mytonctrl\nol\nol --json\nol hash\n```\n\n### `od`\n\n**Purpose:** Diff a proposal’s configuration against the current config.\n\n**Syntax**\n\n```mytonctrl\nod <offer-hash>\n```\n\n**Behavior**\n\n- Fetches the offer, runs lite-client commands to dump the proposed config, and shows a `diff` between the current value and the proposal. The `diff` utility must be available in the command shell to run this command.\n\n**Example**\n\n```mytonctrl\nod xKF+2Cj4wP6w2y...\n```\n\n### `cl`\n\n**Purpose:** List validator complaints for the current or previous round.\n\n**Syntax**\n\n```mytonctrl\ncl [past] [--json] [adnl]\n```\n\n**Behavior**\n\n- With no flags, prints complaint entries with election ID, validator ADNL (trimmed unless `adnl` is supplied), fine, vote count, approval percent, and pass status (color-coded).\n- `past` switches to the previous election round; `--json` dumps raw data.\n\n**Examples**\n\n```mytonctrl\ncl\ncl past adnl\ncl --json\n```\n\n## Election data\n\n### `el`\n\n**Purpose:** Inspect election entries submitted by validators.\n\n**Syntax**\n\n```mytonctrl\nel [past] [--json] [adnl] [pubkey] [wallet]\n```\n\n**Behavior**\n\n- The default view shows trimmed ADNL/pubkey/wallet values along with stake and max-factor.\n- Add `past` to see the previous round, `--json` for raw output, or the literals `adnl`, `pubkey`, `wallet` to disable trimming for those columns.\n\n**Examples**\n\n```mytonctrl\nel\nel past adnl pubkey\nel --json\n```\n\n## Validator roster\n\n### `vl`\n\n**Purpose:** Print the validator list with optional filters and formats.\n\n**Syntax**\n\n```mytonctrl\nvl [past] [fast] [--json] [adnl] [pubkey] [wallet] [offline]\n```\n\n**Behavior**\n\n- Default view shows index, trimmed ADNL/pubkey/wallet, stake, efficiency, and online status (color-coded).\n- `past` loads the previous round; `fast` avoids extra lite-client calls for performance.\n- `--json` returns raw data. Passing `adnl`, `pubkey`, or `wallet` prevents trimming for those columns. `offline` filters to entries marked offline.\n\n**Examples**\n\n```mytonctrl\nvl\nvl fast offline\nvl past --json adnl\n```\n\n## Pool diagnostics\n\n### `get_pool_data`\n\n**Purpose:** Retrieve detailed pool contract data by name or address.\n\n**Syntax**\n\n```mytonctrl\nget_pool_data <pool-name|pool-addr>\n```\n\n**Behavior**\n\n- Accepts either a local pool alias (resolved via stored `.addr` file) or a base64 contract address.\n- Prints the JSON returned by `runmethodfull ... get_pool_data`, including stake, elector values, and state flags.\n\n**Example**\n\n```mytonctrl\nget_pool_data mypool\n```\n"
  },
  {
    "path": "ecosystem/nodes/cpp/mytonctrl/validator.mdx",
    "content": "---\ntitle: \"Validator\"\ndescription: \"Validator mode automates governance voting, election participation, efficiency tracking, and the local collator registry.\"\n---\n\n## Operational notes\n\n- These commands require `validator` mode to be enabled. They interact with the validator console and expect the validator wallet to be configured and funded.\n- Offer hashes, complaint hashes, and election identifiers come from `status`, lite-client, or governance dashboards. Use the exact strings reported there to avoid signature failures.\n- When managing collators, follow up with `setup_collator` (from collator mode) on the node that actually produces blocks. The validator-side registry maintained here determines which collators are accepted and how they behave during elections.\n\n## Governance and elections\n\n### `vo`\n\n**Purpose:** Vote for one or more governance offers (configuration proposals) using the validator wallet.\n\n**Syntax**\n\n```mytonctrl\nvo <offer-hash> [additional_offer_hashes...]\n```\n\n**Behavior**\n\n- Accepts one or more offer hashes exactly as reported by commands like `status` or `ol`. Hashes are typically base64 strings.\n- Fetches the full offer list, saves each voted offer locally for tracking, and submits signed votes through the validator wallet.\n- Skips unknown hashes and raises an error if the vote submission fails.\n\n**Example**\n\n```mytonctrl\nvo xKF+2Cj4wP6w2y... xKF+2Cj4wP6w2y...\n```\n\n### `ve`\n\n**Purpose:** Cast the validator election entry for the upcoming round.\n\n**Syntax**\n\n```mytonctrl\nve\n```\n\n**Behavior**\n\n- Runs the `Elections` helper from `mytoncore`, which prepares and sends the election request using the validator wallet.\n- Reuses configuration stored in the local database (stake amount, elector parameters, etc.).\n- Prints `VoteElectionEntry - OK` when the elector accepts the query.\n\n### `vc`\n\n**Purpose:** Vote on a validator complaint by pairing the election round with the complaint hash.\n\n**Syntax**\n\n```mytonctrl\nvc <election-id> <complaint-hash>\n```\n\n**Behavior**\n\n- `<election-id>` is the integer identifier of the round (from `status` or elector logs).\n- `<complaint-hash>` is usually base64 and matches the hash reported in complaint notifications.\n- Delegates to `VoteComplaint`, which signs and broadcasts the vote via the validator wallet.\n\n**Example**\n\n```mytonctrl\nvc 345678901234567890 xFFmZ...Y\n```\n\n## Performance diagnostics\n\n### `check_ef`\n\n**Purpose:** Review validator efficiency for the previous and current validation rounds.\n\n**Syntax**\n\n```mytonctrl\ncheck_ef\n```\n\n**Behavior**\n\n- Collects validator lists for the current and previous rounds, locates the local ADNL, and prints block production statistics.\n- Highlights time ranges for each round, shows created versus expected masterchain blocks, and colorizes efficiency percentages (green when ≥90%).\n- Warns when efficiency data is unavailable (e.g., when the validator joined as a shard-only participant or the round has just started).\n\n## Local collator registry\n\n### `add_collator`\n\n**Purpose:** Add a collator entry to the validator console’s collator list and configure optional behaviors.\n\n**Syntax**\n\n```mytonctrl\nadd_collator <adnl-id> <workchain>:<shard_hex> [--self-collate true|false] [--select-mode random|ordered|round_robin]\n```\n\n**Behavior**\n\n- `<adnl-id>` accepts base64 or hex. Hex values are automatically converted to base64 before storing.\n- `<workchain>:<shard_hex>` identifies the shard (e.g., `0:2000000000000000`). Use the same format shown in the validator console output.\n- If the shard already exists in the collator list, the command appends the ADNL and optionally updates `self_collate` or `select_mode`. Otherwise, it creates a new shard entry using defaults (`self_collate=true`, `select_mode=random`).\n- Persists the updated list using `set-collators-list` so the validator console starts assigning work to the new collator.\n\n**Example**\n\n```mytonctrl\nadd_collator 2F3C7A...B91 0:2000000000000000 --self-collate true --select-mode ordered\n```\n\n### `delete_collator`\n\n**Purpose:** Remove one or more collator entries from the validator console list.\n\n**Syntax**\n\n```mytonctrl\ndelete_collator [<workchain>:<shard_hex>] <adnl-id>\n```\n\n**Behavior**\n\n- Accepts an optional shard selector. When omitted, the ADNL is removed from every shard where it appears.\n- `<adnl-id>` can be base64 or hex; hex values are converted automatically.\n- After removal, the command cleans up empty shard sections in the stored collator list.\n\n**Examples**\n\n```mytonctrl\ndelete_collator 0:2000000000000000 2F3C7A...B91\ndelete_collator 2F3C7A...B91\n```\n\n### `print_collators`\n\n**Purpose:** Inspect the current collator list and optional liveness information.\n\n**Syntax**\n\n```mytonctrl\nprint_collators [--json]\n```\n\n**Behavior**\n\n- By default, prints the human-readable output from `show-collators-list`, augmented with online/offline status when `collation-manager-stats` provides data.\n- With `--json`, returns the parsed collator list in JSON format, matching the structure passed to `set-collators-list`.\n\n**Examples**\n\n```mytonctrl\nprint_collators\nprint_collators --json\n```\n\n### `reset_collators`\n\n**Purpose:** Clear the entire collator list stored in the validator console.\n\n**Syntax**\n\n```mytonctrl\nreset_collators\n```\n\n**Behavior**\n\n- Calls `clear-collators-list` and removes all shard/ADNL mappings.\n- Reports an error if the console rejects the reset; otherwise, prints `reset_collators - OK`.\n"
  },
  {
    "path": "ecosystem/nodes/cpp/mytonctrl/wallet.mdx",
    "content": "---\ntitle: \"Wallet\"\ndescription: \"Wallet mode provides convenience utilities for generating, activating, importing, exporting, and moving funds between TON wallets managed by MyTonCtrl.\"\n---\n\n## Operational notes\n\n- MyTonCtrl stores wallets under `/var/ton-work/wallets`. Back up `.pk` files securely before deleting or migrating wallets.\n- Generated wallet names follow the `wallet_###` pattern. Use `wl` to find the correct name before funding or exporting.\n- Bookmark support depends on entries configured via other modules (for example, utility commands that register shortcuts).\n- Transfers rely on the validator console and may require the wallet to be active with sufficient rent balance (>0.1 TON).\n\n## Wallet lifecycle\n\n### `nw`\n\n**Purpose:** Create a new local wallet definition and show its deployment address.\n\n**Syntax**\n\n```mytonctrl\nnw [<workchain-id> <wallet-name> [<version> <subwallet>]]\n```\n\n**Behavior**\n\n- With no arguments, autogenerates a name (`wallet_XXX`), uses workchain `0`, selects version `v1`, and derives subwallet `698983191 + workchain`.\n- When arguments are provided, you must supply the workchain and name; optional `version` (`v1`, `v2`, `v3`) and `subwallet` override defaults.\n- Writes `.addr`/`.pk` files under the wallets directory and prints a table with the new wallet address (state-init form).\n\n**Examples**\n\n```mytonctrl\nnw\nnw 0 treasury v3 1001\n```\n\n### `aw`\n\n**Purpose:** Deploy one wallet or all wallets that have unsigned deployment BoCs.\n\n**Syntax**\n\n```mytonctrl\naw [<wallet-name>|all]\n```\n\n**Behavior**\n\n- Without arguments, treats the request as `all` and scans every wallet for pending deployment BoCs, sending them if the target address still has a positive balance.\n- With a wallet name, activates that specific wallet using the stored deployment message.\n\n**Examples**\n\n```mytonctrl\naw\naw wallet_005\n```\n\n### `wl`\n\n**Purpose:** List every wallet known to MyTonCtrl along with its on-chain status.\n\n**Syntax**\n\n```mytonctrl\nwl\n```\n\n**Behavior**\n\n- Prints Name, Status, Balance, Version, Workchain, and Address (current or init address if inactive).\n- Useful for auditing balances before elections or sweeping idle funds.\n\n### `dw`\n\n**Purpose:** Delete a wallet’s local files after operator confirmation.\n\n**Syntax**\n\n```mytonctrl\ndw <wallet-name>\n```\n\n**Behavior**\n\n- Prompts `Are you sure you want to delete this wallet (yes/no):` and only proceeds on `yes`.\n- Removes the `.addr`, `.pk`, and cached query files for `<wallet-name>` but does not touch on-chain accounts.\n\n**Example**\n\n```mytonctrl\ndw treasury\n```\n\n## Importing, exporting, and metadata\n\n### `iw`\n\n**Purpose:** Import an existing wallet by address and secret key.\n\n**Syntax**\n\n```mytonctrl\niw <wallet-addr> <wallet-secret-key-base64>\n```\n\n**Behavior**\n\n- Writes the provided address bytes and base64-encoded private key into a new local wallet (name auto-generated).\n- Prints the assigned wallet name for subsequent commands.\n\n**Example**\n\n```mytonctrl\niw EQDk...cQ KJ4Q...\n```\n\n### `ew`\n\n**Purpose:** Export a wallet’s address and secret key.\n\n**Syntax**\n\n```mytonctrl\new <wallet-name>\n```\n\n**Behavior**\n\n- Reads the `.pk` file, base64-encodes it, and prints the address/key pair along with the wallet name.\n- Useful for backups or migration to hardware wallets.\n\n**Example**\n\n```mytonctrl\new treasury\n```\n\n### `swv`\n\n**Purpose:** Update the recorded wallet version (v1/v2/v3) for an imported wallet.\n\n**Syntax**\n\n```mytonctrl\nswv <wallet-addr> <wallet-version>\n```\n\n**Behavior**\n\n- Updates metadata so MyTonCtrl selects the correct Fift script when sending transactions.\n- Supply the wallet address exactly as stored (base64 or workchain:hex) and the version string.\n\n**Example**\n\n```mytonctrl\nswv EQC0...FQ v3\n```\n\n## Fund transfers\n\n### `mg`\n\n**Purpose:** Send Toncoin from a local wallet to a destination address or bookmark.\n\n**Syntax**\n\n```mytonctrl\nmg <wallet-name> <account-addr|bookmark> <amount> [additional-flags...]\n```\n\n**Behavior**\n\n- `<amount>` accepts numeric TON values or the shortcuts `all` (sends balance minus fees) and `alld` (sends entire balance, including fees).\n- Automatically checks the source balance, destination bounceability, and wallet version. Add `-n` to force non-bounceable mode or other validator-console flags as needed.\n- Submits the signed transfer via the validator console; prints `MoveCoins - OK` on success.\n\n**Examples**\n\n```mytonctrl\nmg treasury EQDv...Qw 1500\nmg treasury bookmark_main all -n\n```\n\n### `mgtp`\n\n**Purpose:** Relay a payment through two temporary proxy wallets before reaching the destination.\n\n**Syntax**\n\n```mytonctrl\nmgtp <wallet-name> <account-addr|bookmark> <amount>\n```\n\n**Behavior**\n\n- Creates two temporary wallets, hops the transfer through them (`wallet -> proxy1 -> proxy2 -> destination`), and cleans up afterward.\n- Ensures the final leg includes `-n` (non-bounceable) to safely reach inactive recipients.\n- Handy when the destination cannot accept a direct bounceable transfer.\n\n**Example**\n\n```mytonctrl\nmgtp treasury EQC6...rA alld\n```\n"
  },
  {
    "path": "ecosystem/nodes/cpp/run-validator.mdx",
    "content": "---\ntitle: \"Run a validator\"\ndescription: \"Run a validator node with MyTonCtrl\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\nimport { Image } from '/snippets/image.jsx';\n\n## Overview\n\nThis guide explains how to run a validator TON node with MyTonCtrl from scratch.\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-30.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-30.png\"\n  alt=\"Architecture\"\n/>\n\n## Step 1: Prepare environment\n\n### 1.1 Maintain costs and expenses\n\n- 200 TON per month on the validator hot wallet for its operational transactions.\n- Validator deposit stake [700 000 TON \\~ 4 000 000 TON](/ecosystem/nodes/cpp/run-validator#step-4:-set-optimal-stake-for-validator).\n- 100 TB/month traffic at a peak load.\n\n### 1.2 Minimal hardware requirements\n\n- 16-core CPU (for example, Intel Xeon E-2388G or equivalent)\n- 128 GB RAM\n- 2 × 1.92 TB NVMe SSD, each with 250,000+ read IOPS and 83,000+ write IOPS\n- 1 Gbit/s network connectivity\n- Fixed (static) public IP address\n\n<Aside type=\"tip\">\n  A 1 Gbit/s network connection is recommended to ensure reliable performance during peak load conditions. The average expected bandwidth usage is approximately 100 Mbit/s.\n\n  Validators must carefully consider IOPS disk requirements, as insufficient storage performance can severely impact validator stability and overall network health. Prefer faster NVMe drives — validator performance depends heavily on disk speed.\n</Aside>\n\n### 1.3 Software requirements\n\n- Ubuntu 22.04 LTS or 24.04 LTS\n- Python 3.10 or higher\n- Clang 16.0.0 or higher\n\n```bash\n# Check Ubuntu version\ncat /etc/os-release\n```\n\n```bash\n# Check Python version\npython3 --version\n```\n\n```bash\n# Check Clang version\nclang --version\n```\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-3.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-3.png\"\n  alt=\"Versions output\"\n/>\n\n<Accordion\n  title=\"Update Clang...\"\n>\n  ```bash\n  # Check Clang version\n  clang --version\n  # If version 16, skip the steps below.\n\n  # Required for Ubuntu 22.04. Update current Clang to clang-16\n  sudo apt update\n  sudo apt install -y lsb-release wget software-properties-common gnupg\n  sudo wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -\n  wget https://apt.llvm.org/llvm.sh\n  chmod +x llvm.sh\n  sudo ./llvm.sh 16 clang\n\n  # Change default Clang\n  sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-16 100\n  sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-16 100\n\n  # Required for Ubuntu 24.04. Install clang-16\n  sudo apt install -y clang-16\n\n  ```\n</Accordion>\n\n### 1.4 Port forwarding for validator\n\nConfigure the network on the server according to the following:\n\n- All outgoing connections are allowed.\n- A static external IP address.\n- [One UDP port open for incoming connections.](/ecosystem/nodes/cpp/run-validator#2-4-verify-validator’s-port)\n\n### 1.5 Follow network announcements\n\nSubscribe and follow the instructions provided for validators with Telegram channels.\n\n<Aside type=\"tip\">\n  Do not ignore announcements for TON Testnet; validators that violate the maintenance rules are fined and excluded from the network.\n</Aside>\n\n| Channel                                      | Network     |\n| -------------------------------------------- | ----------- |\n| [@tonstatus](https://t.me/tonstatus)         | TON Mainnet |\n| [@testnetstatus](https://t.me/testnetstatus) | TON Testnet |\n\n### 1.6 Prepare validator user\n\nPrepare and log in a user for the validator.\n\n1. Create a non-root user\n\n   ```bash\n   # Create a non-root validator user\n   sudo adduser <USERNAME>\n   sudo usermod -aG sudo <USERNAME>\n   ```\n\n1. Switch to it by reconnecting to the server via `ssh`\n\n   ```bash\n   #reconnect as the new user\n   exit\n   ssh <USERNAME>@<SERVER_IP>\n   ```\n\n### 1.7 Benchmark server performance\n\nBefore installing, verify that the server meets performance requirements. Inadequate disk or network performance is the most common cause of validator instability.\n\n#### Network latency\n\nCheck latency to TON beacon nodes. Expect approximately 50 milliseconds to the nearest beacon and up to 300 milliseconds to the farthest:\n\n```bash\nping beacon-eu-01.toncenter.com -c 6\nping beacon-apac-01.toncenter.com -c 6\n```\n\n#### Disk IOPS\n\nInstall `fio` and run a random read/write benchmark:\n\n```bash\nsudo apt install -y fio\nfio --randrepeat=1 --ioengine=libaio --max-jobs=16 --direct=1 --gtod_reduce=1 --name=test --bs=4k --iodepth=64 --readwrite=randrw --rwmixread=75 --size=10G --filename=/tmp/bench\nrm /tmp/bench\n```\n\nRun the benchmark on the same disk where validator data will be stored (`/var/ton-work/`). If `/tmp` is on a different filesystem, replace `/tmp/bench` with a path on the target drive.\n\nMinimum acceptable results:\n\n| Metric | Minimum             |\n| ------ | ------------------- |\n| Read   | 250k IOPS, 981 MB/s |\n| Write  | 83k IOPS, 327 MB/s  |\n\n<Aside\n  type=\"caution\"\n>\n  If disk performance is below these thresholds, the validator may fail to keep up with the network. Upgrade storage before proceeding.\n</Aside>\n\n#### Network bandwidth\n\nVerify network throughput with `speedtest-cli`:\n\n```bash\nsudo apt install -y speedtest-cli\nspeedtest-cli\n```\n\nEnsure download and upload speeds meet the [1 Gbit/s requirement](/ecosystem/nodes/cpp/run-validator#1-2-minimal-hardware-requirements).\n\n### 1.8 Harden server security\n\n<Aside\n  type=\"caution\"\n  title=\"Security baseline\"\n>\n  A compromised validator server puts staked funds at risk. Apply these hardening steps before exposing the server to the network.\n</Aside>\n\n#### SSH hardening\n\nApply the following SSH configuration changes in `/etc/ssh/sshd_config`:\n\n- Enable key-based authentication and disable password login:\n\n```text\nPasswordAuthentication no\nPubkeyAuthentication yes\n```\n\n- Disable root login:\n\n```text\nPermitRootLogin no\n```\n\n- Change the default SSH port:\n\n```text\nPort <SSH_PORT>\n```\n\n`<SSH_PORT>` — a non-default port number (for example, `2222`).\n\n- Restrict SSH access to specific IP addresses using the `Match Address` directive:\n\n```text\nMatch Address <ALLOWED_IP>\n  AllowUsers <USERNAME>\n```\n\nRestart the SSH service after changes:\n\n```bash\nsudo systemctl restart sshd\n```\n\n#### Firewall configuration\n\nEnable the firewall and allow only the SSH port. The validator UDP port is added after installation in [step 2.5](/ecosystem/nodes/cpp/run-validator#2-5-check-validator's-port).\n\n```bash\nsudo ufw allow <SSH_PORT>/tcp\nsudo ufw enable\nsudo ufw status\n```\n\n#### Additional security measures\n\n- Use a unique, strong password for the root user.\n\n- Set a GRUB bootloader password to prevent unauthorized boot modifications.\n\n- Enable Fail2ban for SSH brute-force protection:\n\n  ```bash\n  sudo apt install -y fail2ban\n  sudo systemctl enable fail2ban\n  sudo systemctl start fail2ban\n  ```\n\n- Configure two-factor authentication for SSH using `libpam-google-authenticator` or a similar PAM module.\n\n#### Encrypt sensitive directories (optional)\n\nFor additional protection, store validator keys and configuration on an encrypted partition. Create an encrypted volume and symlink the [backup directories](/ecosystem/nodes/cpp/run-validator#5-5-organize-validator-backup) from it.\n\n<Aside type=\"tip\">\n  After moving directories to the encrypted partition, create symlinks in their original locations so that MyTonCtrl and the validator service continue to function without path changes.\n</Aside>\n\n## Step 2: Validator node installation\n\n### 2.1 Download validator installer (MyTonCtrl)\n\nRun:\n\n```shell\nwget https://raw.githubusercontent.com/ton-blockchain/mytonctrl/master/scripts/install.sh\n```\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-4.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-4.png\"\n  alt=\"Downloading MyTonCtrl\"\n/>\n\n### 2.2 Run validator installation\n\nRun the validator installation. Installation takes approximately 20 minutes:\n\n<CodeGroup>\n  ```shell Mainnet\n  sudo bash install.sh -m single-nominator -n mainnet\n  ```\n\n  ```shell Testnet\n  sudo bash install.sh -m single-nominator -n testnet\n  ```\n</CodeGroup>\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-5.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-5.png\"\n  alt=\"Expected final output for validator installation\"\n/>\n\n<Accordion\n  title=\"Speed up initial sync with a database dump...\"\n>\n  To reduce synchronization time from hours to minutes, download a pre-built database dump instead of syncing from peers. Check the [dump index](https://dump.ton.org/) for available snapshots.\n\n  1. Install `aria2` and `plzip` if not already present:\n\n     ```bash\n     sudo apt install -y aria2 plzip\n     ```\n\n  1. Stop the validator and MyTonCore services:\n\n     ```bash\n     sudo systemctl stop mytoncore.service\n     sudo systemctl stop validator.service\n     ```\n\n  1. Download and extract the dump:\n\n     ```bash\n     cd /var/ton-work/\n     aria2c -x 16 https://dump.ton.org/dumps/latest.tar.lz\n     mv /var/ton-work/db /var/ton-work/db_old\n     mkdir /var/ton-work/db\n     plzip -d -c /var/ton-work/latest.tar.lz | tar -xvf - -C /var/ton-work/db\n     ```\n\n  1. Restore configuration and keys from the original database:\n\n     ```bash\n     cp /var/ton-work/db_old/config.json /var/ton-work/db/config.json\n     cp -r /var/ton-work/db_old/keyring /var/ton-work/db/keyring\n     sudo chown -R validator:validator /var/ton-work/db\n     ```\n</Accordion>\n\n### 2.3 Verify status results\n\nLaunch MyTonCtrl with the command `mytonctrl`. Then, check synchronization using the `status` command:\n\n```sh\nmytonctrl\nMyTonCtrl> status\n```\n\nVerify that the correct modes are enabled:\n\n```bash\nMyTonCtrl> status_modes\n```\n\nExpected output should show `validator` and `single-nominator` as enabled, with all other modes disabled.\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-2.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-2.png\"\n  alt=\"MyTonCtrl status results\"\n/>\n\n<Aside type=\"tip\">\n  Initially, the status shows \"Local validator initial sync status: downloading blockchain state x\", which indicates that the node has started synchronization.\n  There are also other status messages in the very beginning of the synchronization, such as \"starting\", \"init block seqno\", \"last key block is x\", \"downloading all shard states\", \"mc seqno\" - all these statuses are fine.\n</Aside>\n\n### 2.4 Verify validator's port\n\nPrint `engine.addr` port configuration `config.json` file:\n\n```bash\ngrep -A5 '\"addrs\"' -n /var/ton-work/db/config.json | grep '\"port\"' | head -1\n```\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-26.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-26.png\"\n  alt=\"Print validator port\"\n/>\n\n### 2.5 Check validator's port\n\nMake sure UDP `engine.addr` port is allowed with the following command:\n\n```bash\nsudo ufw status\n```\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-25.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-25.png\"\n  alt=\"Check allowed ports\"\n/>\n\nIf the port is filtered (absent in allowed), open this port:\n\n```bash\nsudo ufw allow <PORT_NUMBER>/udp\n```\n\nThen make sure with `sudo ufw status`.\n\n### 2.6 Verify node synchronization\n\nWait until the node is fully synchronized, which takes approximately 3 hours (depending on the network connection). Check the field `Local validator initial sync status: x`, the value x should become less than 20.\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-8.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-8.png\"\n  alt=\"Verify node synchronization in status\"\n/>\n\n<Aside type=\"tip\">\n  Set up [alert bot](/ecosystem/nodes/cpp/integrating-with-prometheus) to receive a notification when the node is synchronized.\n</Aside>\n\n## Step 3: Configure validator\n\nWhen installing, MyTonCtrl automatically creates a validator wallet. Top up and activate (deploy) this wallet so MyTonCtrl can operate the single nominator pool smart contract with it.\n\n### 3.1 Get validator wallet address\n\n```sh\nMyTonCtrl> wl\n```\n\nFind the wallet named `validator_wallet_001` and its address.\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-7.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-7.png\"\n  alt=\"Print validator wallet list\"\n/>\n\n### 3.2 Back-up validator wallet secret key\n\n<Aside\n  type=\"caution\"\n>\n  This private key is required to restore access to the funds stored in the validator wallet. It is not involved in managing rewards or staking.\n</Aside>\n\nMake a backup of the validator wallet secret key:\n\n```sh\nMyTonCtrl> ew validator_wallet_001\n```\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-11.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-11.png\"\n  alt=\"Back-up validator wallet\"\n/>\n\n<Aside type=\"tip\">\n  Import this secret key with [`iw`](/ecosystem/nodes/cpp/mytonctrl/wallet#iw) command.\n</Aside>\n\n### 3.3 Explore validator wallet\n\nExplore validator wallet by address with [Tonviewer](https://tonviewer.com/):\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-6.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-6.png\"\n  alt=\"Explore validator wallet\"\n/>\n\n### 3.4 Credit validator wallet\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  Ensure precise handling of operations, carefully verifying the addresses for `single_nominator_pool`, `owner_address`, and `validator_wallet`. Any incorrect deposit processing may result in the permanent and unrecoverable loss of funds.\n</Aside>\n\nCredit the validator wallet. Ensure that at least 200 TON per month is available in the validator’s wallet to cover operational fees.\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-9.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-9.png\"\n  alt=\"Credit validator wallet\"\n/>\n\n### 3.5 Activate the wallet\n\nActivate (deploy on-chain) validator wallet, run:\n\n```sh\nMyTonCtrl> aw validator_wallet_001\n```\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-12.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-12.png\"\n  alt=\"Activate validator wallet command result\"\n/>\n\nThat also reflects in Tonviewer; the status will be displayed as `Active`\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-14.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-14.png\"\n  alt=\"Validator wallet in explorer\"\n/>\n\n### 3.6 Create a pool\n\nCreate a [single nominator pool](https://docs.ton.org/v3/documentation/smart-contracts/contracts-specs/single-nominator-pool) for secure stake management. As the `owner-address`, specify the beneficiary wallet address that will stake the owner's funds and receive rewards.\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  Use a cold wallet (e.g., Ledger) for the `owner-address` and store its seed phrase securely to keep funds safe. If access to the owner's wallet is lost, access to stake and rewards funds cannot be recovered.\n</Aside>\n\n```bash\nMyTonCtrl> new_single_pool <pool-name> <owner-address>\n```\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-15.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-15.png\"\n  alt=\"Create a single pool\"\n/>\n\n<Accordion\n  title=\"If a single nominator pool already exists...\"\n>\n  If a single-nominator pool is already created, import it with:\n\n  ```bash\n  MyTonCtrl> import_pool <pool-name> <pool-addr>\n  ```\n</Accordion>\n\n### 3.7 Print pool list\n\nExplore pool addresses using `pools_list` command:\n\n```bash\nMyTonCtrl> pools_list\n```\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-16.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-16.png\"\n  alt=\"Pool list result\"\n/>\n\nAt the moment, the pool hasn't been deployed yet, and Explorer will display this as `Nonexist` status\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-17.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-17.png\"\n  alt=\"Nonexist pool\"\n/>\n\n### 3.8 Activate pool\n\nActivate the single pool nominator contract:\n\n```bash\nMyTonCtrl> activate_single_pool <pool-name>\n```\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-18.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-18.png\"\n  alt=\"Activate the pool result\"\n/>\n\n### 3.9 Verify activated pool\n\nMake sure the pool becomes activated with `pools_list`:\n\n```bash\nMyTonCtrl> pools_list\n```\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-19.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-19.png\"\n  alt=\"Pool list\"\n/>\n\n[Blockchain explorer](/ecosystem/explorers/overview) should also display the now-deployed contract with `Active` status.\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-20.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-20.png\"\n  alt=\"Find pool in explorer\"\n/>\n\n<Aside\n  type=\"caution\"\n>\n  After activation, verify the following in a [blockchain explorer](/ecosystem/explorers/overview):\n\n  1. The pool contract code hash matches the [official single nominator pool contract](https://github.com/orbs-network/single-nominator/blob/main/README.md).\n  1. The owner address stored in the pool matches the address specified during creation.\n\n  Skipping these checks may result in funds being sent to an incorrect or malicious contract.\n</Aside>\n\n### 3.10 Test deposit to pool\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  Ensure precise handling of operations, carefully verifying the addresses for `single_nominator_pool`, `owner_address`, and `validator_wallet`. Any incorrect deposit processing may result in the permanent and unrecoverable loss of funds.\n</Aside>\n\nTest deposit to stake workflow. Any user can deposit to the pool via a standard direct TON transfer.\nCredit decent sum around 10 TON:\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-21.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-21.png\"\n  alt=\"Test deposit 1\"\n/>\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-22.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-22.png\"\n  alt=\"Test deposit 2\"\n/>\n\n### 3.11 Test withdrawal from pool\n\nTest withdrawal workflow. Only the [owner's cold wallet](/ecosystem/nodes/cpp/run-validator#3-6-create-a-pool) can request a withdrawal.\nSend a withdrawal request, a message with `w` comment from `owner` wallet to the single nominator pool address:\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-24.jpg\"\n  width=\"280\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-24.jpg\"\n  alt=\"Send withdrawal request\"\n/>\n\n<Accordion\n  title=\"Withdraw with script...\"\n>\n  Insert the single nominator pool address to `SINGLE_NOMINATOR_ADDRESS` and send this message from the owner's wallet.\n\n  ```js Not runnable\n  import {\n    Address,\n    beginCell,\n    internal,\n    storeMessageRelaxed,\n    toNano,\n  } from \"@ton/core\";\n\n  async function main() {\n    const single_nominator_address = Address.parse(\"SINGLE_NOMINATOR_ADDRESS\");\n    const WITHDRAW_OP = 0x1000;\n    const amount = 50000;\n\n    const messageBody = beginCell()\n      .storeUint(WITHDRAW_OP, 32)\n      .storeUint(0, 64)\n      .storeCoins(amount)\n      .endCell();\n\n    const internalMessage = internal({\n      to: single_nominator_address,\n      value: toNano(\"1\"),\n      bounce: true,\n      body: messageBody,\n    });\n  }\n\n  ```\n</Accordion>\n\nOnce the deposit is restored (except 1 TON reserve on the single nominator pool) to the owner's wallet, that means validator are set securely and ready for real stake:\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-23.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-23.png\"\n  alt=\"Pool list\"\n/>\n\n## Step 4: Set optimal stake for validator\n\nTop up the single nominator pool with the effective validation stake. In the next elections, MyTonCtrl will automatically use this pool for staking. Aim for a stake that places the validator between positions 200 and 250 in the [validator index](https://tonscan.org/validators).\n\n<Aside type=\"tip\">\n  If the pool's balance is sufficient to participate in both rounds `balance > min_stake_amount * 2`, MyTonCtrl will automatically participate in both rounds using `stake = balance / 2`, unless the stake is manually set using the `set stake` command. This behavior differs from using a nominator pool but resembles staking with a validator wallet.\n</Aside>\n\n### 4.1 Retrieve stakes for last two cycles\n\nCheck the current validator stakes on [tonscan.org/validators](https://tonscan.org/validators) and the minimum network stake in the [network config](https://tonviewer.com/config).\n\nRetrieve `min_stake` and `max_stake` from [Validation API](https://elections.toncenter.com/getValidationCycles?return_participants=false\\&offset=0\\&limit=2) for two last cycles.\n\n<Accordion\n  title=\"See expected result...\"\n>\n  <Image\n    src=\"/resources/images/nodes/run-validator/run-validator-28.png\"\n    darkSrc=\"/resources/images/nodes/run-validator/run-validator-28.png\"\n    alt=\"Cycle info API response\"\n  />\n</Accordion>\n\nFor example:\n\n```json Not runnable\n\"cycle_id\" : 1764052744,\n\"min_stake\": 701812111528562,  // ~ 701 812 TON\n\"max_stake\": 2008570202020000, // ~ 2 008 570 TON\n```\n\n```json Not runnable\n\"cycle_id\" : 1764052744,\n\"min_stake\": 674810775114391,  // ~ 674 811 TON\n\"max_stake\": 2024432325343173, // ~ 2 024 432 TON\n```\n\n<Aside type=\"tip\">\n  Values retrieved in nanotons, divide this by $10^9$ to get TON units.\n</Aside>\n\n### 4.2 Retrieve stakes boundary values\n\nTo cover the approximate expected stake for odd and even cycles, choose the maximum between the two `min_stake` and the maximum between the two `max_stake`.\n\nFor example:\n\n```text Not runnable\n// largest within 701 812 TON and 674 811 TON\navg_min_stake = 701812\n\n// largest within 2 008 570 TON and 2 024 432 TON\navg_max_stake = 2024432\n```\n\n### 4.3 Calculate effective stakes\n\n<Aside type=\"tip\">\n  _Effective_ stands for winning elections for both odd and even cycles.\n</Aside>\n\nEffective stake for two cycles is a value between the doubled maximum and the minimum average stakes:\n\n```text Not runnable\navg_min_stake * 2 <= effective_stake <= avg_max_stake * 2\n```\n\nFor example:\n\n```text Not runnable\n// twice the average minimum stake\nmin_expected_effective_stake = 1403624\n\n// twice the average maximum stake\nmax_expected_effective_stake = 4048864\n```\n\nThen, the effective stake is approximately:\n\n```text Not runnable\n1403624 TON <= effective_stake <= 4048864 TON\n```\n\n### 4.4 Deposit effective stake\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  Ensure precise handling of operations, carefully verifying the addresses for `single_nominator_pool`, `owner_address`, and `validator_wallet`.\n  Any incorrect deposit processing may result in the permanent and unrecoverable loss of funds.\n</Aside>\n\nDeposit effective stake to the single nominator pool address.\n\n### 4.5 Track first cycle progress\n\nIn the next election cycle (odd/even), MyTonCtrl will send half of the stake from the single nominator pool. Track this with a [blockchain explorer](/ecosystem/explorers/overview).\n\n### 4.6 Track second cycle progress\n\nIn the next paired election cycle (even/odd), MyTonCtrl will send the second half of the stake from the single nominator pool. Track this with a [blockchain explorer](/ecosystem/explorers/overview).\n\n### 4.7 Verify entire staking cycle\n\nThe reward for the odd validation cycle will be returned to the single nominator pool, combined with the stake. Verify this with a blockchain explorer. A few minutes after the reward is accepted, MyTonCtrl initiates a re-stake of this stake, including the reward.\n\n<Image\n  src=\"/resources/images/nodes/run-validator/run-validator-29.png\"\n  darkSrc=\"/resources/images/nodes/run-validator/run-validator-29.png\"\n  alt=\"One cycle staking history\"\n/>\n\n**Legend**\n\n1. Stake for odd cycle.\n1. Reward for odd cycle.\n1. Reinvestment of the odd cycle stake, including the reward in the next odd cycle.\n\n### 4.8 Switch to daily maintenance\n\nMake sure pair stakes are appropriately circulated, then focus on monitoring validator health and updates.\n\n## Step 5: Maintain validator\n\n### 5.1 Fund the validator hot wallet\n\nKeep at least 200 TON on the validator hot wallet. This balance covers operational fees for approximately one month.\n\nTo check the current balance:\n\n```bash\nMyTonCtrl> wl\n```\n\n### 5.2 Top up the single nominator pool\n\nBefore sending funds to the pool:\n\n- Verify that the pool address is correct and uses the **bounceable** format.\n- Confirm that the pool smart contract is still active and not frozen. A pool can become frozen if the entire balance is consumed by storage fees between creation and funding.\n- Follow the [test deposit and withdrawal procedure](/ecosystem/nodes/cpp/run-validator#3-10-test-deposit-to-pool) before depositing the full stake.\n\n<Aside type=\"tip\">\n  By default, MyTonCtrl splits the pool balance 50/50 between odd and even validation cycles. Ensure the total stake is sufficient to participate in both cycles: `balance > min_stake * 2`.\n</Aside>\n\nIf the pool does not pick up the deposit automatically, push it manually:\n\n```bash\nMyTonCtrl> mg validator_wallet_001 <POOL_ADDRESS> 5\n```\n\n`<POOL_ADDRESS>` — the bounceable address of the single nominator pool.\n\n### 5.3 Withdraw funds from the pool\n\nOnly the owner wallet can withdraw funds. Follow the [test withdrawal procedure](/ecosystem/nodes/cpp/run-validator#3-11-test-withdrawal-from-pool) using the same method.\n\n### 5.4 Follow the TON announcements channel\n\nFollow the [@tonstatus](https://t.me/tonstatus) channel, turn on notifications, and be prepared for urgent updates if needed.\n\n### 5.5 Organize validator backup\n\nBack up the following paths to an encrypted, off-site location:\n\n- `/var/ton-work/db/config.json`\n- `/var/ton-work/db/keyring`\n- `/var/ton-work/keys`\n- `/usr/local/bin/mytoncore` (includes wallet files such as `validator_wallet_001.pk` and `validator_wallet_001.addr`)\n\n<Aside\n  type=\"danger\"\n>\n  Store backups in an encrypted format in a secure location. Loss of these files means loss of access to the validator and staked funds.\n</Aside>\n\nAlternatively, use the built-in MyTonCtrl backup:\n\n```bash\nMyTonCtrl> create_backup\n```\n\n### 5.6 Set up alerting\n\nSet up alerting in MyTonCtrl to get a notification of critical issues with the validator. For more information, see [MyTonCtrl private alerting bot](/ecosystem/nodes/cpp/mytonctrl/alerting) or check [MyTonCtrl public alerting bot](https://t.me/validators).\n\n### 5.7 Set up monitoring\n\nSet up monitoring dashboards for RAM, disk, network, CPU usage, and other metrics.\n\n- For on-chain validator metrics, use the [`ton-validators-metrics` system](https://github.com/the-ton-tech/ton-validators-metrics).\n- For system-level metrics, [integrate Prometheus with `node_exporter` with MyTonCtrl](/ecosystem/nodes/cpp/integrating-with-prometheus).\n- For technical assistance, contact [@mytonctrl\\_help\\_bot](https://t.me/mytonctrl_help_bot).\n\n### 5.8 Monitor the efficiency\n\nSet up dashboards to monitor validators using the APIs provided below.\n\n1. Track penalized validators on each round with [@tonstatus\\_notifications](https://t.me/tonstatus_notifications).\n1. Use [Validation API](https://elections.toncenter.com/docs) to obtain information about current and past validation rounds (cycles) - including the timing of rounds, which validators participated, their stakes, and more. Information regarding current and past elections for each validation round is also available.\n1. Use this [API](https://toncenter.com/api/qos/index.html#/) to obtain information about the efficiency of validators over time.\n\n<Aside type=\"tip\">\n  This API analyzes data from the catchain to provide an estimate of a validator's efficiency. It serves as an alternative to the `checkloadall` utility.\n  Unlike `checkloadall`, limited to validation rounds, this API supports any time interval for efficiency analysis.\n</Aside>\n\n**Workflow**\n\n1. Check ADNL address of the validator:\n\n   ```bash\n   MyTonCtrl> status\n   ```\n\n1. To the API, provide the ADNL address of the validator along with a time interval (`from_ts`, `to_ts`). For accurate results, choose a sufficient interval, such as 18 hours ago to the present moment.\n\n1. Retrieve the result. If the efficiency percentage is below 90%, the validator is malfunctioning.\n\n1. The validator must actively participate in validation and use the same ADNL address throughout the specified time period. For example, if a validator contributes to validation every second round, indicate the intervals during which they participated. Failing to do so may result in an inaccurate underestimate. This requirement applies not only to masterchain validators (with an index \\< 100) but also to other validators (with an index > 100).\n\n### 5.9 Learn slashing policy\n\nIf a validator processes less than 90% of the expected blocks during a validation round, they will be fined 101 TON.\n\nLearn more about the [slashing policy](https://old-docs.ton.org/v3/documentation/nodes/validation/staking-incentives#decentralized-system-of-penalties).\n\n### 5.10 Maintain validator\n\nStay vigilant on updates, monitor health status, and efficiency stability with dashboards.\n\n## Verify\n\nAfter completing the setup, confirm the validator is operating correctly:\n\n```bash\nMyTonCtrl> status\n```\n\nCheck the following indicators:\n\n| Indicator                        | Expected value                          |\n| -------------------------------- | --------------------------------------- |\n| Local validator out of sync      | Less than 20 seconds                    |\n| Masterchain out of sync          | Less than 20 seconds                    |\n| Validator efficiency             | Above 90%                               |\n| Validator index                  | Visible in status output                |\n| Validator participation position | Between 200 and 250 for optimal staking |\n\n<Aside type=\"tip\">\n  Validator efficiency may show 0% at the beginning of a cycle until the validator signs its first blocks. This is normal behavior.\n</Aside>\n\nConfirm that the validator participates in elections and recovers stakes on time by monitoring the pool balance in a [blockchain explorer](https://tonviewer.com/).\n\nConfirm that the validator participates in elections and recovers stakes on time by checking the pool balance in a [blockchain explorer](/ecosystem/explorers/overview). For greater observability, [set up the monitoring](/ecosystem/nodes/cpp/run-validator#5-7-set-up-monitoring) of various validator metrics.\n\n## Troubleshoot common issues\n\n### Node is not synchronizing\n\n- Verify that the validator UDP port is open: `sudo ufw status`.\n- Check network connectivity to beacon nodes: `ping beacon-eu-01.toncenter.com -c 6`.\n- Ensure disk IOPS meet minimum requirements. Re-run the [benchmark](/ecosystem/nodes/cpp/run-validator#disk-iops).\n- Check service logs: `journalctl -u validator -f`.\n\n### Validator efficiency is below 90%\n\n- Confirm the node is fully synchronized (`Local validator out of sync` \\< 20).\n- Check disk performance. Slow storage is the most common cause of low efficiency.\n- Verify that no other resource-intensive processes compete for CPU or RAM.\n- Review hardware against [minimum requirements](/ecosystem/nodes/cpp/run-validator#1-2-minimal-hardware-requirements).\n\n### Pool is not participating in elections\n\n- Confirm that the pool is activated: `MyTonCtrl> pools_list` should show `Active` status.\n- Verify the pool has sufficient balance for at least one cycle: `balance > min_stake`.\n- Check that `single-nominator` mode is enabled: `MyTonCtrl> status_modes`.\n- Ensure the validator wallet has enough TON for operational fees.\n\n### Stake was not returned after a validation cycle\n\n- Wait for the full cycle to complete. Stake recovery is not immediate.\n- Check the elector contract status using a [blockchain explorer](/ecosystem/explorers/overview).\n- Contact [@mytonctrl\\_help\\_bot](https://t.me/mytonctrl_help_bot) if the stake is not returned after the cycle ends.\n\n### Pool contract is frozen\n\nA pool contract may freeze if its entire balance is consumed by storage fees. This happens when too much time passes between pool creation and funding. Ensure you fund the pool promptly after activation.\n\n## Support\n\nContact technical support [@mytonctrl\\_help\\_bot](https://t.me/mytonctrl_help_bot). This bot is for validators only and will not assist with questions for regular nodes.\n"
  },
  {
    "path": "ecosystem/nodes/cpp/setup-mylocalton.mdx",
    "content": "---\ntitle: \"Setting up a local blockchain using MyLocalTon\"\ndescription: \"Install MyLocalTon to spin up a self-contained TON network for development and testing.\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\n\nMyLocalTon packages validator nodes, a lite-server, explorer, and optional HTTP API into a single JAR so you can prototype locally without touching mainnet. Use it for integration tests, smart-contract dry runs, and demos before deploying to public networks.\n\n## Prerequisites\n\n- Java Development Kit (JDK) 21 or newer in your `PATH`.\n- Python 3.9-3.12 if you plan to enable the optional HTTP API bridge.\n- On Windows, install the Microsoft Visual C++ 2015+ x64 Redistributable.\n- Allocate at least 4 CPU cores, 16 GB RAM, and 20 GB of free disk space for smooth operation.\n\n## Download and install\n\n### Windows\n\n1. Install the Visual C++ Redistributable.\n1. Download the JAR that matches your architecture from the [MyLocalTon releases](https://github.com/neodix42/MyLocalTon/releases).\n   - `MyLocalTon-x86-64.jar` for x86-64 systems.\n   - `MyLocalTon-arm64.jar` for ARM64 systems.\n\n### macOS and Linux\n\n```bash\n# x86-64\nwget https://github.com/neodix42/MyLocalTon/releases/latest/download/MyLocalTon-x86-64.jar\n# ARM64\nwget https://github.com/neodix42/MyLocalTon/releases/latest/download/MyLocalTon-arm64.jar\n```\n\n### Build from source\n\n```bash\nsudo apt install openjdk-21-jdk ant maven\ngit clone https://github.com/neodix42/MyLocalTon.git\ncd MyLocalTon\nmvn clean package assembly:single\n```\n\nThe JAR with all dependencies appears under `target/` when the build finishes.\n\n## Launch the local network\n\n```bash\njava -jar MyLocalTon-x86-64.jar\n```\n\nUseful arguments:\n\n| Flag                     | Description                                                   |\n| ------------------------ | ------------------------------------------------------------- |\n| `nogui`                  | Run in headless mode without the Swing interface.             |\n| `with-validators=<N>`    | Start `N` validator instances (default: 1).                   |\n| `explorer`               | Launch the bundled block explorer.                            |\n| `ton-http-api`           | Start the HTTP API bridge (requires Python + `ton-http-api`). |\n| `custom-binaries=<PATH>` | Load TON binaries from a custom directory.                    |\n| `ip.addr.X.X`            | Bind services to a specific local IP.                         |\n| `debug`                  | Increase log verbosity for troubleshooting.                   |\n\nThe first run creates the `myLocalTon/` workspace alongside the JAR. Validators, liteserver certificates, and logs live in this directory.\n\n## Connect CLI tools\n\nMyLocalTon prints the lite-server public key during startup and stores certificates in `./myLocalTon/genesis/bin/certs/`.\n\n```bash\nlite-client -a 127.0.0.1:4443 -b E7XwFSQzNkcRepUC23J2nRpASXpnsEKmyyHYV4u/FZY= -c last\nvalidator-engine-console \\\n  -a 127.0.0.1:4441 \\\n  -k $(pwd)/myLocalTon/genesis/bin/certs/client \\\n  -p $(pwd)/myLocalTon/genesis/bin/certs/server.pub\n```\n\n## Enable the HTTP API bridge\n\n<Aside type=\"caution\">On Windows, install [OpenSSL v1.1.1](https://slproweb.com/products/Win32OpenSSL.html) first</Aside>\n\nInstall Python dependencies on the host system, then restart MyLocalTon with the `ton-http-api` flag or enable the \"Start TON Center\" toggle in UI.\n\n```bash\n# Linux\nsudo apt install -y python3 python3-pip\npip3 install --user ton-http-api\n\n# macOS (Homebrew)\nbrew install python3\npython3 -m ensurepip --upgrade\npip3 install --user ton-http-api\n\n# Windows\npy -3 -m ensurepip --upgrade\npy -3 -m pip install --user ton-http-api\n```\n\nThe bridge exposes REST endpoints that mirror the lite-server APIs for tooling that cannot speak the native ADNL protocol.\n\n## Monitor and maintain\n\n- Tail `myLocalTon/MyLocalTon.log` for application-level events.\n- Validator logs reside in `myLocalTon/genesis/db/log`.\n- Re-run with `debug` when reproducing issues.\n- Upgrade by downloading the latest JAR, replacing the existing file, and deleting the `myLocalTon` directory so the genesis state regenerates.\n\n## Troubleshooting tips\n\n| Symptom            | Resolution                                                                                                             |\n| ------------------ | ---------------------------------------------------------------------------------------------------------------------- |\n| JAR fails to start | Verify Java 21+ is installed and the file is not quarantined by the OS (macOS: `xattr -d com.apple.quarantine <JAR>`). |\n| HTTP API errors    | Ensure Python 3.9-3.12 and `ton-http-api` are installed.                                                               |\n| Need a clean reset | Stop the process, delete the `myLocalTon` folder, and restart the JAR to regenerate the network.                       |\n\n## Where to go next\n\n- Graduate to production setups with [Setting up a node using MyTonCtrl](/ecosystem/nodes/cpp/setup-mytonctrl).\n- Explore node roles and responsibilities in the [node overview](/ecosystem/nodes/overview).\n"
  },
  {
    "path": "ecosystem/nodes/cpp/setup-mytonctrl.mdx",
    "content": "---\ntitle: \"Run a node with MyTonCtrl\"\ndescription: \"Provision hardware, install MyTonCtrl, and follow runbooks for validator, liteserver, or archive roles.\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside\n  type=\"caution\"\n  title=\"Handle validator keys like production secrets.\"\n>\n  Keep recovery phrases offline, restrict shell access, and rehearse new procedures on testnet before touching wallets that hold real stake.\n</Aside>\n\n## Plan the environment\n\n### Supported operating systems\n\nMyTonCtrl is tested on the following distributions (choose one and keep it up to date):\n\n- Ubuntu 22.04 LTS or 24.04 LTS\n- Debian 11 or 12\n\nAlways create and use a non-root operator with `sudo` access—running MyTonCtrl as root leads to subtle permission failures later on.\n\n### Hardware sizing by role\n\n| Role                | CPU                                       | RAM    | Storage                                  | Network         | Traffic                              | Notes                                                            |\n| ------------------- | ----------------------------------------- | ------ | ---------------------------------------- | --------------- | ------------------------------------ | ---------------------------------------------------------------- |\n| Full/validator node | 16 dedicated cores (32 threads preferred) | 128 GB | ≥1 TB NVMe SSD or provisioned 64k+ IOPS  | ≥1 Gbps up/down | 64 TB/month typical (peaks \\~100 TB) | Leave headroom for elections and snapshots.                      |\n| Liteserver          | 16 cores                                  | 128 GB | ≥1 TB NVMe SSD                           | ≥1 Gbps         | \\~16 TB/month peaks                  | Hetzner/OVH are acceptable for liteservers (not for validators). |\n| Archive liteserver  | 16 cores                                  | 128 GB | ≥12 TB NVMe or ZFS pool with compression | ≥1 Gbps         | ≥16 TB/month                         | Plan for continuous growth; monitor ZFS capacity.                |\n\n> Disk latency is the common bottleneck. Benchmark storage before going live (`MyTonCtrl> benchmark`).\n\n### Network and ports\n\n- Obtain a static public IPv4 address for each node.\n- Forward a single UDP port (default 30303) from the internet to the node and leave all outbound ports open. Verify exposure with `netstat -tulpn` and third-party scanners.\n- Update cloud security groups or on-prem firewalls after installation—use `MyTonCtrl> about validator` / `about liteserver` to confirm the chosen port.\n\n### Recommended providers\n\nThe TON Foundation validates the following instances for validator-class workloads:\n\n| Cloud Provider | Instance Type                 | CPU      | RAM    | Storage             | Network       | Public IP          | Traffic     |\n| -------------- | ----------------------------- | -------- | ------ | ------------------- | ------------- | ------------------ | ----------- |\n| GCP            | `n2-standard-16`              | 32 vCPUs | 128 GB | 1 TB NVMe SSD       | 16 Gbps       | Static external IP | 64 TB/month |\n| Alibaba Cloud  | `ecs.g6.4xlarge`              | 32 vCPUs | 128 GB | 1 TB NVMe SSD       | Up to 10 Gbps | Elastic IP         | 64 TB/month |\n| Tencent Cloud  | `M5.4XLARGE`                  | 32 vCPUs | 128 GB | 1 TB NVMe SSD       | Up to 10 Gbps | Elastic IP         | 64 TB/month |\n| Vultr          | Bare metal Intel E-2388G      | 16C/32T  | 128 GB | 1.92 TB NVMe SSD    | 10 Gbps       | Fixed              | 64 TB/month |\n| DigitalOcean   | General purpose premium Intel | 32 vCPUs | 128 GB | 1 TB NVMe SSD       | 10 Gbps       | Fixed              | 64 TB/month |\n| Latitude       | `c3.medium.x86`               | 16C/32T  | 128 GB | 1.9 TB NVMe SSD     | 10 Gbps       | Fixed              | 64 TB/month |\n| AWS            | `i4i.8xlarge`                 | 32 vCPUs | 256 GB | 2×3.75 TB Nitro SSD | Up to 25 Gbps | Elastic IP         | 64 TB/month |\n\n### Prepare the operator account\n\nIf you still need a dedicated operator, create and switch to it before installing MyTonCtrl:\n\n```bash\nsudo adduser <USERNAME>\nsudo usermod -aG sudo <USERNAME>\n# reconnect as the new user\nssh <USERNAME>@<SERVER_IP>\n```\n\n## Install MyTonCtrl\n\nRun the installer from the operator account with `sudo` so it can create system users and services:\n\n```bash\nsudo apt update\nsudo apt install -y curl wget git ca-certificates python3-pip\nwget https://raw.githubusercontent.com/ton-blockchain/mytonctrl/master/scripts/install.sh\nsudo bash install.sh -d\n```\n\nThe interactive wizard walks through:\n\n1. Selecting mainnet vs. testnet (or supplying a custom `global.config.json`).\n1. Choosing the initial mode (`validator` or `liteserver`).\n1. Optionally downloading blockchain dumps via TON Storage (recommended for archive builds).\n1. Whether to run post-download tasks in the background (useful when pulling large dumps).\n\nRefer to the [MyTonCtrl overview](/ecosystem/nodes/cpp/mytonctrl/overview#install-mytonctrl) for installer flags and environment variables when you need unattended deployments.\n\n### Verify services and synchronization\n\n```bash\nmytonctrl\nMyTonCtrl> status\nMyTonCtrl> status_fast\nMyTonCtrl> status_modes\n```\n\n- `status` shows the long-form report, including `Local validator initial sync status`—wait for it to read `synchronized` before switching roles.\n- `status_fast` prints live metrics such as `timeDiff` and `Local validator out of sync`; both should trend toward zero on a healthy node.\n- `status_modes` confirms which modes are currently enabled.\n\nAfter installation, verify ownership so MyTonCtrl and validator processes can access state and keys:\n\n```bash\nsudo chown -R validator:validator /var/ton-work/db\nsudo chown -R <install_user>:<install_user> /var/ton-work/keys\n```\n\n### Baseline maintenance tasks\n\n- `MyTonCtrl> create_backup` and `restore_backup` safeguard your configs and keys—run before upgrades and after major changes.\n- `MyTonCtrl> set sendTelemetry true` sends telemetry to the MyTonCtrl developers so they can surface TON status alerts and diagnose emerging issues.\n- `MyTonCtrl> update` followed by `upgrade` applies MyTonCtrl and binary updates; schedule regular maintenance windows.\n- `MyTonCtrl> settings_status` reviews every setting, its owner mode, and the current value.\n- Use `tail -F /var/ton-work/log*` and `journalctl -u validator -f` during troubleshooting; reduce verbosity again if you temporarily ran `installer set_node_argument --verbosity 3`.\n\n## Validator quickstart\n\n**You need:** a fully synchronized node, validator mode not active elsewhere, and at least the current minimum stake (approximately 300,000 TON; check [tonscan.com/validation](https://tonscan.com/validation) for live numbers).\n\n### Prepare the validator wallet (one-time)\n\n1. List existing wallets: `MyTonCtrl> wl`. The installer usually creates `validator_wallet_001`.\n\n1. If you need a dedicated wallet, create one (example):\n\n   ```bash\n   MyTonCtrl> nw 0 validator_wallet v3 1001\n   ```\n\n1. Fund the wallet, inspect recent activity with `vas <wallet_name>`, then activate it:\n\n   ```bash\n   MyTonCtrl> aw validator_wallet\n   ```\n\n1. Tell MyTonCtrl which wallet to use for elections:\n\n   ```bash\n   MyTonCtrl> set validatorWalletName \"validator_wallet\"\n   MyTonCtrl> get validatorWalletName\n   ```\n\n1. Export and store the private key offline: `MyTonCtrl> ew validator_wallet`.\n\nNeed more wallet operations? See the [wallet command reference](/ecosystem/nodes/cpp/mytonctrl/wallet).\n\n### Enable validator mode\n\nDisable conflicting roles (liteserver cannot run alongside validator) and switch modes:\n\n```bash\nMyTonCtrl> disable_mode liteserver\nMyTonCtrl> enable_mode validator\nMyTonCtrl> status_modes\nMyTonCtrl> about validator\n```\n\nConfirm that `validator` shows as enabled and note the advertised ADNL port for firewall rules.\n\n### Configure staking policy\n\nAssign either a fixed stake or a percentage of wallet balance:\n\n```bash\nMyTonCtrl> set stake 500000\n# or\nMyTonCtrl> set stakePercent 99\n```\n\n`get stake` / `get stakePercent` display the stored values; adjust before each election window if your balance changes.\n\n### Election routine\n\nUse the same sequence every election cycle (automate with cron if desired):\n\n```bash\nMyTonCtrl> status_fast\nMyTonCtrl> ve\nMyTonCtrl> check_ef\n```\n\n- Wait until `Local validator out of sync` is below 20 before running `ve`.\n- `ve` submits election messages, `check_ef` reports the previous and current round efficiency.\n- MyTonCtrl automatically splits balances into two stakes when the Elector accepts your bid; withdrawals become available in the following election per protocol rules.\n\n### Operational discipline\n\n- Track network announcements via [`@tonstatus`](https://t.me/tonstatus) and enable notifications.\n- Keep hardware aligned with the [minimum system requirements](#hardware-sizing-by-role); upgrade storage promptly if metrics show saturation.\n- Leave telemetry enabled (`set sendTelemetry true`) so telemetry continues reaching the MyTonCtrl developers and they can warn the community about issues.\n- Monitor RAM, disk, CPU, and bandwidth dashboards. Contact [`@mytonctrl_help_bot`](https://t.me/mytonctrl_help_bot) if metrics or efficiency drop below target.\n- Re-run `check_ef` or consult the [efficiency API](https://toncenter.com/api/qos/index.html#/) when diagnosing performance.\n\n## Liteserver quickstart\n\n**You need:** a synchronized full node with validator mode disabled (liteserver cannot run alongside validator on the same machine).\n\n### Activate liteserver services\n\n```bash\nMyTonCtrl> enable_mode liteserver\nMyTonCtrl> status_modes\n```\n\n### Configure endpoints and proxies\n\n```bash\nMyTonCtrl> installer\nInstaller> enable LS\nInstaller> plsc\nInstaller> exit\n```\n\n- `enable LS` deploys the liteserver daemon.\n- `plsc` prints the client bundle—share it with `/var/ton-work/keys/liteserver.pub` so lite-clients can connect.\n- Regenerate configs at any time with `installer clcf`.\n\n### Open the liteserver port\n\n1. Check the port in `/var/ton-work/db/config.json` (within the `liteservers` array).\n\n1. Update security groups or configure `ufw` on bare-metal hosts:\n\n   ```bash\n   sudo apt install -y ufw\n   sudo ufw allow ssh\n   sudo ufw allow <port>\n   sudo ufw enable\n   sudo ufw status\n   ```\n\n1. Confirm connectivity by initializing a lite-client using the generated config.\n\n### Ongoing care\n\n- Monitor `netLoadAvg` and CPU via `status_fast`; scale hardware before saturation.\n- Export `create_backup` after any config change so you can rapidly rebuild liteserver hosts.\n- Keep ports private—front them with VPNs or proxies when exposing to public users.\n\n## Archive liteserver quickstart\n\n**You need:** liteserver mode enabled, ≥12 TB of fast storage, and ZFS installed for handling compressed dumps.\n\n### Prepare storage with ZFS\n\n```bash\nsudo apt install -y zfsutils-linux\nsudo zpool create data <disk>\nsudo zfs set compression=lz4 data\nsudo zfs create data/ton-work\nsudo zfs set mountpoint=/var/ton-work data/ton-work\n```\n\nUse a dedicated SSD-backed pool and monitor free space—archive size grows continually (check the [archive dump index](https://archival-dump.ton.org/)).\n\n### Install and download archive data\n\n[Run the installer](#install-mytonctrl), choose `liteserver` mode, and answer **Yes (1)** when prompted to download archive blocks via TON Storage. Allow the job to continue in the background—the download may take days.\n\nTrack progress in MyTonCtrl logs and wait for `status` → `Local validator initial sync status` to report `synchronized` before serving traffic.\n\n### Troubleshooting imports\n\nIncrease verbosity temporarily to review archive import logs, then revert:\n\n```bash\nMyTonCtrl> installer set_node_argument --verbosity 3\ntail -f /var/ton-work/log*\n# ...review output...\nMyTonCtrl> installer set_node_argument --verbosity 1\n```\n\nIf you see repeated `Importing archive ... from net` messages, investigate storage latency—IOPS may be insufficient.\n\n### Snapshot and recovery tips\n\n- Use ZFS snapshots (`zfs snapshot data/ton-work@<label>`) for fast rollbacks.\n- To restore, stop services before `zfs rollback`: `sudo systemctl stop validator`.\n- Keep off-site backups of `/var/ton-work/keys` and `create_backup` archives.\n\n## Monitoring and support\n\n- Subscribe to [`@tonstatus`](https://t.me/tonstatus) and [`@tonstatus_notifications`](https://t.me/tonstatus_notifications) for real-time validator alerts.\n- Use the private alert bot once your node is stable: `MyTonCtrl> enable_mode alert-bot` then configure credentials per the [alerting guide](/ecosystem/nodes/cpp/mytonctrl/alerting).\n- Contact validator support via [`@validators_help_bot`](https://t.me/validators_help_bot); regular node operators can use [`@ton_node_help`](https://t.me/ton_node_help).\n- Audit node health weekly: `status_fast`, `check_ef`, disk usage (`du -sh /var/ton-work/db`), and snapshot consistency.\n\nOnce comfortable with these workflows, dive into the [detailed command references](/ecosystem/nodes/cpp/mytonctrl/overview) for advanced automation.\n"
  },
  {
    "path": "ecosystem/nodes/overview.mdx",
    "content": "---\ntitle: \"Blockchain nodes overview\"\nsidebarTitle: \"Overview\"\ndescription: \"Pick the right TON node setup and understand the operational work it requires.\"\n---\n\nA full node is a software that stores the whole blockchain state locally, opposite to lite-clients, which request small pieces of data from liteservers when needed. It does not solve any problem itself, but provides a base for other services requiring a full blockchain state (validator, liteserver, etc). Usually, full nodes keep only the latest part of the blockchain state, which is vital for ensuring client applications' network stability and operation. Full nodes _prune_ the state of the TON blockchain they keep. This means the full node automatically removes earlier blocks that become unnecessary for the network to manage its data volume effectively. To allow client applications to look for blocks and transactions and send new transactions into the TON blockchain, full nodes are equipped with the liteserver functionality.\n\n## Full node modes\n\n| Role               | What it does                                                                                   | When to use it                                                                                       |\n| ------------------ | ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |\n| Liteserver         | Stores the latest shards, tracks the masterchain, and serves data to lite-clients.             | Required for custom infrastructure, analytics, or to back your own APIs.                             |\n| Archive liteserver | Stores all blockchain data, including old blocks and states.                                   | Required for explorers and other services working with historical data.                              |\n| Validator          | Signs blocks, participates in elections, and earns rewards.                                    | Needed to run validation with your stake or to operate a nominator pool service.                     |\n| Collator           | Produces blocks for validators.                                                                | Needed to reduce load on your validators by setting up block creation on a separate machine.         |\n| Nominator pool     | Accepts funds from stakers and runs a validator with their stake.                              | Needed when you want to securely accept stakes from multiple parties and share rewards between them. |\n| Single nominator   | Secure way to run a validator without depositing all funds to a hot wallet.                    | Generally, you should use it each time you want to run a new validator.                              |\n| Liquid staking     | Same as nominator pool, but exchanges stakers' funds for a synthetic token to be used in DeFi. | Needed to run a liquid staking protocol.                                                             |\n\n## Do you need your own node?\n\n- **Run your own full node** when you need guaranteed uptime or to serve high-volume workloads without third-party rate limits. Validators and staking services need to install a node and activate validator mode.\n- **Rely on public endpoints** when building prototypes or light integrations. Community liteservers and APIs such as [TON Center](/ecosystem/api/toncenter) or other [RPC providers](/ecosystem/api/overview) already expose the blockchain for read access and transaction submission.\n\n## Pick your target environment\n\n| If you need                             | Run                                                                                                                                                                                                                      |\n| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| Validator or nominator capacity         | [Setting up a node using MyTonCtrl](/ecosystem/nodes/cpp/setup-mytonctrl) with the validator, nominator pool, or single nominator workflows; the wrapper automates validator wallets, overlays, elections, and upgrades. |\n| Liteserver APIs                         | [Setting up a node using MyTonCtrl](/ecosystem/nodes/cpp/setup-mytonctrl) with liteserver option (and archive mode if needed) to expose API for applications.                                                            |\n| An isolated development network         | [Setting up a local blockchain using MyLocalTon](/ecosystem/nodes/cpp/setup-mylocalton) to spin up a local shard, explorer, and APIs for rapid iterations with no mainnet impact.                                        |\n| Kubernetes-native production operations | [Use Rust node chart workflows](/ecosystem/nodes/rust/quick-start) and references.                                                                                                                                       |\n\n## Rust node overview\n\nTON Rust node is an alternative implementation of a TON full node written in Rust. It is protocol-compatible with TON and follows an operational model designed for containerized environments rather than single-instance deployments.\n\nRust node operational focus:\n\n- container-based architecture;\n- Kubernetes-native deployment model;\n- deterministic, version-pinned builds with automated release validation;\n- node lifecycle management within a cluster environment;\n- integration with external key management systems such as [HashiCorp Vault](https://www.hashicorp.com/en/products/vault).\n\nRust node is designed for:\n\n- node providers operating multiple full nodes, liteservers, or validators;\n- staking operators managing one or many validators as cluster resources;\n- operators running node infrastructure that requires external key management integration and structured operational processes.\n\nThis model targets predictable scaling: infrastructure growth is handled through standardized deployment patterns, centralized control, and safer upgrade workflows.\n\n### Advantages\n\n- Multi-node deployment and centralized management: a new node can be launched in minutes, excluding sync time, using standardized Helm workflows.\n- Fully tested container delivery: release images are version-pinned and validated by more than 10 automated test suites before publication.\n- Built-in observability: Rust node exposes Prometheus metrics across 8 subsystems and serves `/healthz` and `/readyz` from the same metrics HTTP server.\n- Grafana-ready workflow: a bundled dashboard and documented Prometheus/Grafana integration are provided for Kubernetes deployments.\n- Key isolation: validator wallet and ADNL keys are designed for Vault-backed workflows instead of direct in-node private key storage.\n\n### Rust node resource recommendations\n\nRecommended Kubernetes requests and limits are:\n\n| Role                   | CPU request | CPU limit | Memory request | Memory limit |\n| ---------------------- | ----------- | --------- | -------------- | ------------ |\n| Full node / liteserver | 8           | 16        | 32GiB          | 64GiB        |\n| Validator              | 16          | 32        | 64GiB          | 128GiB       |\n\nThe node can run on fewer resources, but these values provide headroom for load spikes such as elections, heavy traffic, and catch-up after restarts.\n\nSource: [TON Rust Node resource recommendations](https://github.com/RSquad/ton-rust-node/blob/e8bd0451b326099146a90a913beedaebd952fa56/helm/ton-rust-node/docs/resources.md).\n\n## Full node\n\n**The full node** is a basic node type within the TON blockchain. It serves as the backbone of the TON blockchain by keeping its block history — in other words, its _current state_.\n\nCompared to **archive nodes**, full nodes keep only the latest part of the blockchain state, which is vital for ensuring client applications' network stability and operation. Full nodes _prune_ the state of the TON blockchain they keep. This means the full node automatically removes earlier blocks that become unnecessary for the network to manage its data volume effectively.\n\nTo allow client applications to look for blocks and transactions and send new transactions into the TON blockchain, full nodes are equipped with the liteserver functionality.\n\n## Archive node\n\nThe archive node is a full node that keeps the entire block history of the TON blockchain. These nodes act as the decentralized point of truth to ensure consistency of the whole blockchain history. They are a backend for blockchain explorers and other applications relying on deep transaction history.\n\nArchive nodes do not prune the blockchain state, elevating system requirements, especially in storage. According to the latest estimations, while full and validator nodes require about 1 TB of disk space, archive nodes need about 12 TB to store the complete block history.\n\n## Validator node\n\n**Validator nodes** or **validators** are the TON network participants who propose new blocks and verify transactions according to the TON's _proof-of-stake_ mechanism. In this way, validators contribute to the overall blockchain security.\n\nValidators get rewards in TON for successful participation in the validation process.\n\nTo be entitled to propose and validate blocks, other participants elect validators based on the amount of TON they hold — in other words, their _stake_. The more TON a validator stakes, the higher its chances of being elected, validating blocks for the network, and earning rewards. As a rule, validator operators motivate other TON holders to stake with them to get passive income from the resulting rewards. In this way, validators ensure network stability and security and contribute to its growth.\n\n## Interacting with TON nodes\n\nTON nodes can run in **liteserver mode**, which allows external applications to interact with the TON blockchain. In this mode, the nodes process client requests, enabling clients to access blockchain data, send transactions, and retrieve information about blocks and transactions.\n\nFull and archive nodes typically enable liteserver mode because they store blockchain history and handle external requests. In contrast, validator nodes do not need it, as they focus on efficiently validating new blocks without additional workload from external queries. Use MyTonCtrl to [enable liteserver mode in a full or archive C++ node](/ecosystem/nodes/cpp/setup-mytonctrl#liteserver-quickstart).\n\nLiteserver mode, or _liteserver_ for short, uses the Abstract Datagram Network Layer (ADNL) protocol. Direct connections require either a client called _lite-client_ downloaded from the [latest TON release](https://github.com/ton-blockchain/ton/releases/latest), or a library that understands ADNL. In the [SDK table](/ecosystem/sdks), such libraries have a mark in the ADNL column.\n\nTo connect from a webpage or otherwise interact with TON nodes over HTTP, an HTTP-to-ADNL frontend is required. [TON Center](/ecosystem/api/toncenter/introduction) is an official HTTP API provider, and its API endpoints can be used directly or [self-hosted](/ecosystem/api/overview). In the [SDK table](/ecosystem/sdks), libraries that use these endpoints or other HTTP providers have a mark in the HTTP column.\n"
  },
  {
    "path": "ecosystem/nodes/rust/architecture.mdx",
    "content": "---\ntitle: \"Architecture reference\"\nsidebarTitle: \"Architecture\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nTON Rust node Helm chart deploys the following Kubernetes resources:\n\n- A `StatefulSet` named after the release, with `podManagementPolicy: Parallel` and `fsGroup: 1000`.\n- One per-replica ADNL `Service` (default type: `LoadBalancer`) with `externalTrafficPolicy: Local` and optional static IP assignment. Additional per-replica Services are created for enabled `control`, `liteserver`, and `jsonRpc` ports, and a shared `<release>-metrics` `ClusterIP` Service is created when `ports.metrics` is enabled.\n- An init container (configured by `initImage`, default `alpine:3.21`) that seeds configs from mounted volumes into the main persistent volume claim (PVC).\n- `PersistentVolumeClaim` (PVC) resources: `main`, `db`, `keys`, and optionally `logs` (controlled by `storage.logs.enabled`).\n- `ConfigMap` resources for global config, logs config, and optional bootstrap files: `basestate` (base state, `basestate.boc`) and `zerostate` (zero state, `zerostate.boc`).\n- A `Secret` for per-node JSON configs.\n\nAll resource names are prefixed with the release name, so multiple installations can run in one namespace.\n\n## Volumes and mounts\n\nThe node uses persistent volumes:\n\n| Volume | Mount path | Purpose                                                                                                       | Optional                     |\n| ------ | ---------- | ------------------------------------------------------------------------------------------------------------- | ---------------------------- |\n| `main` | `/main`    | Working directory: node config, global config, logs config, static files (`basestate` and `zerostate` hashes) | No                           |\n| `db`   | `/db`      | Blockchain database (largest volume, grows over time)                                                         | No                           |\n| `logs` | `/logs`    | Rolling log files (`output.log`, rotated by `logsConfig`)                                                     | Yes (`storage.logs.enabled`) |\n| `keys` | `/keys`    | Node keys and vault                                                                                           | No                           |\n\n## Storage recommendations\n\n<Aside\n  type=\"caution\"\n  title=\"Important\"\n>\n  Disk performance is critical for correct node operation. The `db` volume requires storage that can sustain up to 64,000 input/output operations per second (IOPS). Insufficient disk performance causes sync delays, missed validations, and degraded node behavior. Use NVMe or high-performance SSD with a local volume provisioner.\n</Aside>\n\nThe `db` and `logs` volumes are performance-critical because they handle continuous heavy I/O from blockchain database operations and log writes. The chart recommends local storage with direct disk access (`local-path`, OpenEBS with Linux Logical Volume Manager (`LVM`) support, or similar local volume provisioners).\nNetwork-attached storage (Network File System (`NFS`), Ceph Reliable Autonomic Distributed Object Store (`RADOS`) block device (`RBD`), Amazon Elastic Block Store (`EBS`), and similar systems) adds latency and can significantly affect node performance and sync speed under high I/O workloads.\n\nThe `main` and `keys` volumes have minimal I/O load, so standard storage classes are usually sufficient. The chart recommends Longhorn v1 with replica count `3` for data safety. Longhorn v2 is currently not recommended for TON Rust Node workloads in the chart maintainers' current test scope.\n\n| Volume | Default size | Notes                                                                                                                                                                     |\n| ------ | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `db`   | `1Ti`        | Going below `500Gi` is not recommended. Size grows as blockchain state accumulates.                                                                                       |\n| `logs` | `150Gi`      | Default [log](/ecosystem/nodes/rust/logs-config) rotation is 25 GB per file with 4 rotations. Volume size can be reduced if rolling file limits are adjusted accordingly. |\n| `main` | `1Gi`        | Stores configs and static files. Default is sufficient.                                                                                                                   |\n| `keys` | `1Gi`        | Stores node keys and vault. Default is sufficient.                                                                                                                        |\n\n## Init container bootstrap flow\n\nBefore the node starts, the init container (configured by `initImage`, default `alpine:3.21`) prepares the `/main` volume:\n\n1. Copies `global.config.json` and `logs.config.yml` from seed `ConfigMap` volumes into `/main`.\n1. If `basestate` and `zerostate` files are provided, compute SHA-256 hashes and write files as `/main/static/<HASH>.boc`.\n1. Resolves pod index from pod name (for example, `my-node-2` -> `2`) and copies `node-2.json` from the node-config `Secret` to `/main/config.json`.\n1. Sets ownership to UID `1000` (non-root app user).\n\nSeed volumes (`ConfigMap` and `Secret`) are mounted read-only under `/seed/`:\n\n| Seed volume     | Mount path            | Source                                        |\n| --------------- | --------------------- | --------------------------------------------- |\n| `global-config` | `/seed/global-config` | `ConfigMap` with `global.config.json`         |\n| `logs-config`   | `/seed/logs-config`   | `ConfigMap` with `logs.config.yml`            |\n| `node-configs`  | `/seed/node-configs`  | `Secret` with `node-<INDEX>.json` per replica |\n| `basestate`     | `/seed/basestate`     | `ConfigMap` with `basestate.boc` (optional)   |\n| `zerostate`     | `/seed/zerostate`     | `ConfigMap` with `zerostate.boc` (optional)   |\n\n## Container command resolution\n\nThe main container command is selected automatically:\n\n| Order | Condition                                     | Command                         |\n| ----- | --------------------------------------------- | ------------------------------- |\n| 1     | `debug.sleep: true`                           | `sleep infinity`                |\n| 2     | `command` is set                              | custom command from `command`   |\n| 3     | both `basestate` and `zerostate` are provided | `node -c /main -z /main/static` |\n| 4     | otherwise                                     | `node -c /main`                 |\n\nConditions are evaluated in this order, and the first matching condition is used. When `command` is set, the chart runs exactly the command configured in `command`.\n\nFor `debug.sleep: true`, the chart uses a `busybox` image.\n\n## Config change detection\n\nThe pod annotation `rsquad.io/config-checksum` stores a SHA-256 checksum of all inline configs. Any config change triggers a pod restart.\n"
  },
  {
    "path": "ecosystem/nodes/rust/global-config.mdx",
    "content": "---\ntitle: \"How to configure global JSON file\"\nsidebarTitle: \"Global configuration\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nThe global config is a JSON file that specifies the configuration required for a node to connect to a TON network. All nodes in the same network use the same file.\n\n- [global.config.json](https://ton-blockchain.github.io/global.config.json) contains the configuration for the TON mainnet. It is included with the chart and used by default unless an override is provided.\n- [testnet-global.config.json](https://ton-blockchain.github.io/testnet-global.config.json) contains the configuration for the TON Testnet.\n\n## Configuration structure\n\nThe global config contains three top-level sections:\n\n| Section       | Purpose                                                            |\n| ------------- | ------------------------------------------------------------------ |\n| `dht`         | Bootstrap DHT nodes used to discover and connect to network peers. |\n| `liteservers` | Public liteserver endpoints used by lite clients.                  |\n| `validator`   | Network identity: zero state, init block, and hardfork references. |\n\n<Aside type=\"note\">\n  The global config is not templated or modified by Helm values. The file is passed to the node without changes.\n</Aside>\n\n### `dht`\n\n`dht` defines properties for bootstrap [distributed hash table (DHT)](https://en.wikipedia.org/wiki/Distributed_hash_table) servers used to find peers during initial node setup. It contains three parameters:\n\n- `k` and `a` – DHT configuration parameters. In a [Kademlia-based DHT](/foundations/whitepapers/ton#3-2-ton-dht-kademlia-like-distributed-hash-table):\n  - `k` – the maximum number of nodes stored in a routing bucket.\n  - `a` – parallel lookup parameter specifying the number of nodes queried concurrently during a DHT lookup operation.\n- `static_nodes` – an array of node objects. Each node includes:\n  - `@type` – node type; `dht.node`;\n  - `id` – node identifier;\n  - `addr_list` – address list object containing:\n    - `addrs` – array of address objects with `@type`, `ip`, and `port`;\n    - `version`, `reinit_date`, `priority`, `expire_at` – addresses version and lifecycle data.\n  - `version` – node version;\n  - `signature` – base64-encoded cryptographic signature of the node.\n\n```json\n \"dht\": {\n    \"@type\": \"dht.config.global\",\n    \"k\": 6,\n    \"a\": 3,\n    \"static_nodes\": {\n      \"@type\": \"dht.nodes\",\n      \"nodes\": [\n        {\n          \"@type\": \"dht.node\",\n          \"id\": {\n            \"@type\": \"pub.ed25519\",\n            \"key\": \"6PGkPQSbyFp12esf1NqmDOaLoFA8i9+Mp5+cAx5wtTU=\"\n          },\n          \"addr_list\": {\n            \"@type\": \"adnl.addressList\",\n            \"addrs\": [\n              {\n                \"@type\": \"adnl.address.udp\",\n                \"ip\": -1185526007,\n                \"port\": 22096\n              }\n            ],\n            \"version\": 0,\n            \"reinit_date\": 0,\n            \"priority\": 0,\n            \"expire_at\": 0\n          },\n          \"version\": -1,\n          \"signature\": \"L4N1+dzXLlkmT5iPnvsmsixzXU0L6kPKApqMdcrGP5d9ssMhn69SzHFK+yIzvG6zQ9oRb4TnqPBaKShjjj2OBg==\"\n        }\n      ]\n    }\n  }\n```\n\n### `liteservers`\n\n`liteservers` defines an array of public endpoints used by lite clients (not by the node itself) to retrieve blockchain data, including balances, transactions, blocks, and [network configuration](/foundations/config). Each server object has three properties:\n\n- `ip` – IP address of the server, represented as a signed 32-bit integer;\n- `port` – port number on which the server operates;\n- `id` – object representing the server’s identifier, with two properties:\n  - `@type` – type of the public key; `pub.ed25519`;\n  - `key` – server public key, represented as a base64-encoded string.\n\n```json\n\"liteservers\": [\n    {\n      \"ip\": 84478511,\n      \"port\": 19949,\n      \"id\": {\n        \"@type\": \"pub.ed25519\",\n        \"key\": \"n4VDnSCUuSpjnCyUk9e3QOOd6o0ItSWYbTnW3Wnn8wk=\"\n      }\n    },\n  ]\n```\n\n### `validator`\n\n`validator` defines global validator configuration parameters. It contains:\n\n- `@type` – configuration type; `validator.config.global`;\n- `zero_state` – reference to the zero blockchain state;\n- `init_block` – reference to the initial block used to start synchronization;\n- `hardforks` – array of hardfork reference points.\n\nThe `zero_state`, `init_block`, and each entry in `hardforks` include:\n\n- `workchain` – workchain identifier;\n- `shard` – shard identifier;\n- `seqno` – sequence number of the block;\n- `root_hash` – base64-encoded root hash of the block;\n- `file_hash` – base64-encoded file hash of the block.\n\n```json\n \"validator\": {\n    \"@type\": \"validator.config.global\",\n    \"zero_state\": {\n      \"workchain\": -1,\n      \"shard\": -9223372036854775808,\n      \"seqno\": 0,\n      \"root_hash\": \"F6OpKZKqvqeFp6CQmFomXNMfMj2EnaUSOXN+Mh+wVWk=\",\n      \"file_hash\": \"XplPz01CXAps5qeSWUtxcyBfdAo5zVb1N979KLSKD24=\"\n    },\n    \"init_block\": {\n      \"workchain\": -1,\n      \"shard\": -9223372036854775808,\n      \"seqno\": 46894135,\n      \"root_hash\": \"MEjmmhLPlG68mbTPnKYcP/Sz/MiMQBV2OsASBOzBv58=\",\n      \"file_hash\": \"u9rAtFQ+kUFEnOs3w8Y7punMTiyQTXf1bRfkSs8dG+0=\"\n    },\n    \"hardforks\": [\n      {\n        \"workchain\": -1,\n        \"shard\": -9223372036854775808,\n        \"seqno\": 8536841,\n        \"root_hash\": \"08Kpc9XxrMKC6BF/FeNHPS3MEL1/Vi/fQU/C9ELUrkc=\",\n        \"file_hash\": \"t/9VBPODF7Zdh4nsnA49dprO69nQNMqYL+zk5bCjV/8=\"\n      }\n    ]\n  }\n```\n\n## When to override\n\nIn most deployments, the global config does not require modification. A custom config is required only in the following cases:\n\n1. When using a testnet instead of mainnet, download the testnet config from [the official source](https://ton-blockchain.github.io/).\n1. When running a private network with custom DHT nodes and overlays, provide a custom config.\n1. When the bundled config becomes outdated, fetch a fresh copy. The official config may change over time, for example, updated DHT nodes or init blocks.\n\n## How to override\n\n1. Download the latest mainnet config:\n   ```bash\n   curl -o global.config.json https://ton-blockchain.github.io/global.config.json\n   ```\n1. Pass it to the Helm chart:\n\n   ```bash\n   helm install my-node ./helm/ton-rust-node \\\n     --set-file globalConfig=./global.config.json \\\n     ...\n   ```\n\nOr provide it inline in `values.yaml`:\n\n```yaml title=values.yaml\nglobalConfig: |\n  {\"@type\": \"config.global\", \"dht\": {...}, ...}\n```\n\nOr reference an existing ConfigMap:\n\n```yaml title=values.yaml\nexistingGlobalConfigMapName: my-global-config\n```\n\n## See also\n\n- [Configuration repository](https://ton-blockchain.github.io/)\n"
  },
  {
    "path": "ecosystem/nodes/rust/logs-config.mdx",
    "content": "---\ntitle: \"How to configure logging YAML file\"\nsidebarTitle: \"Logging configuration\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nThe TON node uses the [`log4rs` framework](https://docs.rs/log4rs/1.3.0/log4rs/) for logging.\n\nLogging is configured using a YAML file specified in the `log_config_name` field of the [node configuration](/ecosystem/nodes/rust/node-config). In the Helm chart, this file is mounted at `/main/logs.config.yml`.\n\nA default configuration is bundled with the chart at [`files/logs.config.yml`](https://github.com/RSquad/ton-rust-node/blob/master/helm/ton-rust-node/files/logs.config.yml) and is used if no custom configuration is provided. It can be overridden in one of the following ways:\n\n- inline in `values.yaml`;\n- from local file `--set-file logsConfig=path`;\n- by referencing an existing [ConfigMap](https://kubernetes.io/docs/concepts/configuration/configmap/).\n\n## Hot reload\n\nThe `refresh_rate` field instructs `log4rs` to periodically re-read the configuration file. This allows log levels to be changed without restarting the node – updates are applied within the specified interval.\n\n```yaml\nrefresh_rate: 30 seconds\n```\n\nSupported units: `seconds`, `minutes`, `hours`. If the field is omitted, the config is read only once at startup.\n\nThis feature can be used during production debugging: temporarily increase a logger’s level to `debug`, observe the output, then restore the original level without restarting the node.\n\n## Appenders\n\nAppenders define where logs are written. Each appender has a unique name, the YAML key, and a `kind`. Three kinds are supported: `rolling_file`, `console`, and `file`.\n\nA TON node can generate a large volume of logs, especially during synchronization, elections, and catch-up. Appender configuration and log levels should be selected accordingly.\n\n### `rolling_file`\n\nThe `rolling_file` appender is the default and recommended option for production. It writes logs to a file with automatic size-based rotation.\n\nThe chart creates a dedicated `logs` [`PersistentVolumeClaim`](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) for this appender, ensuring logs remain available locally. Rotation prevents uncontrolled disk usage.\n\n```yaml\nappenders:\n  rolling_logfile:\n    kind: rolling_file\n    path: /logs/output.log\n    encoder:\n      pattern: \"{d(%Y-%m-%d %H:%M:%S.%f)} {l} [{t}] {I}: {m}{n}\"\n    policy:\n      kind: compound\n      trigger:\n        kind: size\n        limit: 25 gb\n      roller:\n        kind: fixed_window\n        pattern: '/logs/output_{}.log'\n        base: 1\n        count: 4\n```\n\n- The `policy` section defines when and how rotation occurs.\n\n- Trigger: `size`\n\n  Rotates the log file when it reaches the configured size.\n\n  | Field   | Description                                                                       |\n  | ------- | --------------------------------------------------------------------------------- |\n  | `limit` | Maximum file size. Supported suffixes: `b`, `kb`, `mb`, `gb`, `tb`; e.g. `25 gb`. |\n\n- Roller: `fixed_window`\n\n  Renames archived files using a pattern with a sliding index.\n\n  | Field     | Required        | Description                                                                                  |\n  | --------- | --------------- | -------------------------------------------------------------------------------------------- |\n  | `pattern` | yes             | Archive filename template. `{}` is replaced by the index. Append `.gz` to compress archives. |\n  | `base`    | no; default `0` | Starting index                                                                               |\n  | `count`   | yes             | Maximum number of archive files                                                              |\n\n  Example configuration:\n\n  - `pattern: \"/logs/output_{}.log\"`\n  - `base: 1`\n  - `count: 4`\n\n  On rotation:\n\n  1. `output.log` is renamed to `output_1.log`\n  1. `output_1.log` → `output_2.log`\n  1. `output_2.log` → `output_3.log`\n  1. `output_3.log` → `output_4.log`\n  1. The previous `output_4.log` is deleted\n\n  Add `.gz` to the pattern to enable compression of archived logs:\n\n  ```yaml\n  pattern: '/logs/output_{}.log.gz'\n  ```\n\nStorage sizing:\n\nThe Helm value `storage.logs.size` defines the size of the PVC mounted at `/logs`. Rotation settings must fit within this limit. Example of default configuration:\n\n- `limit: 25 gb`\n- `count: 4`\n\nMaximum disk usage is 1 active file + 4 archived files = 5 × 25 GB = 125 GB\n\nThe default `storage.logs.size` is `150Gi` (\\~161 GB), providing headroom. If rotation limits are reduced, for example, 1 GB × 10 archives with `.gz` compression, actual disk usage is lower, allowing a smaller volume size.\n\n### `console`\n\nThe `console` appender writes logs to `stdout` or `stderr`. It is suitable when the cluster uses a log collection stack such as Loki, Fluentd, or Elasticsearch, and log storage is handled externally.\n\nAt `debug` or `trace` levels, log volume can be high and may overload the collector. Log levels should be configured accordingly. When using console-only logging, disable the logs volume by setting `storage.logs.enabled` to `false`.\n\n```yaml\nappenders:\n  stdout:\n    kind: console\n    target: stdout          # or \"stderr\"\n    encoder:\n      pattern: \"{d(%Y-%m-%d %H:%M:%S.%f)} {l} [{t}] {I}: {m}{n}\"\n```\n\n### `file`\n\nThe `file` appender writes logs to a file without rotation. The file grows indefinitely and may exhaust disk space. Use `rolling_file` instead.\n\n```yaml\nappenders:\n  logfile:\n    kind: file\n    path: /logs/output.log\n    append: true            # default: true\n    encoder:\n      pattern: \"...\"\n```\n\n### `filters`\n\n`filters` may be attached to any appender for additional message filtering. Here, threshold filter discards messages below the specified level.\n\n```yaml\nappenders:\n  stdout:\n    kind: console\n    filters:\n      - kind: threshold\n        level: warn\n    encoder:\n      pattern: \"...\"\n```\n\n## Encoder (log format)\n\nEach appender uses an `encoder` to format log entries. The default encoder kind is `pattern`:\n\n```yaml\nencoder:\n  pattern: \"{d(%Y-%m-%d %H:%M:%S.%f)} {l} [{t}] {I}: {m}{n}\"\n```\n\n### Format specifiers\n\n| Specifier          | Name       | Description                                                                                           |\n| ------------------ | ---------- | ----------------------------------------------------------------------------------------------------- |\n| `{d}` / `{d(fmt)}` | date       | Timestamp. Default format is ISO 8601. Custom format uses chrono syntax: `{d(%Y-%m-%d %H:%M:%S.%f)}`. |\n| `{l}`              | level      | Log levels: `error`, `warn`, `info`, `debug`, `trace`                                                 |\n| `{m}`              | message    | Log message body                                                                                      |\n| `{n}`              | newline    | Platform-dependent newline                                                                            |\n| `{t}`              | target     | Logger target; module name or explicit `target:` in the log macro.                                    |\n| `{I}`              | thread\\_id | Numeric thread ID                                                                                     |\n| `{T}`              | thread     | Thread name                                                                                           |\n| `{f}`              | file       | Source file name                                                                                      |\n| `{L}`              | line       | Source line number                                                                                    |\n| `{M}`              | module     | Module path                                                                                           |\n| `{P}`              | pid        | Process ID                                                                                            |\n| `{h(..)}`          | highlight  | Colorizes enclosed text by log levels; applies to console output only.                                |\n\n### Example output\n\n```\n2025-01-15 14:30:45.123456 INFO [validator] 140234567890: Block validated successfully\n```\n\n<Aside type=\"note\">\n  Do not use `{h(...)}` in file appenders. It writes ANSI escape codes to the log output, which makes the file harder to read and search.\n</Aside>\n\n## Loggers\n\n### Root logger\n\nThe root logger is the default logger. All log records not matched by a named logger are processed by it.\n\n```yaml\nroot:\n  level: error\n  appenders:\n    - rolling_logfile\n```\n\n| Field       | Required | Description                                                  |\n| ----------- | -------- | ------------------------------------------------------------ |\n| `level`     | yes      | Log level: `off`, `error`, `warn`, `info`, `debug`, `trace`. |\n| `appenders` | yes      | List of appender names defined in the appenders section.     |\n\n### Named loggers\n\nNamed loggers configure log levels for specific components. The logger name must match the `target` used in the node code.\n\n```yaml\nloggers:\n  validator:\n    level: info\n```\n\n| Field       | Required | Default               | Description                                                               |\n| ----------- | -------- | --------------------- | ------------------------------------------------------------------------- |\n| `level`     | no       | inherited from parent | Log level                                                                 |\n| `appenders` | no       | `[]`                  | Appenders assigned to this logger.                                        |\n| `additive`  | no       | `true`                | If `true`, messages also propagate to the parent logger appenders (root). |\n\nLoggers form a hierarchy using `::`. For example:\n\n- `node`;\n- `node::network` is a child of `node`.\n\nIf `additive: true`, messages logged by `node::network` are written to:\n\n- the appenders configured for `node::network`;\n- the appenders of `node`;\n- the appenders of the root logger.\n\n### Log levels\n\nOrdered from most to least verbose:\n\n| Level   | Description                                           |\n| ------- | ----------------------------------------------------- |\n| `trace` | Most detailed level. Used for execution flow tracing. |\n| `debug` | Debug information.                                    |\n| `info`  | Informational messages about normal operation.        |\n| `warn`  | Indication of a potential problem.                    |\n| `error` | Errors that don't stop the node.                      |\n| `off`   | Logging disabled.                                     |\n\n### Available logger targets\n\nThe following targets can be configured in the `loggers` section:\n\n| Target                      | Description                              |\n| --------------------------- | ---------------------------------------- |\n| `node`                      | Core node messages                       |\n| `boot`                      | Node bootstrap and initialization        |\n| `sync`                      | Block synchronization                    |\n| `node::network`             | Node networking                          |\n| `node::network::neighbours` | Neighbor tracking (high log volume)      |\n| `node::network::liteserver` | Liteserver request handling              |\n| `node::validator::collator` | Block collation                          |\n| `adnl`                      | ADNL network protocol                    |\n| `adnl_query`                | ADNL query processing                    |\n| `overlay`                   | Overlay networks                         |\n| `overlay_broadcast`         | Overlay broadcast messages               |\n| `rldp`                      | RLDP protocol (reliable large datagrams) |\n| `dht`                       | Distributed hash table                   |\n| `block`                     | Block structure and config parsing       |\n| `executor`                  | Transaction execution                    |\n| `tvm`                       | TON Virtual Machine                      |\n| `validator`                 | Validation (general)                     |\n| `validator_manager`         | Validator management                     |\n| `validate_query`            | Block and query validation               |\n| `validate_reject`           | Rejected block and query validation      |\n| `catchain`                  | Catchain consensus protocol              |\n| `catchain_adnl_overlay`     | ADNL overlay for catchain                |\n| `catchain_network`          | Catchain network transport               |\n| `validator_session`         | Validator sessions                       |\n| `consensus_common`          | Shared consensus logic                   |\n| `storage`                   | Data storage                             |\n| `index`                     | Data indexing                            |\n| `ext_messages`              | External message handling                |\n| `telemetry`                 | Telemetry and metrics                    |\n\n<Aside type=\"note\">\n  HTTP requests such as JSON-RPC and metrics endpoints are not logged by the node. There is no logger target for HTTP request tracing.\n</Aside>\n"
  },
  {
    "path": "ecosystem/nodes/rust/metrics.mdx",
    "content": "---\ntitle: \"Metrics\"\n---\n\nAll metrics are served at `GET /metrics` on the metrics port and are exposed in the standard Prometheus text format. Configure the port using `ports.metrics` in the Helm chart.\n\n## Configuration\n\nMetrics are configured in the node's [config.json](/ecosystem/nodes/rust/node-config):\n\n```json\n{\n  \"metrics\": {\n    \"address\": \"0.0.0.0:9100\",\n    \"histogram_buckets\": {},\n    \"global_labels\": {\n      \"network\": \"mainnet\",\n      \"node_id\": \"validator-01\"\n    }\n  }\n}\n```\n\n| Field               | Description                                                                                                                                        |\n| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `address`           | Listen address for the metrics and probes HTTP server. If the `metrics` section is absent, the server does not start.                              |\n| `histogram_buckets` | Custom histogram buckets by metric name. When empty, default duration buckets apply to all histograms whose names end with the suffix `*_seconds`. |\n| `global_labels`     | Key-value pairs added to every metric. Useful for distinguishing nodes in a shared Prometheus.                                                     |\n\nDefault histogram buckets for `*_seconds` metrics:\n\n```\n[0.000001, 0.0001, 0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0, 60.0, 120.0, 300.0, 600.0, 3600.0]\n```\n\n## Build info\n\n`ton_node_build_info` is an informational gauge that is always set to `1`. Build metadata is encoded as labels:\n\n```\nton_node_build_info{version=\"<node-version>\", commit=\"<git-commit>\", branch=\"<git-branch>\", build_time=\"<build-timestamp>\", rustversion=\"<rustc-version>\", arch=\"<target-arch>\", os=\"<target-os>\"} 1\n```\n\n| Label         | Description                                    |\n| ------------- | ---------------------------------------------- |\n| `version`     | Package version from `Cargo.toml`              |\n| `commit`      | Full git commit hash                           |\n| `branch`      | Git branch at build time                       |\n| `build_time`  | Build timestamp                                |\n| `rustversion` | Rust compiler version                          |\n| `arch`        | Target architecture; `x86_64`, `aarch64`, etc. |\n| `os`          | Target OS; `linux`, `macos`, etc.              |\n\n## Naming convention\n\nAll metrics follow the format:\n\n```\nton_node_{subsystem}_{metric_name}[_{unit_suffix}]\n```\n\n- `ton_node_` – application prefix that prevents collisions in shared Prometheus instances.\n- `{subsystem}` – functional area defined in the table below.\n- `{metric_name}` – descriptive name in snake case.\n- `{unit_suffix}` – optional: `_total` (counters), `_seconds` (durations), `_bytes` (sizes), `_ratio` (dimensionless).\n\n| Subsystem      | Scope                                              |\n| -------------- | -------------------------------------------------- |\n| `engine`       | Core node state, sync status, masterchain tracking |\n| `validator`    | Block validation lifecycle                         |\n| `collator`     | Block collation lifecycle                          |\n| `outqueue`     | Outbound message queue cleanup                     |\n| `ext_messages` | External messages queue                            |\n| `network`      | ADNL, catchain, overlay, neighbor stats            |\n| `db`           | Database, shard state, `gc`, persistent state      |\n| `block`        | Block parsing, block sizes                         |\n\n## Metric types\n\n| Type      | Behavior                                                                       | Suffix convention                       |\n| --------- | ------------------------------------------------------------------------------ | --------------------------------------- |\n| counter   | Monotonically increasing value. Resets to `0` on restart.                      | `_total`                                |\n| gauge     | Arbitrary value that can increase or decrease.                                 | none, `_seconds`, `_ratio`              |\n| histogram | Samples sorted into configurable buckets. Exposes `_bucket`, `_sum`, `_count`. | `_seconds`, `_bytes`, `_ratio`, or none |\n\n## Labels\n\nSome metrics carry labels for additional dimensions:\n\n| Label       | Subsystems                          | Values                | Description                               |\n| ----------- | ----------------------------------- | --------------------- | ----------------------------------------- |\n| `shard`     | `validator`, `collator`, `outqueue` | `ShardIdent` string   | Shard identifier for per-shard breakdown  |\n| `step`      | `outqueue`                          | step identifier       | Outgoing queue cleanup step identifier    |\n| `peer`      | `network`                           | peer key ID (hex)     | ADNL peer for round-trip measurements     |\n| `neighbour` | `network`                           | neighbor key ID (hex) | Overlay neighbor for reliability tracking |\n\n## `engine`\n\nCore node state, including sync progress, masterchain tracking, validation intent, and applied transactions.\nThis subsystem exposes 8 metrics: 7 gauges and 1 counter.\n\n| Metric                                       | Type    | Description                                                                                |\n| -------------------------------------------- | ------- | ------------------------------------------------------------------------------------------ |\n| `ton_node_engine_sync_status`                | gauge   | Sync state machine value.                                                                  |\n| `ton_node_engine_timediff_seconds`           | gauge   | Seconds between current time and the last applied masterchain block.                       |\n| `ton_node_engine_last_mc_block_utime`        | gauge   | Unix timestamp of the last applied masterchain block.                                      |\n| `ton_node_engine_last_mc_block_seqno`        | gauge   | Seqno of the last applied masterchain block.                                               |\n| `ton_node_engine_shards_mc_seqno`            | gauge   | Masterchain block seqno last processed by the shard client.                                |\n| `ton_node_engine_shards_timediff_seconds`    | gauge   | Seconds between current time and the masterchain block last processed by the shard client. |\n| `ton_node_engine_will_validate`              | gauge   | `1` if the node intends to validate, `0` otherwise.                                        |\n| `ton_node_engine_applied_transactions_total` | counter | Total number of transactions in all applied blocks, including masterchain and shards.      |\n\n### Sync status values\n\n| Value | State         | Description                              |\n| ----- | ------------- | ---------------------------------------- |\n| 0     | `not_set`     | Initial state; status not yet determined |\n| 1     | `start_boot`  | Boot sequence started                    |\n| 3     | `load_states` | Loading shard states from the network    |\n| 4     | `finish_boot` | Boot sequence completing                 |\n| 5     | `sync_blocks` | Syncing blocks from the network          |\n| 6     | `synced`      | Fully synced with the network            |\n| 7     | `checking_db` | Database integrity check in progress     |\n| 8     | `db_broken`   | Database corruption detected             |\n\nA healthy, synced node reports `sync_status = 6`. During initial sync or restart, the value progresses through `1 → 3 → 4 → 5 → 6`.\n\n### Time difference\n\n`timediff_seconds` measures the gap between wall-clock time and the `gen_utime` of the last applied masterchain block. Values below 20 seconds indicate a healthy node; values above 60 seconds require investigation.\n\n## `validator`\n\nBlock validation lifecycle, including state, set membership, outcomes, and gas. It exposes 8 metrics: 4 gauges, 3 counters, and 1 histogram.\n\n| Metric                                        | Type      | Description                                            |\n| --------------------------------------------- | --------- | ------------------------------------------------------ |\n| `ton_node_validator_status`                   | gauge     | Validation state machine value.                        |\n| `ton_node_validator_in_current_set`           | gauge     | `1` if the node is in the current validator set (p34). |\n| `ton_node_validator_in_next_set`              | gauge     | `1` if the node is in the next validator set (p36).    |\n| `ton_node_validator_active`                   | gauge     | Number of validation queries currently in progress.    |\n| `ton_node_validator_successes_total`          | counter   | Successful block validations.                          |\n| `ton_node_validator_failures_total`           | counter   | Failed block validations.                              |\n| `ton_node_validator_ref_block_failures_total` | counter   | Failed reference shard block validations.              |\n| `ton_node_validator_gas_rate_ratio`           | histogram | Gas rate ratio from validation.                        |\n\n### Validation status values\n\n| Value | State        | Description                                   |\n| ----- | ------------ | --------------------------------------------- |\n| 0     | `Not in Set` | Node is not part of the current validator set |\n| 1     | `Waiting`    | Waiting for next validation round             |\n| 2     | `Countdown`  | Elected; countdown to validation start        |\n| 3     | `Active`     | Actively validating blocks                    |\n\n## `collator`\n\nBlock collation lifecycle, including outcomes, duration, gas usage, message flow, and transaction counts. It exposes 14 metrics: 2 gauges, 6 counters, and 6 histograms.\n\n| Metric                                           | Type      | Description                                                             |\n| ------------------------------------------------ | --------- | ----------------------------------------------------------------------- |\n| `ton_node_collator_active`                       | gauge     | Number of collation queries currently in progress.                      |\n| `ton_node_collator_successes_total`              | counter   | Successful block collations.                                            |\n| `ton_node_collator_failures_total`               | counter   | Failed block collations.                                                |\n| `ton_node_collator_duration_seconds`             | histogram | End-to-end block collation duration.                                    |\n| `ton_node_collator_process_ext_messages_seconds` | histogram | Time to process inbound external messages.                              |\n| `ton_node_collator_process_new_messages_seconds` | histogram | Time to process new internal messages.                                  |\n| `ton_node_collator_gas_used`                     | histogram | Gas consumed per collated block.                                        |\n| `ton_node_collator_gas_rate_ratio`               | histogram | Gas rate ratio from collation.                                          |\n| `ton_node_collator_dequeued_messages_total`      | counter   | Messages dequeued from the outbound queue during collation.             |\n| `ton_node_collator_enqueued_messages_total`      | counter   | Messages enqueued to the outbound queue during collation.               |\n| `ton_node_collator_inbound_messages_total`       | counter   | Inbound messages processed during collation.                            |\n| `ton_node_collator_outbound_messages_total`      | counter   | Outbound messages produced during collation.                            |\n| `ton_node_collator_transit_messages_total`       | counter   | Transit messages, which are forwarded between shards, during collation. |\n| `ton_node_collator_executed_transactions_total`  | counter   | Transactions executed during collation.                                 |\n\n## `outqueue`\n\nOutbound message queue periodic cleanup statistics. This subsystem exposes 4 metrics, all of which are gauges.\n\n| Metric                                     | Type  | Description                                                               |\n| ------------------------------------------ | ----- | ------------------------------------------------------------------------- |\n| `ton_node_outqueue_clean_partial`          | gauge | `1` if last outgoing queue clean was partial; not all messages processed. |\n| `ton_node_outqueue_clean_duration_seconds` | gauge | Duration of the last outgoing queue clean in seconds.                     |\n| `ton_node_outqueue_clean_processed`        | gauge | Messages processed in the last outgoing queue clean.                      |\n| `ton_node_outqueue_clean_deleted`          | gauge | Messages deleted in the last outgoing queue clean.                        |\n\n## `ext_messages`\n\nExternal message queue containing messages received from clients and awaiting inclusion in blocks. It exposes 2 metrics: 1 gauge, 1 counter.\n\n| Metric                                | Type    | Description                                       |\n| ------------------------------------- | ------- | ------------------------------------------------- |\n| `ton_node_ext_messages_queue_size`    | gauge   | Current size of the external message queue.       |\n| `ton_node_ext_messages_expired_total` | counter | Expired external messages removed from the queue. |\n\n## `network`\n\nNetworking metrics covering ADNL round-trips, catchain timings, overlay queries, and neighbor reliability. It exposes 7 metrics: 1 gauge, 1 counter, and 5 histograms.\n\n| Metric                                             | Type      | Labels      | Description                                                             |\n| -------------------------------------------------- | --------- | ----------- | ----------------------------------------------------------------------- |\n| `ton_node_network_adnl_roundtrip_seconds`          | histogram | `peer`      | ADNL query round-trip time.                                             |\n| `ton_node_network_catchain_overlay_query_seconds`  | histogram |             | Catchain overlay query time.                                            |\n| `ton_node_network_catchain_send_seconds`           | histogram |             | Catchain send message time.                                             |\n| `ton_node_network_catchain_client_query_seconds`   | histogram |             | Catchain client query time.                                             |\n| `ton_node_network_consensus_overlay_query_seconds` | histogram |             | Consensus overlay query time.                                           |\n| `ton_node_network_neighbour_failures_total`        | counter   | `neighbour` | Failed queries to overlay neighbors.                                    |\n| `ton_node_network_neighbour_unreliability`         | gauge     | `neighbour` | Neighbor unreliability score; higher values indicate lower reliability. |\n\n## `db`\n\nDatabase operations, including shard state management, garbage collection, persistent state, and Merkle updates. It exposes 5 metrics: 1 gauge, 4 histograms.\n\n| Metric                                       | Type      | Description                                         |\n| -------------------------------------------- | --------- | --------------------------------------------------- |\n| `ton_node_db_shardstate_queue_size`          | gauge     | Shard state processing queue size.                  |\n| `ton_node_db_shardstate_gc_seconds`          | histogram | Shard state garbage collection duration.            |\n| `ton_node_db_persistent_state_write_seconds` | histogram | Persistent state write duration; BoC serialization. |\n| `ton_node_db_restore_merkle_update_seconds`  | histogram | Merkle update duration during chain restore.        |\n| `ton_node_db_calc_merkle_update_seconds`     | histogram | Merkle update calculation duration.                 |\n\n## `block`\n\nBlock parsing and size metrics. It exposes 3 metrics, all of which are histograms.\n\n| Metric                                    | Type      | Description                          |\n| ----------------------------------------- | --------- | ------------------------------------ |\n| `ton_node_block_accounts_parsing_seconds` | histogram | Time to parse accounts from a block. |\n| `ton_node_block_parsed_accounts`          | histogram | Number of accounts parsed per block. |\n| `ton_node_block_size_bytes`               | histogram | Block size in bytes.                 |\n"
  },
  {
    "path": "ecosystem/nodes/rust/monitoring.mdx",
    "content": "---\ntitle: \"Monitoring\"\nsidebarTitle: \"Monitoring\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\n\n## Objective\n\nSet up Prometheus and Grafana for TON node metrics. `kube-prometheus-stack` is recommended because the chart includes a `ServiceMonitor` template for automatic scrape discovery.\n\n## Prerequisites\n\n1. Enable the metrics HTTP server in node config (`config.json`):\n\n   ```json\n   {\n     \"metrics\": {\n       \"address\": \"0.0.0.0:9100\",\n       \"global_labels\": {\n         \"network\": \"mainnet\",\n         \"node_id\": \"my-node-0\"\n       }\n     }\n   }\n   ```\n\n   The server exposes `/metrics` (Prometheus format), `/healthz` (liveness), and `/readyz` (readiness). If `metrics` is absent, the server is not started.\n\n   <Aside\n     type=\"note\"\n     title=\"Required labels\"\n   >\n     `global_labels` with `network`, and `node_id` are required for the bundled Grafana dashboard. Without them, dashboard variables are empty and panels show no data.\n   </Aside>\n\n1. Set `ports.metrics` in Helm values:\n\n   ```yaml\n   ports:\n     metrics: 9100\n   ```\n\n   The port must match the `metrics.address` port in [node config](/ecosystem/nodes/rust/node-config-ref).\n\n## Network security\n\nThe metrics port is never exposed on public per-replica `LoadBalancer` services. The chart creates a dedicated internal `<release>-metrics` `ClusterIP` service instead, accessible only inside the cluster.\n\nExternal metrics access can be added with a custom `LoadBalancer` service that targets the metrics port. The recommended approach is an ingress with authentication (basic auth, OAuth2 proxy, and similar) that proxies to `<release>-metrics`.\n\n## Quick start\n\nMinimal values to enable metrics, probes, and `ServiceMonitor`:\n\nNot runnable\n\n```yaml\nports:\n  metrics: 9100\n\nprobes:\n  startup:\n    httpGet:\n      path: /healthz\n      port: metrics\n    failureThreshold: 60\n    periodSeconds: 10\n  liveness:\n    httpGet:\n      path: /healthz\n      port: metrics\n    periodSeconds: 30\n    failureThreshold: 3\n  readiness:\n    httpGet:\n      path: /readyz\n      port: metrics\n    periodSeconds: 10\n    failureThreshold: 3\n\nmetrics:\n  serviceMonitor:\n    enabled: true\n```\n\n## ServiceMonitor configuration\n\nEnable `ServiceMonitor` so `kube-prometheus-stack` discovers and scrapes node metrics automatically:\n\nNot runnable\n\n```yaml\nmetrics:\n  serviceMonitor:\n    enabled: true\n```\n\n### Label matching\n\nSome Prometheus Operator installations filter `ServiceMonitor` resources by labels (`serviceMonitorSelector` in the Prometheus custom resource). If a Prometheus instance requires labels:\n\nNot runnable\n\n```yaml\nmetrics:\n  serviceMonitor:\n    enabled: true\n    labels:\n      release: kube-prometheus-stack\n```\n\n### Scrape interval\n\nBy default, `ServiceMonitor` inherits the global Prometheus scrape interval (typically `30s`). To override:\n\nNot runnable\n\n```yaml\nmetrics:\n  serviceMonitor:\n    enabled: true\n    interval: \"15s\"\n    scrapeTimeout: \"10s\"\n```\n\n### Cross-namespace monitoring\n\nIf Prometheus runs in a different namespace, set the `ServiceMonitor` namespace to the namespace where Prometheus looks:\n\nNot runnable\n\n```yaml\nmetrics:\n  serviceMonitor:\n    enabled: true\n    namespace: monitoring\n```\n\nA `namespaceSelector` is added automatically so Prometheus can discover services in the release namespace.\n\n## Alternative: Prometheus annotations\n\nIf Prometheus Operator is not used and services are scraped through `prometheus.io/*` annotations:\n\nNot runnable\n\n```yaml\nmetrics:\n  annotations:\n    enabled: true\n```\n\nThis adds `prometheus.io/scrape`, `prometheus.io/port`, and `prometheus.io/path` to the `<release>-metrics` `ClusterIP` service.\n\n## Alternative: static scrape config\n\nFor other Prometheus setups, the metrics endpoint is available through the internal `ClusterIP` service:\n`<release>-metrics.<namespace>.svc.cluster.local`\n\n## Grafana dashboard\n\nThe Grafana dashboard is authored as TypeScript with [Grafana Foundation SDK](https://grafana.com/docs/grafana/latest/as-code/observability-as-code/foundation-sdk/) and generated to JSON. Dashboard source is available in [TON Rust Node Grafana source](https://github.com/RSquad/ton-rust-node/blob/e8bd0451b326099146a90a913beedaebd952fa56/grafana/src/index.ts). Generated output file name is `ton-node-overview.json`.\n\nThe dashboard uses two multi-select template variables:\n\n- `network`\n- `node_id`\n\nThese correspond to `global_labels` in node metrics config.\n\nDashboard sections:\n\n- Node Status\n- Build Info\n- Transactions per second\n- Sync and Block Progress\n- Validation and Collation\n- Outbound Message Queue\n- Network\n- Database and Storage\n\n### Generate dashboard JSON\n\nRun from the TON Rust Node repository root.\n\n```bash\ncd grafana\nbun install\nbun run generate\n```\n\n`bun run generate` writes `ton-node-overview.json`.\n\n### Import into Grafana\n\n1. Open <kbd>Dashboards</kbd> > <kbd>New</kbd> > <kbd>Import</kbd>.\n1. Upload `ton-node-overview.json`.\n1. Select a Prometheus data source.\n1. Click <kbd>Import</kbd>.\n\n### Edit workflow\n\n1. Edit dashboard TypeScript source files.\n1. Run `bun run generate`.\n1. Import the generated JSON and verify panels.\n1. Commit TypeScript source files. The generated JSON file is ignored by Git.\n\n## Alert rules\n\n`PrometheusRule` resources can be created to trigger alerts based on TON node [metrics](/ecosystem/nodes/rust/metrics).\n"
  },
  {
    "path": "ecosystem/nodes/rust/node-config-ref.mdx",
    "content": "---\ntitle: \"Node configuration reference\"\nsidebarTitle: \"Node configuration reference\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n## Top-level fields\n\n### `log_config_name`\n\nPath to the [loggers YAML configuration file](/ecosystem/nodes/rust/logs-config). Relative paths are resolved from the directory containing `config.json`.\n\n| Type           | Required | Default                                               |\n| -------------- | -------- | ----------------------------------------------------- |\n| string \\| null | no       | `null`; falls back to console output at `info` level. |\n\nIn the Helm chart, set this field to `\"/main/logs.config.yml\"`.\n\n### `ton_global_config_name`\n\nPath to the [global network config](/ecosystem/nodes/rust/global-config). Determines which network the node joins.\n\n| Type           | Required | Default |\n| -------------- | -------- | ------- |\n| string \\| null | yes      | `null`  |\n\nIn the Helm chart, always set to `\"/main/global.config.json\"`.\n\n### `internal_db_path`\n\nPath to the node's internal database directory. Stores blocks, states, indexes, and other persistent data. Requires substantial disk space; on mainnet, storage requirements are typically hundreds of gigabytes.\n\n| Type           | Required | Default     |\n| -------------- | -------- | ----------- |\n| string \\| null | no       | `\"node_db\"` |\n\nIn the Helm chart, always set to `\"/db\"`, where the database PVC is mounted.\n\n### `restore_db`\n\nEnable database integrity check and repair on startup.\n\n| Type | Required | Default |\n| ---- | -------- | ------- |\n| bool | no       | `false` |\n\n### `boot_from_zerostate`\n\nIf `true`, the node starts synchronization from the zero state, which is the genesis block, instead of the `init_block` specified in the [global config](/ecosystem/nodes/rust/global-config). This increases sync time but verifies the entire blockchain history from genesis.\n\n| Type         | Required | Default |\n| ------------ | -------- | ------- |\n| bool \\| null | no       | `false` |\n\n### `sync_by_archives`\n\nIf `true`, the node syncs by downloading block archives. Faster than block-by-block sync but requires peers that serve archives.\n\n| Type | Required | Default |\n| ---- | -------- | ------- |\n| bool | no       | `true`  |\n\n### `skip_saving_persistent_states`\n\nIf `true`, the node skips saving periodic shard state snapshots. Saves disk space but makes recovery after failures harder.\n\n| Type | Required | Default |\n| ---- | -------- | ------- |\n| bool | no       | `false` |\n\n### `states_cache_mode`\n\nShards state caching strategy.\n\n| Type          | Required | Default      |\n| ------------- | -------- | ------------ |\n| string (enum) | no       | `\"Moderate\"` |\n\n| Value        | Description                                    |\n| ------------ | ---------------------------------------------- |\n| `\"Off\"`      | States are saved synchronously and not cached. |\n| `\"Moderate\"` | States are saved asynchronously; recommended.  |\n\n### `accelerated_consensus_disabled`\n\nIf `true`, uses the standard consensus procedure instead of the accelerated one.\n\n| Type | Required | Default |\n| ---- | -------- | ------- |\n| bool | no       | `false` |\n\n### `validation_countdown_mode`\n\nControls the countdown behavior for block validation.\n\n| Type           | Required | Default                           |\n| -------------- | -------- | --------------------------------- |\n| string \\| null | no       | `null`; equivalent to `\"always\"`. |\n\n| Value                | Description                                 |\n| -------------------- | ------------------------------------------- |\n| `\"always\"`           | Countdown applies to all blocks.            |\n| `\"except-zerostate\"` | Countdown does not apply to the zero state. |\n\n### `default_rldp_roundtrip_ms`\n\nInitial round-trip time or RTT estimates for the [Reliable Large Datagram Protocol (RLDP)](/foundations/whitepapers/ton#3-1-9-rldp-or-reliable-large-datagram-protocol-over-adnl) in milliseconds. RLDP is a transport layer on top of ADNL that provides ordered, retransmitted delivery for large data transfers.\n\n| Type        | Required | Default                                       |\n| ----------- | -------- | --------------------------------------------- |\n| u32 \\| null | no       | `null`; uses the RLDP implementation default. |\n\n### `unsafe_catchain_patches_path`\n\nPath to a directory with catchain JSON patch files. Used for emergency intervention in the [catchain protocol](/foundations/whitepapers/catchain) for resync and rotation. Only for emergency situations.\n\n| Type           | Required | Default |\n| -------------- | -------- | ------- |\n| string \\| null | no       | `null`  |\n\n## `adnl_node`\n\nADNL (Abstract Datagram Network Layer) is the core networking protocol of TON. This section defines how the node participates in the ADNL network.\n\n### `adnl_node.ip_address`\n\nThe node's external IP address and UDP port. Must be reachable from the internet. Other nodes connect to this address.\n\n| Type   | Required | Format      |\n| ------ | -------- | ----------- |\n| string | yes      | `\"IP:PORT\"` |\n\n<Aside type=\"note\">\n  The `adnl_node.ip_address` value must match the external IP assigned to this replica's `LoadBalancer` service. The port must match `ports.adnl` defined in Helm values.\n</Aside>\n\n### `adnl_node.keys`\n\nCryptographic keys for different node functions. Each key has a `tag` that determines its purpose.\n\n| Field          | Type            | Description                             |\n| -------------- | --------------- | --------------------------------------- |\n| `tag`          | integer         | Key purpose; defined in the \"Key tags\". |\n| `data.type_id` | integer         | Key type. `1209251014` = Ed25519        |\n| `data.pvt_key` | string (base64) | 256-bit Ed25519 private key             |\n\nKey tags:\n\n| Tag | Purpose                                         |\n| --- | ----------------------------------------------- |\n| `1` | DHT key – used for peer discovery.              |\n| `2` | Overlay key – used for block and data exchange. |\n\n### Additional `adnl_node` fields\n\nThese optional fields are not commonly needed:\n\n| Field                              | Type        | Default | Description                                         |\n| ---------------------------------- | ----------- | ------- | --------------------------------------------------- |\n| `recv_pipeline_pool`               | u8 \\| null  | `null`  | Percentage of CPU cores for packet receive workers. |\n| `recv_priority_pool`               | u8 \\| null  | `null`  | Percentage of workers for priority receive.         |\n| `throughput`                       | u32 \\| null | `null`  | Max send throughput in bytes/sec.                   |\n| `timeout_expire_queued_packet_sec` | u32 \\| null | `null`  | Timeout for queued packets in seconds.              |\n\n## `gc`\n\nGarbage collector settings for cleaning up stale data.\n\n### `gc.enable_for_archives`\n\nEnables automatic cleanup of old block archives. If `false`, archives accumulate indefinitely.\n\n| Type | Default |\n| ---- | ------- |\n| bool | `false` |\n\n### `gc.archives_life_time_hours`\n\nArchive retention period in hours. Archives older than the specified number of hours are pruned by `gc`.\n\n| Type        | Default                             |\n| ----------- | ----------------------------------- |\n| u32 \\| null | `null`; delete as soon as possible. |\n\nExample: `48` keeps archives for the last 2 days.\n\n### `gc.enable_for_shard_state_persistent`\n\nEnable cleanup of old persistent shard state snapshots.\n\n| Type | Default |\n| ---- | ------- |\n| bool | `false` |\n\n### `gc.cells_gc_config`\n\n`gc` settings for cells – the basic data storage units in TON.\n\n| Field                | Type | Default            | Description                                                              |\n| -------------------- | ---- | ------------------ | ------------------------------------------------------------------------ |\n| `gc_interval_sec`    | u32  | `900` (15 min)     | Interval between cell `gc` runs.                                         |\n| `cells_lifetime_sec` | u64  | `86400` (24 hours) | Cells unused for longer than this duration become eligible for deletion. |\n\nThis setting only affects cells required for serving external queries (e.g., account state requests from a lite-client). Cells required for the node’s own operation are retained regardless of this configuration.\n\nFor validators or nodes without a liteserver, a lower value, such as `1800 = 30 min`, can be used to reduce disk usage and improve performance.\n\n## `cells_db_config`\n\nCell database tuning. If omitted entirely, the node uses built-in defaults for all fields. If the section is present, all fields must be specified — partial configs fail to deserialize.\n\n### `cells_db_config.states_db_queue_len`\n\nMaximum queue length for state write operations. Controls backpressure during async saves.\n\n| Type | Default |\n| ---- | ------- |\n| u32  | `1000`  |\n\n### `cells_db_config.prefill_cells_counters`\n\nIf `true`, pre-fills the cell counter cache during startup. Improves performance after start but increases startup time.\n\n| Type | Default |\n| ---- | ------- |\n| bool | `false` |\n\n### `cells_db_config.cells_cache_size_bytes`\n\nSize of the cell cache in bytes. Larger values reduce disk I/O at the cost of increased memory usage.\n\n| Type | Default               |\n| ---- | --------------------- |\n| u64  | `4000000000` (\\~4 GB) |\n\n### `cells_db_config.counters_cache_size_bytes`\n\nSize of the cell reference counter cache in bytes. Used for reference counting during `gc`.\n\n| Type | Default               |\n| ---- | --------------------- |\n| u64  | `4000000000` (\\~4 GB) |\n\n## `collator_config`\n\nConfiguration of the collator component responsible for assembling new blocks. Only relevant for validators.\n\n### `collator_config.cutoff_timeout_ms`\n\nSoft collation timeout in milliseconds. After this interval, the collator stops accepting new transactions and begins block finalization.\n\n| Type | Default           |\n| ---- | ----------------- |\n| u32  | `1000` (1 second) |\n\n### `collator_config.stop_timeout_ms`\n\nHard collation timeout in milliseconds. Collation is forcibly terminated after this interval. Must be greater than or equal to `cutoff_timeout_ms`.\n\n| Type | Default              |\n| ---- | -------------------- |\n| u32  | `1500` (1.5 seconds) |\n\n### `collator_config.clean_timeout_percentage_points`\n\nCleanup timeout as a fraction of `cutoff_timeout`. Measured in per-mille; out of 1000. For example, `150` corresponds to 15% of `cutoff_timeout` and defines the time allocated for removing processed messages during collation.\n\n| Type | Default |\n| ---- | ------- |\n| u32  | `150`   |\n\n### `collator_config.optimistic_clean_percentage_points`\n\nFraction of `clean_timeout` used for the first cleanup attempt. `1000` corresponds to 100%.\n\n| Type | Default |\n| ---- | ------- |\n| u32  | `1000`  |\n\n### `collator_config.max_secondary_clean_timeout_percentage_points`\n\nMaximum secondary cleanup timeout as a fraction of `cutoff_timeout`. `350` corresponds to 35%.\n\n| Type | Default |\n| ---- | ------- |\n| u32  | `350`   |\n\n### `collator_config.max_collate_threads`\n\nMaximum number of parallel collation threads.\n\n| Type | Default |\n| ---- | ------- |\n| u32  | `10`    |\n\n### `collator_config.retry_if_empty`\n\nIf `true`, retries collation when the resulting block contains no transactions. For TON consensus, `false` is recommended. Setting `true` may be useful in experimental networks to reduce block frequency during periods of low activity.\n\n| Type | Default |\n| ---- | ------- |\n| bool | `false` |\n\n### `collator_config.finalize_empty_after_ms`\n\nTime in milliseconds to wait for transactions before finalizing an empty block. If no transactions are received within this interval, the block is finalized as empty.\n\n| Type | Default |\n| ---- | ------- |\n| u32  | `800`   |\n\n### `collator_config.empty_collation_sleep_ms`\n\nPause in milliseconds between collation attempts when there are no transactions. Reduces CPU usage during low activity.\n\n| Type | Default |\n| ---- | ------- |\n| u32  | `100`   |\n\n### `collator_config.external_messages_timeout_percentage_points`\n\nFraction of `cutoff_timeout` allocated for processing external messages. `100` corresponds to 10%.\n\n| Type | Default |\n| ---- | ------- |\n| u32  | `100`   |\n\n### `collator_config.external_messages_maximum_queue_length`\n\nMaximum external message queue length. Limits memory usage during external message spam.\n\n| Type        | Default |\n| ----------- | ------- |\n| u32 \\| null | `25600` |\n\n### `collator_config_mc`\n\nSeparate collator config for the masterchain. Same format as `collator_config`. If not set, `collator_config` is used for all chains.\n\n| Type           | Default |\n| -------------- | ------- |\n| object \\| null | `null`  |\n\n## `control_server`\n\nAdministrative interface for managing the node — validator key rotation, monitoring, etc. Required for validators; optional for full nodes.\n\n### `control_server.address`\n\nAddress and port to listen on.\n\n| Type   | Format      |\n| ------ | ----------- |\n| string | `\"IP:PORT\"` |\n\nUse `\"0.0.0.0:<port>\"` to listen on all interfaces. For security, consider `\"127.0.0.1:<port>\"` if management is local only. The port must match `ports.control` in Helm values.\n\n### `control_server.server_key`\n\nServer private key for ADNL encryption.\n\n| Field     | Type            | Description            |\n| --------- | --------------- | ---------------------- |\n| `type_id` | integer         | `1209251014` = Ed25519 |\n| `pvt_key` | string (base64) | 256-bit private key    |\n\n### `control_server.clients`\n\nAuthorized clients allowed to connect.\n\n| Field            | Type            | Description                 |\n| ---------------- | --------------- | --------------------------- |\n| `list`           | array           | Array of client public keys |\n| `list[].type_id` | integer         | `1209251014` = Ed25519      |\n| `list[].pub_key` | string (base64) | Client public key           |\n\nIf `clients` is omitted or empty, any client can connect.\n\n## `lite_server`\n\nAllows lite clients, such as tonlib, etc., to connect to the node for queries. The corresponding public key is published in the global config's `liteservers` section for clients to discover it.\n\n### `lite_server.address`\n\nAddress and port for liteclient connections. The port must match `ports.liteserver` in Helm values.\n\n| Type   | Format      |\n| ------ | ----------- |\n| string | `\"IP:PORT\"` |\n\n### `lite_server.server_key`\n\nServer private key. Same format as `control_server.server_key`.\n\n### `lite_server.max_parallel_fast_queries`\n\nMaximum number of concurrent \"fast\" queries, which read from cache or perform simple lookups. Limits concurrency to prevent resource exhaustion under high load.\n\n| Type        | Required | Default |\n| ----------- | -------- | ------- |\n| u64 \\| null | no       | `256`   |\n\n### `lite_server.max_parallel_slow_queries`\n\nMaximum number of concurrent \"slow\" queries, which require disk reads, state traversal, or proof generation. These are more resource-intensive, so the default is lower.\n\n| Type        | Required | Default |\n| ----------- | -------- | ------- |\n| u64 \\| null | no       | `16`    |\n\n### `lite_server.account_state_cache_size_mb`\n\nSize of the in-memory cache for account states in megabytes. Caches recently queried account states to avoid repeated disk lookups.\n\n| Type        | Required | Default    |\n| ----------- | -------- | ---------- |\n| u64 \\| null | no       | `256` (MB) |\n\n## `json_rpc_server`\n\nHTTP JSON-RPC server for API requests.\n\n### `json_rpc_server.address`\n\nAddress and port for the HTTP API. The port must match `ports.jsonRpc` in Helm values.\n\n| Type   | Format      |\n| ------ | ----------- |\n| string | `\"IP:PORT\"` |\n\n## `metrics`\n\nPrometheus metrics and Kubernetes health probe HTTP server. When present, the node starts an HTTP server with three endpoints:\n\n| Endpoint       | Purpose                    |\n| -------------- | -------------------------- |\n| `GET /metrics` | Prometheus scrape endpoint |\n| `GET /healthz` | Kubernetes liveness probe  |\n| `GET /readyz`  | Kubernetes readiness probe |\n\nIf the `metrics` section is absent from the config, the metrics server is not started, meaning no metrics and no probes.\n\n### `metrics.address`\n\nAddress and port for the [metrics](/ecosystem/nodes/rust/metrics) and [probes](/ecosystem/nodes/rust/probes) HTTP server. The port must match `ports.metrics` in Helm values.\n\n| Type   | Required | Format      |\n| ------ | -------- | ----------- |\n| string | yes      | `\"IP:PORT\"` |\n\nRecommended: `\"0.0.0.0:9100\"`.\n\n### `metrics.histogram_buckets`\n\nCustom histogram bucket boundaries, keyed by metric name suffix. If a key matches the end of a histogram metric name, those buckets are used.\n\n| Type                   | Required | Default                                                            |\n| ---------------------- | -------- | ------------------------------------------------------------------ |\n| map\\<string, float\\[]> | no       | `{}`; default duration buckets applied to all `*_seconds` metrics. |\n\nWhen empty or absent, the following default buckets are applied to all histograms whose name ends with `seconds`:\n\n```\n[0.000001, 0.0001, 0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0, 60.0, 120.0, 300.0, 600.0, 3600.0]\n```\n\nExample of overriding buckets for all `*_seconds` histograms and adding custom ones for `gas_used`:\n\n```json\n\"histogram_buckets\": {\n  \"seconds\": [0.001, 0.01, 0.1, 0.5, 1.0, 5.0, 30.0, 60.0],\n  \"gas_used\": [1000, 10000, 100000, 500000, 1000000]\n}\n```\n\n### `metrics.global_labels`\n\nKey-value pairs added to every metric. Useful for distinguishing nodes when multiple instances report to the same Prometheus.\n\n| Type                 | Required | Default |\n| -------------------- | -------- | ------- |\n| map\\<string, string> | no       | `{}`    |\n\n<Aside type=\"note\">\n  The bundled [Grafana dashboard](https://github.com/RSquad/ton-rust-node/tree/master/grafana) relies on the `network` and `node_id` labels for filtering. If `global_labels` is not set or is empty, dashboard variables will be empty and panels will display no data.\n\n  Both labels must be defined.\n</Aside>\n\nExample:\n\n```json\n\"global_labels\": {\n  \"network\": \"mainnet\",\n  \"node_id\": \"validator-01\"\n}\n```\n\n### Full example\n\n```json\n\"metrics\": {\n  \"address\": \"0.0.0.0:9100\",\n  \"histogram_buckets\": {},\n  \"global_labels\": {\n    \"network\": \"mainnet\",\n    \"node_id\": \"validator-01\"\n  }\n}\n```\n\n## `extensions`\n\nOptional network extensions.\n\n| Field                          | Type       | Default | Description                                                                                                                   |\n| ------------------------------ | ---------- | ------- | ----------------------------------------------------------------------------------------------------------------------------- |\n| `disable_broadcast_retransmit` | bool       | `false` | Disable broadcast retransmission. Reduces traffic but hurts data propagation.                                                 |\n| `adnl_compression`             | bool       | `false` | Enable ADNL packet compression. Not compatible with C++ TON nodes; only enable in networks where all peers run the Rust node. |\n| `broadcast_hops`               | u8 \\| null | `null`  | Maximum number of broadcast hops.                                                                                             |\n\n<Aside\n  type=\"danger\"\n  title=\"Mainnet compatibility\"\n>\n  Do not enable `adnl_compression` on mainnet while any dependent peers run C++ TON nodes. This option is only safe when all interacting peers run the Rust node implementation.\n</Aside>\n\n## `secrets_vault_config`\n\nExternal secrets vault for storing private keys outside of `config.json`.\n\n```json\n\"secrets_vault_config\": {\n  \"url\": \"file:///path/to/vault\"\n}\n```\n\n| Type           | Default |\n| -------------- | ------- |\n| object \\| null | `null`  |\n\n<Aside\n  type=\"note\"\n  title=\"Helm integration\"\n>\n  For Helm deployments, prefer chart-level `vault.url` or `vault.secretName` values. When `VAULT_URL` is set by Helm, do not also set `secrets_vault_config` in `config.json`.\n</Aside>\n\n## Auto-managed fields\n\nThe following fields are written by the node itself through the control server and must not be edited manually:\n\n| Field                | Description                                                       |\n| -------------------- | ----------------------------------------------------------------- |\n| `validator_keys`     | Validator key records with election IDs and expiration timestamps |\n| `validator_key_ring` | Private key storage for validator keys                            |\n\nThese fields are primarily relevant in testing environments. During validator elections, the node rotates keys and writes updated values to `config.json`. In a Kubernetes environment, this has no persistent effect because the configuration is stored in a Secret and is overwritten on pod restart or Helm upgrade.\n\nThese fields should be treated as initialization-only or system-managed. The node regenerates them as required through the control server.\n\n## Validator-specific sections\n\nThe [`collator_config` section](/ecosystem/nodes/rust/node-config-ref#collator_config) defines block collation parameters, including timeouts, threading, and message queue limits. Use the [validator node config example](/ecosystem/nodes/rust/node-config#validator-node-config-example) for typical values.\n\n## Advanced fields\n\nThe following fields are present in the configuration but are not required for standard node operation. They should be left unchanged unless explicitly instructed otherwise.\n\n| Field                            | Type           | Default             | Description                                                                       |\n| -------------------------------- | -------------- | ------------------- | --------------------------------------------------------------------------------- |\n| `accelerated_consensus_disabled` | bool           | `false`             | Disables accelerated consensus, falling back to the standard procedure.           |\n| `validation_countdown_mode`      | string \\| null | `null` (`\"always\"`) | Defines when validation countdown is applied: `\"always\"` or `\"except-zerostate\"`. |\n| `default_rldp_roundtrip_ms`      | u32 \\| null    | `null`              | Initial RTT estimate for the RLDP protocol, in milliseconds.                      |\n| `unsafe_catchain_patches_path`   | string \\| null | `null`              | Path to catchain emergency patch files. Intended for emergency use only.          |\n"
  },
  {
    "path": "ecosystem/nodes/rust/node-config.mdx",
    "content": "---\ntitle: \"How to configure node JSON file\"\nsidebarTitle: \"Node configuration\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nEach TON node replica requires its own `config.json` – the main configuration file that defines ADNL settings, database paths, garbage collection, collator behavior, and optional control, liteserver, or JSON-RPC endpoints.\n\nIn the Helm chart, per-node configuration files are provided through the `nodeConfigs` map in `values.yaml` or through an existing [Secret](https://kubernetes.io/docs/concepts/configuration/secret/). Keys must follow the `node-N.json` naming pattern, where `N` matches the 0-based [`StatefulSet`](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/) replica index.\n\nDuring pod initialization, the init container copies `node-<pod-index>.json` to `/main/config.json`.\n\n## Node config overview\n\n### Helm integration constraints\n\nSeveral fields in the node config must be consistent with Helm values:\n\n| Field                     | Requirement                                                                                                     |\n| ------------------------- | --------------------------------------------------------------------------------------------------------------- |\n| `adnl_node.ip_address`    | Must match the external IP assigned to this replica's `LoadBalancer` service. The port must match `ports.adnl`. |\n| `control_server.address`  | The port must match `ports.control` if the control server is enabled.                                           |\n| `lite_server.address`     | The port must match `ports.liteserver` if the liteserver is enabled.                                            |\n| `json_rpc_server.address` | The port must match `ports.jsonRpc` if JSON-RPC is enabled.                                                     |\n| `metrics.address`         | The port must match `ports.metrics` if metrics are enabled.                                                     |\n| `log_config_name`         | Must be `/main/logs.config.yml`, where the chart mounts the logs config.                                        |\n| `ton_global_config_name`  | Must be `/main/global.config.json`, where the chart mounts the global config.                                   |\n| `internal_db_path`        | Must be `/db`, where the chart mounts the database PVC.                                                         |\n\n### How to provide configs\n\nChoose one of the following options:\n\n- Use `--set-file`:\n  ```bash\n  helm install my-node ./helm/ton-rust-node \\\n    --set-file 'nodeConfigs.node-0\\.json=./node-0.json' \\\n    ...\n  ```\n\n- Define inline in `values.yaml`:\n\n  ```yaml\n  nodeConfigs:\n    node-0.json: |\n      { \"log_config_name\": \"/main/logs.config.yml\", ... }\n  ```\n\n- Reference an existing Secret:\n\n  ```yaml\n  existingNodeConfigsSecretName: my-node-configs\n  ```\n\n### Full node with liteserver config example\n\nA typical full node exposes `lite_server` for lite-client queries and `json_rpc_server` for the HTTP API. The `control_server` is optional.\n\nThe example shows recommended values for production deployments. These values may differ from the defaults listed in the [field reference](/ecosystem/nodes/rust/node-config-ref). If a field is not specified, the node uses the default value defined in the codebase.\n\n```json expandable\n{\n  \"log_config_name\": \"/main/logs.config.yml\",\n  \"ton_global_config_name\": \"/main/global.config.json\",\n  \"internal_db_path\": \"/db\",\n  \"sync_by_archives\": true,\n  \"states_cache_mode\": \"Moderate\",\n  \"adnl_node\": {\n    \"ip_address\": \"<your-external-ip>:30303\",\n    \"keys\": [\n      { \"tag\": 1, \"data\": { \"type_id\": 1209251014, \"pvt_key\": \"<dht-private-key-base64>\" } },\n      { \"tag\": 2, \"data\": { \"type_id\": 1209251014, \"pvt_key\": \"<overlay-private-key-base64>\" } }\n    ]\n  },\n  \"lite_server\": {\n    \"address\": \"0.0.0.0:40000\",\n    \"server_key\": { \"type_id\": 1209251014, \"pvt_key\": \"<liteserver-private-key-base64>\" }\n  },\n  \"json_rpc_server\": {\n    \"address\": \"0.0.0.0:8081\"\n  },\n  \"metrics\": {\n    \"address\": \"0.0.0.0:9100\",\n    \"global_labels\": { \"network\": \"mainnet\", \"node_id\": \"lite-0\" }\n  },\n  \"gc\": {\n    \"enable_for_archives\": true,\n    \"archives_life_time_hours\": 48,\n    \"enable_for_shard_state_persistent\": true,\n    \"cells_gc_config\": {\n      \"gc_interval_sec\": 900,\n      \"cells_lifetime_sec\": 86400\n    }\n  },\n  \"cells_db_config\": {\n    \"states_db_queue_len\": 1000,\n    \"prefill_cells_counters\": false,\n    \"cells_cache_size_bytes\": 4000000000,\n    \"counters_cache_size_bytes\": 4000000000\n  }\n}\n```\n\n### Validator node config example\n\nA validator requires `control_server` for key management and election participation. Liteserver and JSON-RPC endpoints are not required on a validator and should be deployed separately for security reasons. The `collator_config` defines block production parameters.\n\nThe example shows recommended values for production deployments. These values may differ from the defaults listed in the [field reference](/ecosystem/nodes/rust/node-config-ref). If a field is not specified, the node uses the default value defined in the codebase.\n\n```json expandable\n{\n  \"log_config_name\": \"/main/logs.config.yml\",\n  \"ton_global_config_name\": \"/main/global.config.json\",\n  \"internal_db_path\": \"/db\",\n  \"sync_by_archives\": true,\n  \"states_cache_mode\": \"Moderate\",\n  \"adnl_node\": {\n    \"ip_address\": \"<your-external-ip>:30303\",\n    \"keys\": [\n      { \"tag\": 1, \"data\": { \"type_id\": 1209251014, \"pvt_key\": \"<dht-private-key-base64>\" } },\n      { \"tag\": 2, \"data\": { \"type_id\": 1209251014, \"pvt_key\": \"<overlay-private-key-base64>\" } }\n    ]\n  },\n  \"control_server\": {\n    \"address\": \"0.0.0.0:50000\",\n    \"server_key\": { \"type_id\": 1209251014, \"pvt_key\": \"<control-server-private-key-base64>\" },\n    \"clients\": {\n      \"list\": [\n        { \"type_id\": 1209251014, \"pub_key\": \"<control-client-public-key-base64>\" }\n      ]\n    }\n  },\n  \"metrics\": {\n    \"address\": \"0.0.0.0:9100\",\n    \"global_labels\": { \"network\": \"mainnet\", \"node_id\": \"validator-0\" }\n  },\n  \"collator_config\": {\n    \"cutoff_timeout_ms\": 1000,\n    \"stop_timeout_ms\": 1500,\n    \"max_collate_threads\": 10,\n    \"retry_if_empty\": false,\n    \"finalize_empty_after_ms\": 800,\n    \"empty_collation_sleep_ms\": 100,\n    \"external_messages_maximum_queue_length\": 25600\n  },\n  \"gc\": {\n    \"enable_for_archives\": true,\n    \"archives_life_time_hours\": 48,\n    \"enable_for_shard_state_persistent\": true,\n    \"cells_gc_config\": {\n      \"gc_interval_sec\": 900,\n      \"cells_lifetime_sec\": 86400\n    }\n  },\n  \"cells_db_config\": {\n    \"states_db_queue_len\": 1000,\n    \"prefill_cells_counters\": false,\n    \"cells_cache_size_bytes\": 4000000000,\n    \"counters_cache_size_bytes\": 4000000000\n  }\n}\n```\n\n### How to generate keys\n\nEach node requires multiple [Ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519) key pairs. The config references them as base64-encoded 32-byte private keys. A separate key pair is required for each purpose: DHT, overlay, liteserver, control server, and control client.\n\nAll keys in the config use the following structure:\n\n```json\n{ \"type_id\": 1209251014, \"pvt_key\": \"<base64-encoded-32-byte-private-key>\" }\n```\n\nThe `type_id` value `1209251014` corresponds to Ed25519, which is the only supported key type. Public keys, such as in `control_server.clients`, use the same structure but specify `pub_key` instead of `pvt_key`.\n\nTo generate:\n\n<Steps>\n  <Step\n    title=\"Generate private key\"\n  >\n    Generate a raw 32-byte Ed25519 private key using OpenSSL:\n\n    ```bash\n    openssl genpkey -algorithm ed25519 -outform DER | tail -c 32 | base64\n    ```\n\n    This command outputs a base64 string such as `GnEN3s5t2Z3W1e...==`. Use this value as `pvt_key`.\n  </Step>\n\n  <Step\n    title=\"Derive public key\"\n  >\n    Derive the corresponding public key from the private key:\n\n    ```bash\n    openssl genpkey -algorithm ed25519 -outform DER > /tmp/ed25519.der\n    # private key (base64):\n    tail -c 32 /tmp/ed25519.der | base64\n    # public key (base64):\n    openssl pkey -inform DER -in /tmp/ed25519.der -pubout -outform DER | tail -c 32 | base64\n    ```\n\n    Use the public key for `control_server.clients` and for publishing the liteserver key in the global config.\n  </Step>\n\n  <Step\n    title=\"Repeat the process\"\n  >\n    Repeat the process for each required key pair.\n\n    A typical full node with liteserver requires 3 key pairs:\n\n    | Key                    | Used in                     | Field     |\n    | ---------------------- | --------------------------- | --------- |\n    | DHT private key        | `adnl_node.keys[0]` (tag 1) | `pvt_key` |\n    | Overlay private key    | `adnl_node.keys[1]` (tag 2) | `pvt_key` |\n    | Liteserver private key | `lite_server.server_key`    | `pvt_key` |\n\n    A validator additionally requires:\n\n    | Key                        | Used in                          | Field                        |\n    | -------------------------- | -------------------------------- | ---------------------------- |\n    | Control server private key | `control_server.server_key`      | `pvt_key`                    |\n    | Control client key pair    | `control_server.clients.list[0]` | `pub_key` (public part only) |\n  </Step>\n</Steps>\n\n#### Quick generation script\n\nGenerate all keys at once for a full node with liteserver:\n\n```bash\n#!/bin/bash\nfor name in dht overlay liteserver; do\n  openssl genpkey -algorithm ed25519 -outform DER > /tmp/${name}.der\n  pvt=$(tail -c 32 /tmp/${name}.der | base64)\n  pub=$(openssl pkey -inform DER -in /tmp/${name}.der -pubout -outform DER | tail -c 32 | base64)\n  echo \"${name}:\"\n  echo \"  pvt_key: ${pvt}\"\n  echo \"  pub_key: ${pub}\"\n  rm /tmp/${name}.der\ndone\n```\n\nFor a validator, add `control-server` and `control-client` to the loop.\n\n<Aside\n  type=\"danger\"\n  title=\"Key reuse risk\"\n>\n  Each key must be unique. Do not reuse the same key for different purposes, such as DHT and overlay. Do not share keys between different nodes.\n</Aside>\n\n### Archival node\n\nBy default, the node prunes old block archives and state snapshots through the `gc` section. To preserve the full blockchain history, override the `gc` settings in the node configuration:\n\n```json\n{\n  \"gc\": {\n    \"enable_for_archives\": false,\n    \"enable_for_shard_state_persistent\": false,\n    \"cells_gc_config\": {\n      \"gc_interval_sec\": 900,\n      \"cells_lifetime_sec\": 86400\n    }\n  },\n  \"skip_saving_persistent_states\": false\n}\n```\n\n- `enable_for_archives: false` stops pruning of block archives. When turned off, `archives_life_time_hours` is ignored.\n- `enable_for_shard_state_persistent: false` stops `gc` from pruning persistent state snapshots. With `gc` enabled, older states are retained at decreasing frequency. Turning it off preserves all snapshots and increases disk usage.\n- `skip_saving_persistent_states: false`  ensures persistent snapshots are created. If set to `true`, snapshots are never saved regardless of `gc` settings.\n- Do not turn `cells_gc_config` off. Cells `gc` removes unreferenced cells only and does not delete blocks or states. Disabling it leads to database storage leaks.\n\nFull mainnet history is in the terabytes range and grows continuously. Make sure `storage.db.size` is large enough.\n\n## Networking\n\nA TON node needs a stable, publicly reachable IP address. Other nodes connect to the `adnl_node.ip_address` specified in the node config.\n\n### Ports and services\n\nThe chart exposes five ports. Each port is optional. Set it to `null` to omit it. `ports.adnl` is an exception and is always enabled.\n\n| Port               | Protocol | Default | Purpose                                                            |\n| ------------------ | -------- | ------- | ------------------------------------------------------------------ |\n| `ports.adnl`       | UDP      | `30303` | Peer-to-peer protocol. Must be publicly reachable.                 |\n| `ports.control`    | TCP      | `50000` | Node management; stop, restart, elections. Should remain internal. |\n| `ports.liteserver` | TCP      | `null`  | Liteserver API for external consumers.                             |\n| `ports.jsonRpc`    | TCP      | `null`  | JSON-RPC API for external consumers.                               |\n| `ports.metrics`    | TCP      | `null`  | Prometheus metrics, health and readiness probes.                   |\n\n#### Per-port services\n\nEach enabled port gets its own Kubernetes Service per replica. This allows independent configuration of the service type, annotations, and traffic policy for each port.\n\n| Port       | Service name               | Default type | Rationale                                                                                  |\n| ---------- | -------------------------- | ------------ | ------------------------------------------------------------------------------------------ |\n| ADNL       | `<release>-<i>`            | LoadBalancer | Must be publicly reachable for peer-to-peer communication.                                 |\n| control    | `<release>-<i>-control`    | ClusterIP    | Used for node management. Keep internal.                                                   |\n| liteserver | `<release>-<i>-liteserver` | LoadBalancer | Serves external API consumers.                                                             |\n| jsonRpc    | `<release>-<i>-jsonrpc`    | LoadBalancer | Serves external API consumers.                                                             |\n| metrics    | `<release>-metrics`        | ClusterIP    | Used for internal scraping only. Not per-replica, implemented through a separate template. |\n\nTo override the type per port:\n\n```yaml\nservices:\n  adnl:\n    type: LoadBalancer           # default\n    externalTrafficPolicy: Local\n  control:\n    type: ClusterIP              # default — recommended to keep internal\n  liteserver:\n    type: LoadBalancer           # default\n  jsonRpc:\n    type: LoadBalancer           # default\n```\n\nEach port's service supports `type`, `externalTrafficPolicy`, `annotations`, and [`perReplica`](/ecosystem/nodes/rust/node-config#loadbalancer-recommended) overrides.\n\n### Exposure modes\n\nThe chart supports five exposure modes. Exposure modes control how traffic reaches the pod, not which ports are enabled. Choose one mode per deployment. Modes can be combined, but this is uncommon.\n\n#### LoadBalancer (recommended)\n\nEach per-replica Service provisions a cloud load balancer or a MetalLB VIP. The external IP is assigned through provider-specific annotations on the ADNL service.\n\n```yaml\nservices:\n  adnl:\n    type: LoadBalancer\n    externalTrafficPolicy: Local\n```\n\nThis is the default. No changes are required for a basic deployment.\n\n##### Static IP assignment\n\nUse `perReplica` annotations to pin IPs. List index matches replica index.\n\n- MetalLB:\n\n  ```yaml\n  services:\n    adnl:\n      perReplica:\n        - annotations:\n            metallb.universe.tf/loadBalancerIPs: \"192.168.1.100\"\n        - annotations:\n            metallb.universe.tf/loadBalancerIPs: \"192.168.1.101\"\n  ```\n\n- AWS Elastic IP:\n\n  ```yaml\n  services:\n    adnl:\n      perReplica:\n        - annotations:\n            service.beta.kubernetes.io/aws-load-balancer-eip-allocations: \"eipalloc-aaa\"\n        - annotations:\n            service.beta.kubernetes.io/aws-load-balancer-eip-allocations: \"eipalloc-bbb\"\n  ```\n\n- GCP:\n\n  ```yaml\n  services:\n    adnl:\n      perReplica:\n        - annotations:\n            networking.gke.io/load-balancer-ip-addresses: \"my-ip-ref-0\"\n        - annotations:\n            networking.gke.io/load-balancer-ip-addresses: \"my-ip-ref-1\"\n  ```\n\nThe `adnl_node.ip_address` in the node config must match the external IP assigned to that replica's ADNL service.\n\n#### NodePort\n\nUses the Kubernetes NodePort mechanism. Traffic arrives at `<node-ip>:<nodePort>` and is forwarded to the pod.\n\n```yaml\nservices:\n  adnl:\n    type: NodePort\n    externalTrafficPolicy: Local\n```\n\nUse this mode in clusters without a LoadBalancer controller; no cloud load balancer, no MetalLB.\n\nTrade-offs:\n\n- Works on any cluster. No load balancer infrastructure required.\n- Port conflicts must be managed manually. Multiple replicas require different ports; NodePorts default range: 30000–32767.\n- The `adnl_node.ip_address` must be the node's external IP with the NodePort, not the container port.\n- The pod must run on the node whose IP is configured. Enforce this using `nodeSelector` or `nodeAffinity`.\n\n#### hostPort\n\nBinds selected container ports directly to the host network interface. The pod remains in the pod network. Only the selected ports are exposed on the host IP. Network policies continue to work.\n\nEach port can be enabled independently:\n\n```yaml\nhostPort:\n  adnl: true\n  control: false\n  liteserver: false\n  jsonRpc: false\n  metrics: false\n```\n\nUse this mode when ADNL must be exposed on the host IP without a LoadBalancer, while keeping other ports isolated in the pod network. Common in bare-metal clusters with direct public IPs assigned to nodes.\n\nTrade-offs:\n\n- Only the enabled ports are exposed on the host. Other ports remain in the pod network behind Services.\n- Network policies still work, unlike `hostNetwork`.\n- One pod per node. The port binds to `0.0.0.0` on the host. Two pods on the same node would conflict. Use `podAntiAffinity` or `nodeSelector` to spread replicas.\n- `adnl_node.ip_address` must match the host's external IP.\n\nExample with anti-affinity:\n\n```yaml\nhostPort:\n  adnl: true\n\naffinity:\n  podAntiAffinity:\n    requiredDuringSchedulingIgnoredDuringExecution:\n      - labelSelector:\n          matchLabels:\n            app.kubernetes.io/name: node\n        topologyKey: kubernetes.io/hostname\n```\n\n#### hostNetwork\n\nThe pod uses the host network stack directly. All container ports bind directly to the host IP. No NAT or Service abstraction is required. The pod itself becomes the network endpoint.\n\n```yaml\nhostNetwork: true\n```\n\nUse this mode in bare-metal deployments that require zero NAT overhead and accept the security trade-offs.\n\nTrade-offs:\n\n- Zero NAT overhead.\n- All ports are exposed on the host, including control. Restrict access using firewall rules.\n- Network policies do not work. The pod runs in the host network namespace.\n- One pod per node. Same scheduling constraint as `hostPort`.\n- `adnl_node.ip_address` must match the host's external IP.\n- Services are still created. Set `services.adnl.type: ClusterIP` if a LoadBalancer is not required.\n\nExample with anti-affinity:\n\n```yaml\nhostNetwork: true\n\naffinity:\n  podAntiAffinity:\n    requiredDuringSchedulingIgnoredDuringExecution:\n      - labelSelector:\n          matchLabels:\n            app.kubernetes.io/name: node\n        topologyKey: kubernetes.io/hostname\n```\n\n#### Ingress-nginx stream proxy\n\nReuses an existing ingress-nginx controller to forward raw TCP and UDP streams to the node's ClusterIP Services. No chart changes are required. Configuration is external.\n\nOverride the service type to ClusterIP for the ports routed through the ingress:\n\n```yaml\nservices:\n  liteserver:\n    type: ClusterIP\n  jsonRpc:\n    type: ClusterIP\n```\n\nADNL still requires external reachability. Keep it as LoadBalancer or enable `hostPort.adnl: true`.\n\nUse this mode when ingress-nginx is already deployed, and additional LoadBalancers for liteserver or JSON-RPC are not desired. ADNL still requires a direct path; LoadBalancer or hostPort.\n\nTrade-offs:\n\n- Reuses existing infrastructure. No additional load balancer cost.\n- Adds an extra proxy hop; ingress-nginx sits between the client and the node.\n- `adnl_node.ip_address` must be the ingress controller's external IP.\n- Configuration is external. The ingress-nginx `tcp-services` and `udp-services` ConfigMaps must be managed separately.\n\nExample ingress-nginx ConfigMap:\n\n```yaml\n# TCP services (control, liteserver)\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: tcp-services\n  namespace: ingress-nginx\ndata:\n  \"50000\": \"ton/my-node-0-control:50000\"\n  \"40000\": \"ton/my-node-0-liteserver:40000\"\n---\n# UDP services (ADNL)\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: udp-services\n  namespace: ingress-nginx\ndata:\n  \"30303\": \"ton/my-node-0:30303\"\n```\n\n### Comparison\n\n| Mode                 | NAT overhead | LB required              | Port management           | Network policies | Complexity |\n| -------------------- | ------------ | ------------------------ | ------------------------- | ---------------- | ---------- |\n| LoadBalancer         | DNAT         | yes (cloud LB / MetalLB) | automatic                 | yes              | low        |\n| NodePort             | kube-proxy   | no                       | manual (port ranges)      | yes              | medium     |\n| hostPort             | minimal      | no                       | manual (one pod per node) | yes              | medium     |\n| hostNetwork          | none         | no                       | manual (one pod per node) | **no**           | medium     |\n| Ingress-nginx stream | proxy hop    | no (reuses ingress)      | manual (ConfigMaps)       | yes              | medium     |\n\nLoadBalancer with a static IP is recommended for most deployments.\n\n- Use `hostPort` in bare-metal with direct public IPs when MetalLB is not available.\n- Use `hostNetwork` only when zero NAT overhead is critical, and the security trade-offs of exposing all ports are acceptable.\n\n### NetworkPolicy\n\nThe chart can create a NetworkPolicy with per-port ingress rules.\n\n```yaml\nnetworkPolicy:\n  enabled: true\n  control:\n    enabled: true\n    allowFrom:\n      - ipBlock:\n          cidr: 10.0.0.0/8\n  metrics:\n    enabled: true\n    allowFrom:\n      - namespaceSelector:\n          matchLabels:\n            name: monitoring\n```\n\nWhen `networkPolicy.enabled` is `true`:\n\n- ADNL (UDP) ingress is always created. If `networkPolicy.adnl.allowFrom` is empty, the default source is `0.0.0.0/0`.\n- TCP rules are configured independently per port: `control`, `liteserver`, `jsonRpc`, `metrics`.\n- A TCP rule is created only when both conditions are true:\n- the corresponding port is enabled in `ports.*`;\n- `networkPolicy.<port>.enabled: true`.\n- `networkPolicy.<port>.allowFrom` accepts raw Kubernetes `from` entries. If omitted or empty, source is not restricted for that rule.\n- `networkPolicy.extraIngress` appends additional raw ingress rules.\n\nThis policy covers ingress only. If the cluster enforces egress policies, outbound UDP to `0.0.0.0/0` must be allowed separately for ADNL.\n\nNetworkPolicy has no effect when `hostNetwork: true`, because the pod runs in the host network namespace.\n"
  },
  {
    "path": "ecosystem/nodes/rust/probes.mdx",
    "content": "---\ntitle: \"Health probes\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nKubernetes liveness, readiness, and startup probes for the TON node.\n\n## Available endpoints\n\nThe TON node metrics HTTP server exposes two health endpoints:\n\n| Endpoint   | Purpose         | Kubernetes probe |\n| ---------- | --------------- | ---------------- |\n| `/healthz` | Liveness check  | `livenessProbe`  |\n| `/readyz`  | Readiness check | `readinessProbe` |\n\nBoth endpoints return `HTTP 200` with a JSON body:\n\n```json\n{\n  \"status\": \"ok\",\n  \"sync_status\": 6,\n  \"last_mc_block_seqno\": 12345678,\n  \"validation_status\": 3\n}\n```\n\nThese endpoints are served by the same HTTP server as `/metrics` and require the `metrics` section in the [node config](/ecosystem/nodes/rust/node-config).\n\n<Aside type=\"note\">\n  Both `/healthz` and `/readyz` return 200 if the metrics HTTP server is running. They do not check sync status or other internal health criteria.\n</Aside>\n\n## Enabling probes\n\nProbes require `ports.metrics` to be set in the Helm values:\n\n```yaml\nports:\n  metrics: 9100\n\nprobes:\n  startup:\n    httpGet:\n      path: /healthz\n      port: metrics\n    failureThreshold: 60\n    periodSeconds: 10\n  liveness:\n    httpGet:\n      path: /healthz\n      port: metrics\n    periodSeconds: 30\n    failureThreshold: 3\n  readiness:\n    httpGet:\n      path: /readyz\n      port: metrics\n    periodSeconds: 10\n    failureThreshold: 3\n```\n\nThe `port: metrics` value references the named container port and resolves to the value defined in `ports.metrics`.\n\n## Startup probe\n\nThe startup probe is critical for TON nodes. The node may take several minutes to start, depending on:\n\n- Database size and integrity checks.\n- State loading and Merkle tree reconstruction.\n- Network bootstrap and peer discovery.\n\nWithout a startup probe, the liveness probe may restart the pod before the node finishes initializing.\n\nRecommended settings:\n\n| Parameter          | Value  | Rationale                                             |\n| ------------------ | ------ | ----------------------------------------------------- |\n| `failureThreshold` | `60`   | Allows up to 10 minutes for initialization (60 x 10s) |\n| `periodSeconds`    | `10` s | Checks every 10 seconds                               |\n\nOnce the startup probe succeeds, Kubernetes switches to the liveness and readiness probes.\n\n## Tuning\n\n### Validators\n\nValidators have stricter uptime requirements. Use tighter probe settings:\n\n```yaml\nprobes:\n  startup:\n    httpGet:\n      path: /healthz\n      port: metrics\n    failureThreshold: 60\n    periodSeconds: 10\n  liveness:\n    httpGet:\n      path: /healthz\n      port: metrics\n    periodSeconds: 15\n    failureThreshold: 3\n  readiness:\n    httpGet:\n      path: /readyz\n      port: metrics\n    periodSeconds: 5\n    failureThreshold: 2\n```\n\n### Full nodes and liteservers\n\nFull nodes are more tolerant of brief interruptions. The default values from the enabling probes are appropriate.\n\n### Without the metrics port\n\nIf the metrics HTTP server cannot be enabled, configure a TCP socket probe on the control port as a basic liveness check:\n\n```yaml\nports:\n  control: 50000\n\nprobes:\n  liveness:\n    tcpSocket:\n      port: control\n    periodSeconds: 30\n    failureThreshold: 3\n```\n\nA TCP socket probe only verifies that the port accepts connections. It does not check node health. Use this approach only when the metrics endpoint cannot be enabled.\n"
  },
  {
    "path": "ecosystem/nodes/rust/quick-start.mdx",
    "content": "---\ntitle: \"Rust node quick start\"\nsidebarTitle: \"Quick start\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nDeploy a TON Rust node using the Helm chart.\n\nFor chart-specific values, configuration examples, and operator documentation such as networking, Vault, and monitoring, refer to the [chart README](https://github.com/RSquad/ton-rust-node/tree/master/helm/ton-rust-node).\n\n## Image configuration\n\nThe Helm chart defines the container image through Helm values:\n\n- `image.repository`\n- `image.tag`\n\nAvoid relying on a hard-coded tag in the documentation, because default values can change between chart releases.\n\nTo see the current defaults, refer to:\n\n- [Chart values](https://raw.githubusercontent.com/RSquad/ton-rust-node/master/helm/ton-rust-node/values.yaml)\n- [Chart `appVersion`](https://raw.githubusercontent.com/RSquad/ton-rust-node/master/helm/ton-rust-node/Chart.yaml)\n\n## Node roles\n\nThe chart deploys the same TON Rust node binary in two operational roles: validator and full node.\n\n| Role      | Purpose                                                          | Ports to expose                                                                                                      |\n| --------- | ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |\n| Validator | Participates in consensus and validator elections.               | Keep `liteserver` and `jsonRpc` disabled; expose only required node and ops ports (`adnl`, and `control` if needed). |\n| Full node | Syncs chain and serves external clients (APIs, explorers, bots). | Enable `liteserver`, `jsonRpc`, or both when external access is required.                                            |\n\n- Run validators and full nodes as separate Helm releases so resources, security policy, and lifecycle stay isolated.\n- If full chain history is needed, enable archival mode as described in [Archival node settings](/ecosystem/nodes/rust/node-config#archival-node).\n\n## Quick start\n\n### Prerequisites\n\n- Kubernetes cluster access configured for `helm`.\n- [Helm 3 installed](https://helm.sh/docs/intro/install/).\n- Access to the chart at `./helm/ton-rust-node` by cloning the [`ton-rust-node` repository](https://github.com/RSquad/ton-rust-node/tree/master/helm/ton-rust-node).\n- A values file for the release, for example `values.yaml`.\n\nInstall and deploy TON Rust node with [Helm](https://helm.sh) using a minimal configuration, then optionally enable liteserver and JSON Remote Procedure Call (JSON-RPC) ports.\n\nTo deploy a validator, use this page for base deployment and keep the liteserver and JSON-RPC ports disabled. For validator election and operations workflow, use the validator guide [(`nodectl`)](https://github.com/RSquad/ton-rust-node/tree/master/helm/nodectl).\n\n### 1. Prepare a values file\n\nNot runnable\n\n```yaml title=\"values.yaml\"\n\nreplicas: 2\n\nservices:\n  adnl:\n    perReplica:\n      - annotations:\n          metallb.universe.tf/loadBalancerIPs: \"1.2.3.4\"\n      - annotations:\n          metallb.universe.tf/loadBalancerIPs: \"5.6.7.8\"\n\nnodeConfigs:\n  node-0.json: |\n    { \"log_config_name\": \"/main/logs.config.yml\", ... }\n  node-1.json: |\n    { \"log_config_name\": \"/main/logs.config.yml\", ... }\n```\n\nThe chart includes a mainnet [`globalConfig`](/ecosystem/nodes/rust/global-config) and a default [`logsConfig`](/ecosystem/nodes/rust/logs-config). This minimal setup requires only [`nodeConfigs`](/ecosystem/nodes/rust/node-config).\n\nOther networking modes are described in the [Networking section](/ecosystem/nodes/rust/node-config#networking), including `NodePort`, `hostPort`, `hostNetwork`, and ingress controllers such as `ingress-nginx`.\n\n### 2. Install the release\n\nAll `helm` commands below require [Helm to be installed](https://helm.sh/docs/intro/install/) and available in `PATH`.\n\nUse the local chart from [`ton-rust-node/helm/ton-rust-node`](https://github.com/RSquad/ton-rust-node/tree/e8bd0451b326099146a90a913beedaebd952fa56/helm/ton-rust-node):\n\n```bash\nhelm install <RELEASE_NAME> ./helm/ton-rust-node -f <VALUES_FILE>\n```\n\nOr install from an Open Container Initiative registry:\n\n```bash\nhelm install <RELEASE_NAME> oci://ghcr.io/rsquad/ton-rust-node/helm/node -f <VALUES_FILE>\n```\n\n## Verify deployment\n\nCheck pod status for the release:\n\n```bash\nkubectl get pods -l app.kubernetes.io/name=node,app.kubernetes.io/instance=<RELEASE_NAME>\n```\n\nCheck service status for the release:\n\n```bash\nkubectl get svc -l app.kubernetes.io/name=node,app.kubernetes.io/instance=<RELEASE_NAME>\n```\n\n## Enable liteserver and JSON-RPC ports\n\nUse this only for full node deployments. Do not expose these ports on validators.\n\nNot runnable\n\n```yaml\nreplicas: 2\n\nports:\n  liteserver: 40000\n  jsonRpc: 8081\n\nservices:\n  adnl:\n    perReplica:\n      - annotations:\n          metallb.universe.tf/loadBalancerIPs: \"10.0.0.1\"\n      - annotations:\n          metallb.universe.tf/loadBalancerIPs: \"10.0.0.2\"\n\nnodeConfigs:\n  node-0.json: |\n    { \"log_config_name\": \"/main/logs.config.yml\", ... }\n  node-1.json: |\n    { \"log_config_name\": \"/main/logs.config.yml\", ... }\n```\n\n## Run multiple releases in the same namespace\n\nUse different release names:\n\n```bash\nhelm install validator ./helm/ton-rust-node -f validator-values.yaml\nhelm install fullnode ./helm/ton-rust-node -f fullnode-values.yaml\n```\n\nThis creates separate StatefulSets (`validator`, `fullnode`), services (`validator-0`, `fullnode-0`), and configs.\n\n## Operational notes\n\n### Helm hooks\n\nThis chart does not rely on [Helm hooks](https://helm.sh/docs/topics/charts_hooks/) for bootstrap. Instead, an init container seeds `/main` from ConfigMaps and Secrets before the main container starts.\n\nIf pre- or post-deployment actions are required, such as backups before upgrades or data integrity checks, implement them outside the chart. This can be done in a CI/CD pipeline, dedicated Jobs, or Helm hooks in a wrapper chart.\n\nChart implementation references:\n\n- [Init bootstrap script](https://raw.githubusercontent.com/RSquad/ton-rust-node/master/helm/ton-rust-node/files/init-script.sh)\n- [StatefulSet init container](https://raw.githubusercontent.com/RSquad/ton-rust-node/master/helm/ton-rust-node/templates/statefulset.yaml)\n\n### Ingress and TLS\n\n- The chart does not create Kubernetes `Ingress` resources.\n\n  For UDP and TCP stream ports, including ADNL UDP, liteserver TCP, control TCP, a standard HTTP Ingress is not sufficient.\n\n  If `ingress-nginx` is already used, [TCP and UDP ports can be exposed](https://kubernetes.github.io/ingress-nginx/user-guide/exposing-tcp-udp-services/) through its `tcp-services` and `udp-services` ConfigMaps, which enable stream proxying.\n\n- TLS termination depends on the protocol used by the exposed port.\n\n  - For HTTP-based ports such as some JSON-RPC setups, terminate TLS at an L7 proxy or an Ingress controller that supports HTTP routing.\n  - For pure TCP stream proxying, terminate TLS at an external load balancer or TCP proxy, or use a TCP proxy that supports TLS passthrough or termination.\n  - ADNL uses UDP and is typically exposed directly through `LoadBalancer`, `hostPort`, or `hostNetwork`. TLS termination does not apply to it in the same way as for HTTP.\n\n- [Chart networking reference](https://raw.githubusercontent.com/RSquad/ton-rust-node/master/helm/ton-rust-node/docs/networking.md)\n\n### PVC resizing and retention\n\nThe chart defines `volumeClaimTemplates` in the StatefulSet for `main`, `db`, `keys`, and optionally `logs`.\n\nPVC resizing (expansion) depends on the StorageClass configuration. If the StorageClass is `allowVolumeExpansion: true`, the PVC size can be increased by editing the PVC. Shrinking PVCs is not supported.\n\nRelated Kubernetes documentation:\n\n- [PVC expansion overview](https://kubernetes.io/blog/2018/07/12/resizing-persistent-volumes-using-kubernetes/)\n- If data must be preserved, consider using the PersistentVolume [reclaim policy](https://kubernetes.io/docs/tasks/administer-cluster/change-pv-reclaim-policy/) `Retain` instead of the default `Delete` for dynamically provisioned volumes.\n\nChart retention configuration:\n\n- The chart supports `helm.sh/resource-policy: keep` for selected PVCs through `storage.<vol>.resourcePolicy`; defaults keep for `main` and `keys`.\n- [Values chart](https://raw.githubusercontent.com/RSquad/ton-rust-node/master/helm/ton-rust-node/values.yaml)\n\n### Safe upgrades, backups, and rolling restarts\n\n1. Use `helm upgrade` with an explicit image tag bump.\n1. Treat the `db` and `keys` PVCs as critical state. Plan backups according to the storage backend.\n1. Configuration changes:\n   - Inline configuration changes trigger pod restarts through a checksum annotation.\n   - External `existing*` ConfigMaps and Secrets are managed outside the chart. Changing them does not trigger an automatic rollout. Restart the pods or upgrade the release explicitly.\n\n### Exposure mode examples\n\n- Use one [exposure mode](/ecosystem/nodes/rust/node-config#exposure-modes) per deployment. Combining modes is possible but uncommon.\n- [Chart implementation reference for per-port Services](https://raw.githubusercontent.com/RSquad/ton-rust-node/master/helm/ton-rust-node/templates/services.yaml)\n\n### Vault integration using VAULT\\_URL\n\nThe chart supports an operator workflow where private keys are stored in an encrypted vault file, and the vault URL is passed through the `VAULT_URL` environment variable.\n\nRecommended configuration (Secret-based):\n\n```yaml\nvault:\n  secretName: ton-node-vault\n  secretKey: VAULT_URL\n```\n\nThe Secret should contain `VAULT_URL`. Example format: `file:///keys/vault.json&master_key=<64-hex-chars>`.\n\n<Aside\n  type=\"caution\"\n>\n  In the RSquad chart workflow, Vault is configured through `VAULT_URL`. Do not rely on `secrets_vault_config` in `config.json` when using this approach.\n\n  Keep the vault master key secure: it decrypts the vault file.\n</Aside>\n\n- [Chart Vault reference](https://raw.githubusercontent.com/RSquad/ton-rust-node/master/helm/ton-rust-node/docs/vault.md)\n- Chart implementation references:\n  - [`VAULT_URL` injection helper](https://raw.githubusercontent.com/RSquad/ton-rust-node/master/helm/ton-rust-node/templates/_helpers.tpl)\n  - [Container env wiring](https://raw.githubusercontent.com/RSquad/ton-rust-node/master/helm/ton-rust-node/templates/statefulset.yaml)\n\n## Useful commands\n\n```bash\n# Check pod status (replace \"my-node\" with the release name)\nkubectl get pods -l app.kubernetes.io/name=node,app.kubernetes.io/instance=my-node\n\n# Get external service IPs\nkubectl get svc -l app.kubernetes.io/name=node,app.kubernetes.io/instance=my-node\n\n# View logs\nkubectl logs my-node-0 -c ton-node\n\n# Exec into pod\nkubectl exec -it my-node-0 -c ton-node -- /bin/sh\n```\n"
  },
  {
    "path": "ecosystem/oracles/overview.mdx",
    "content": "---\ntitle: \"Oracles overview\"\nsidebarTitle: \"Overview\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\nimport { Image } from '/snippets/image.jsx';\n\nBlockchain oracles are entities that connect the blockchain to external systems, allowing smart contracts to be executed based on real-world inputs.\n\n## How blockchain oracles work\n\nBlockchain oracles are specialized services that act as bridges between the real world and blockchain technology. They provide smart contracts with relevant and necessary information from the outside world, such as exchange rates, payment statuses, or even weather conditions. This data helps to automate and fulfill the terms of contracts without direct human intervention.\n\nThe basic principle behind oracles is their ability to function outside of the blockchain by connecting to various online sources to collect data. Although oracles are not part of the blockchain itself, they play a key role in making it functional by acting as a trusted intermediary that reliably feeds external data into the system.\n\nMost oracles tend to be decentralized, avoiding the risks associated with dependence on a single source of data. This provides greater security and reliability to the system as data is verified and validated through a network of nodes before it is used in smart contracts. This approach minimizes the risk of manipulation and errors, ensuring that the information provided is accurate and up-to-date.\n\n## Varieties of blockchain oracles\n\nBlockchain oracles are categorized according to various aspects: mechanism of operation, data sources, data direction, and governance structure. Let's take a look at the most common types of oracles.\n\n### Push and pull oracles\n\nPush and pull oracles differ in how they deliver data to an on-chain smart contract.\n\nFor push oracle, the data provider constantly updates info, _pushing_ the newest data to the centralized trusted contract.\n\nRead more about oracle model differences: [ChainLink - Pull vs Push oracles](https://chain.link/education-hub/pull-oracles-vs-push-oracles).\n\nFor pull oracle, users should retrieve the latest data from the off-chain data provider themselves, then verify it using the oracle contract. [Learn more](#oracles-in-ton) about data verification flow with pull model oracles.\n\nGiven TON actor-model, pull oracles prove to be more suited for real world applications.\n\n### Centralized and decentralized oracles\n\nCentralized oracles are controlled by a single party, which creates security and reliability risks. Decentralized oracles use multiple nodes to verify data, making them more secure and reliable.\n\n### Cross-chain oracles\n\nThese oracles are used to transfer data between different blockchains and are a critical component of bridges. They are used for decentralized applications that use cross-chain transactions, such as cross-chain transfer of crypto assets from one network to another.\n\n## Application of blockchain oracles\n\nBlockchain oracles build bridges between the digital world of blockchains and real life, opening up a wide range of applications. Let's take a look at some of the most popular uses of oracles.\n\n### DeFi (decentralized finance)\n\nOracles play a critical role in the DeFi ecosystem by providing market price and cryptocurrency data. Price oracles allow DeFi platforms to link token values to real assets, which is essential for controlling liquidity and securing users' positions. Additionally, oracles are vital for lending platforms, where accurate price data ensures proper collateral valuation and risk management, safeguarding both lenders and borrowers. This makes transactions more transparent and secure, contributing to the stability and reliability of financial transactions.\n\n### Prediction markets\n\nOracles can automatically read and analyze data from a variety of sources to determine the occurrence of real-life events. This enables prediction and insurance contracts to automatically pay claims, reducing the need for manual processing of each case and speeding up response times to events.\n\n### Random number generation\n\nIt is difficult to generate random numbers in smart contracts because all operations must be reproducible and predictable, which contradicts the concept of randomness. Computational oracles solve this problem by bringing data from the outside world into contracts. They can generate verifiable random numbers for games and lotteries, ensuring fairness and transparency of results.\n\nRead more: [Randomness in TON](/contract-dev/random)\n\n## Oracles in TON\n\nSince the TON execution model is asynchronous, the classic ways to interact with oracles (get methods during transaction) can't be applied here. You can learn about the differences in [\"Coming from Ethereum\"](/from-ethereum) article. The best pattern to retrieve data from an oracle is the Request-Response pattern - you send an internal message to the oracle contract and verify the response, getting the needed data.\n\nThis model works well with pull oracles, since you can always guarantee the lowest possible latency for real-world data. If you use push oracle, you will still need to process two internal messages (request and response) to retrieve data. However, data relevance is limited by the data provider's up-time and pushing intervals: if the data provider pushes updated data every 10 minutes, you will commonly receive information that is outdated by 5 minutes. But using pull oracle, you can ensure pushes as often as your service needs by updating the data yourself.\n\n### Push oracle flow\n\n0. Data provider pushes the latest data on-chain\n\n0. The user contract, which needs prices on-chain, sends a request message to the trusted oracle contract\n\n0. Oracle contract replies to the sender address with a response internal message, containing the requested data\n\n0. User contract receives oracle response, verifies sender address, and then is ready to use the provided data\n\n### Pull oracle flow\n\n1. Users' off-chain backend calls the API method on the data provider\n\n1. Provider responds with signed price data (including timestamp till this data is valid)\n\n3-4. User sends a message to his on-chain contract that will need prices (and the rest of the business logic)\n\n5. User contract sends \"Verify that this price is correctly signed and valid\" internal message to the oracle contract\n\n5. Oracle contract verifies signature, timestamp, and price feed ID. If everything is okay, it sends a response with the prices back\n\n5. User contract receives a response from the oracle contract, checks if the sender is really the oracle, and then can use the provided data\n\n<Image\n  src=\"/resources/images/oracles/oracle-flow.svg\"\n  alt=\"oracle-flow\"\n/>\n\n## List of oracles in TON\n\n- [RedStone](/ecosystem/oracles/redstone)\n- [Pyth](/ecosystem/oracles/pyth)\n"
  },
  {
    "path": "ecosystem/oracles/pyth.mdx",
    "content": "---\ntitle: \"Pyth oracle\"\n---\n\n## How to use real-time data in TON contracts\n\nPyth is a pull oracle. Pyth price feeds on TON are managed through the main TON Pyth smart\ncontract, enabling seamless interaction with on-chain data. In TON,\nthese interactions are facilitated by specific functions within the\nPyth TON contract. This contract acts as an interface to Pyth\nprice feeds, handling the retrieval and updating of price data.\n\n## Install the Pyth SDK\n\nInstall the Pyth TON SDK and other necessary dependencies using npm or yarn:\n\n```bash\nnpm install @pythnetwork/pyth-ton-js @pythnetwork/hermes-client @ton/core @ton/ton @ton/crypto\n```\n\n## Write code to interact with oracle\n\n### Off-chain data fetch and update\n\nThe following code snippet demonstrates how to fetch price updates, interact with the Pyth contract on TON, and update price feeds:\n\n- TON Mainnet: [`EQA5NPyjfZztDm8jcTBwTAU9NGsgJEkw19z61yecX0TlseSB`](https://docs.pyth.network/price-feeds/contract-addresses/ton)\n- TON Testnet: [`EQBeydTZBuv4nkqN8jkScqZbWcyx7TsmOtxsEDbFann0IRtD`](https://docs.pyth.network/price-feeds/contract-addresses/ton)\n\nThe following example uses the testnet contract. For mainnet usage, change the `PYTH_CONTRACT_ADDRESS_TESTNET` to `PYTH_CONTRACT_ADDRESS_MAINNET` accordingly.\n\n```ts expandable\nimport { TonClient, Address, WalletContractV4 } from \"@ton/ton\";\nimport { mnemonicToPrivateKey } from \"@ton/crypto\";\nimport { HermesClient } from \"@pythnetwork/hermes-client\";\nimport {\n  PythContract,\n  PYTH_CONTRACT_ADDRESS_TESTNET,\n  PYTH_CONTRACT_ADDRESS_MAINNET,\n  calculateUpdatePriceFeedsFee,\n} from \"@pythnetwork/pyth-ton-js\";\n\nconst BTC_PRICE_FEED_ID =\n  \"0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43\";\n\nasync function main() {\n  // Initialize TonClient\n  const client = new TonClient({\n    endpoint: \"https://testnet.toncenter.com/api/v2/jsonRPC\",\n    apiKey: \"your-api-key-here\", // Get your TON Center API key via @tonapibot or https://t.me/toncenter (optional)\n  });\n\n  // Create PythContract instance\n  const contractAddress = Address.parse(PYTH_CONTRACT_ADDRESS_TESTNET);\n  const contract = client.open(PythContract.createFromAddress(contractAddress));\n\n  // Get current guardian set index\n  const guardianSetIndex = await contract.getCurrentGuardianSetIndex();\n  console.log(\"Guardian Set Index:\", guardianSetIndex);\n\n  // Get BTC price from TON contract\n  const price = await contract.getPriceUnsafe(BTC_PRICE_FEED_ID);\n  console.log(\"BTC Price from TON contract:\", price);\n\n  // Fetch latest price updates from Hermes\n  const hermesEndpoint = \"https://hermes.pyth.network\";\n  const hermesClient = new HermesClient(hermesEndpoint);\n  const priceIds = [BTC_PRICE_FEED_ID];\n  const latestPriceUpdates = await hermesClient.getLatestPriceUpdates(\n    priceIds,\n    { encoding: \"hex\" }\n  );\n  console.log(\"Hermes BTC price:\", latestPriceUpdates.parsed?.[0].price);\n\n  // Prepare update data\n  const updateData = Buffer.from(latestPriceUpdates.binary.data[0], \"hex\");\n  console.log(\"Update data:\", updateData);\n\n  // Get update fee\n  const updateFee = await contract.getUpdateFee(updateData);\n  console.log(\"Update fee:\", updateFee);\n  const totalFee =\n    calculateUpdatePriceFeedsFee(BigInt(updateFee)) + BigInt(updateFee);\n\n  // Update price feeds\n  const mnemonic = \"your mnemonic here\";\n  const key = await mnemonicToPrivateKey(mnemonic.split(\" \"));\n  const wallet = WalletContractV4.create({\n    publicKey: key.publicKey,\n    workchain: 0,\n  });\n\n  const provider = client.open(wallet);\n  await contract.sendUpdatePriceFeeds(\n    provider.sender(key.secretKey),\n    updateData,\n    totalFee\n  );\n\n  console.log(\"Price feeds updated successfully.\");\n}\n\nmain().catch(console.error);\n```\n\n## Additional resources\n\nYou may find these additional resources helpful for developing your TON application:\n\n- [Pyth price feed IDs](https://pyth.network/developers/price-feed-ids)\n- [Pyth TON contract](https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/ton/contracts)\n- [Pyth TON SDK](https://github.com/pyth-network/pyth-crosschain/tree/main/target_chains/ton/sdk)\n- [Pyth TON example](https://github.com/pyth-network/pyth-examples/tree/main/price_feeds/ton/sdk_js_usage)\n"
  },
  {
    "path": "ecosystem/oracles/redstone.mdx",
    "content": "---\ntitle: \"RedStone oracle\"\n---\n\n## How to use real-time data in TON contracts\n\nRedStone is a pull oracle that uses an alternative design for providing oracle data to smart contracts. Instead of constantly persisting data on the contract's storage, the information is brought on-chain only when needed by end users. Until that moment, data remains in the decentralized cache layer, powered by RedStone light cache gateways and a stream-based data broadcasting protocol.\n\nData is transferred to the contract by end users, who attach signed data packages to their function invocations. The information integrity is verified on-chain through signature checking.\n\n## Install the RedStone SDK\n\nInstall the RedStone TON connector and other necessary dependencies:\n\n```bash\nnpm install @redstone-finance/ton-connector @redstone-finance/sdk\n```\n\n## Write code to interact with oracle\n\n### Off-chain data fetch and update\n\nThe following code snippet demonstrates how to fetch price updates and interact with RedStone contracts on TON:\n\n```ts\nimport { TonPricesContractConnector } from \"@redstone-finance/ton-connector\";\nimport { ContractParamsProvider, getSignersForDataServiceId } from \"@redstone-finance/sdk\";\n\nasync function main() {\n  // Configure API endpoint\n  const apiV2Config = {\n    apiEndpoint: \"https://testnet.toncenter.com/api/v2/jsonRPC\",\n    apiKey: \"your-api-key-here\", // Get your TON Center API key\n  };\n\n  // Initialize the connector\n  const contractAddress = \"EQCMxfukwpP3BI_6Pn3lmOXgxlp3dPabVGOM0UvJCjsDhkdD\";\n  const prices = new TonPricesContractConnector(network, contractAddress);\n\n  // Configure RedStone data service parameters\n  const paramsProvider = new ContractParamsProvider({\n    dataServiceId: \"redstone-main-demo\",\n    uniqueSignersCount: 1,\n    dataPackagesIds: [\"ETH\", \"BTC\"],\n    authorizedSigners: getSignersForDataServiceId(\"redstone-main-demo\"),\n  });\n\n  // Get prices using on-the-fly processing (doesn't modify contract state)\n  const pricesFromPayload = await (await prices.getAdapter()).getPricesFromPayload(paramsProvider);\n  console.log(\"ETH and BTC prices from payload:\", pricesFromPayload);\n\n  // Write prices to contract storage (modifies contract state)\n  await (await prices.getAdapter()).writePricesFromPayloadToContract(paramsProvider);\n  console.log(\"Prices written to contract storage successfully.\");\n\n  // Read prices from contract storage\n  const storedPrices = await (await prices.getAdapter()).readPricesFromContract(paramsProvider);\n  console.log(\"Stored prices:\", storedPrices);\n\n  // Get timestamp of last update\n  const lastUpdateTimestamp = await (await prices.getAdapter()).readTimestampFromContract();\n  console.log(\"Last update timestamp:\", lastUpdateTimestamp);\n}\n\nmain().catch(console.error);\n```\n\nThis code snippet does the following:\n\n1. Imports the `TonPricesContractConnector` and sets up the RedStone SDK.\n1. Configures the API endpoint and creates a connector to your deployed contract.\n1. Sets up a `ContractParamsProvider` with the data service ID and feed identifiers.\n1. Fetches price data using on-the-fly processing (no gas cost).\n1. Writes price data to the contract's storage (requires gas).\n1. Reads stored prices and the last update timestamp from the contract.\n\n## Contract types\n\nRedStone provides several contract types for different use cases:\n\n### Price Manager\n\nManages multiple price feeds with signature verification and supports both on-the-fly processing and storage persistence.\n\n### Single Feed Manager\n\nSimplified version for handling a single price feed, reducing gas costs for single-feed applications.\n\n### Price Feed\n\nAn individual feed contract that stores price data for a specific asset.\n\n### Sample Consumer\n\nExample consumer contract that demonstrates how to read data from price feeds.\n\n## Error handling\n\nCommon error codes you might encounter:\n\n- **300+**: Insufficient valid signers (less than `signer_count_threshold`)\n- **200+**: Timestamp validation failed (data too old or in the future)\n- **Other codes**: See [RedStone constants](https://github.com/redstone-finance/redstone-oracles-monorepo/blob/main/packages/ton-connector/src/config/constants.ts)\n\n## Additional resources\n\nYou may find these additional resources helpful for developing your TON application:\n\n- [RedStone documentation](https://docs.redstone.finance/docs/introduction)\n- [RedStone TON connector](https://github.com/redstone-finance/redstone-oracles-monorepo/tree/main/packages/ton-connector)\n- [RedStone smart contracts](https://github.com/redstone-finance/redstone-oracles-monorepo/tree/main/packages/ton-connector/contracts)\n- [RedStone showroom](https://ton-showroom.redstone.finance/)\n"
  },
  {
    "path": "ecosystem/sdks.mdx",
    "content": "---\ntitle: \"SDKs\"\nmode: \"wide\"\n---\n\nThere are several ways to interact with TON blockchain:\n\n- **HTTP** libraries connect through HTTP JSON APIs to read and write to the blockchain. HTTP servers mostly relay these requests to the ADNL network.\n- **ADNL** libraries connect to [liteserver](/ecosystem/nodes/overview#interacting-with-ton-nodes).\n\nHere's a small comparison of these protocols:\n\n|                                                      | HTTP            | ADNL            |\n| ---------------------------------------------------- | --------------- | --------------- |\n| Standardized                                         | No              | Yes             |\n| Can connect from a web page                          | Yes             | No              |\n| Has free third-party servers                         | Yes             | Yes             |\n| Can be self-hosted                                   | Yes             | Yes             |\n| Requires trusting third parties                      | Yes<sup>1</sup> | No              |\n| First connection takes time for data synchronization | No              | Yes<sup>2</sup> |\n\n<sup>1</sup> Some HTTP servers do provide proofs, but there is no out‑of‑the‑box library that verifies them. <br />\n<sup>2</sup> If proofs returned by liteservers are ignored, the first connection skips data synchronization; however, this requires trusting the liteserver.\n\nSDKs might also provide some other functionality:\n\n- **Core** libraries implement standard TON data structures (cell, slice), formats (address, mnemonic), cryptography, etc.\n- **Wrappers** provide high-level APIs for interacting with standard contracts (Wallet, Jetton, NFT).\n- **Emulator** libraries provide an execution environment similar to a real blockchain for testing purposes.\n\n|    |                                    | HTTP | ADNL | Core | Wrappers | Emulator | Language   |                                                                  |                                                                                              |                                    |\n| -- | ---------------------------------- | ---- | ---- | ---- | -------- | -------- | ---------- | ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | ---------------------------------- |\n| ⭐ | `@ton/ton`                         | ✅   |      |      | ✅       |          | TypeScript | [Code](https://github.com/ton-org/ton)                           |                                                                                              | [Chat](https://t.me/tondev_eng)    |\n| ⭐ | `@ton/core`                        |      |      | ✅   |          |          | TypeScript | [Code](https://github.com/ton-org/ton-core)                      | [Docs](https://ton-org.github.io/ton-core/)                                                  |                                    |\n| ⭐ | `@ton/sandbox`                     |      |      |      |          | ✅       | TypeScript | [Code](https://github.com/ton-org/sandbox)                       |                                                                                              |                                    |\n| ⭐ | `ton4j`                            | ✅   |      | ✅   |          | ✅       | Java       | [Code](https://github.com/neodix42/ton4j)                        |                                                                                              | [Chat](https://t.me/ton4java)      |\n| ⭐ | `tonutils-go`                      |      | ✅   | ✅   | ✅       |          | Go         | [Code](https://github.com/xssnick/tonutils-go)                   |                                                                                              | [Chat](https://t.me/tonutils)      |\n| ⭐ | `tonutils`                         | ✅   | ✅   | ✅   | ✅       |          | Python     | [Code](https://github.com/nessshon/tonutils)                     | [Docs](https://tonutils.ness.su/)                                                            | [Chat](https://t.me/pythonnton)    |\n|    | `adnl`                             |      | ✅   |      |          |          | TypeScript | [Code](https://github.com/tonkite/adnl)                          |                                                                                              |                                    |\n|    | `tonutils`                         |      | ✅   |      |          |          | TypeScript | [Code](https://github.com/thekiba/tonutils)                      |                                                                                              |                                    |\n|    | `tonlib-java`                      |      | ✅   |      |          |          | Java       | [Code](https://github.com/ton-blockchain/tonlib-java)            |                                                                                              |                                    |\n|    | `tonlib`                           |      | ✅   |      |          |          | C++        | [Code](https://github.com/ton-blockchain/ton/tree/master/tonlib) | [Docs](https://github.com/ton-blockchain/ton/tree/master/example/cpp)                        |                                    |\n|    | `ton-kotlin`                       |      | ✅   | ✅   |          |          | Kotlin     | [Code](https://github.com/ton-community/ton-kotlin)              | [Docs](https://github.com/ton-blockchain/ton-kotlin/wiki/TON-Kotlin-documentation)           |                                    |\n|    | `pytonlib`                         |      | ✅   |      |          |          | Python     | [Code](https://github.com/toncenter/pytonlib)                    |                                                                                              |                                    |\n|    | `pytoniq`                          |      | ✅   |      |          |          | Python     | [Code](https://github.com/yungwine/pytoniq)                      | [Docs](https://yungwine.gitbook.io/pytoniq-doc/)                                             | [Chat](https://t.me/pythonnton)    |\n|    | `pytoniq-core`                     |      |      | ✅   |          |          | Python     | [Code](https://github.com/yungwine/pytoniq-core)                 | [Docs](https://yungwine.gitbook.io/pytoniq-doc/)                                             | [Chat](https://t.me/pythonnton)    |\n|    | `mytonlib`                         |      | ✅   | ✅   |          |          | Python     | [Code](https://github.com/igroman787/mytonlib)                   |                                                                                              |                                    |\n|    | `tonpy`                            |      |      | ✅   |          |          | Python     | [Code](https://github.com/disintar/tonpy)                        | [Docs](https://tonpy.dton.io/)                                                               |                                    |\n|    | `tvm_valuetypes`                   |      |      | ✅   |          |          | Python     | [Code](https://github.com/toncenter/tvm_valuetypes)              |                                                                                              |                                    |\n|    | `pytvm`                            |      |      |      |          | ✅       | Python     | [Code](https://github.com/yungwine/pytvm)                        |                                                                                              |                                    |\n|    | `tongo`                            |      | ✅   | ✅   | ✅       | ✅       | Go         | [Code](https://github.com/tonkeeper/tongo)                       |                                                                                              |                                    |\n|    | `ton`                              | ✅   |      |      |          |          | PHP        | [Code](https://github.com/olifanton/ton)                         |                                                                                              |                                    |\n|    | `interop`                          |      |      | ✅   |          |          | PHP        | [Code](https://github.com/olifanton/interop)                     |                                                                                              |                                    |\n|    | `ton-rs`                           |      | ✅   | ✅   | ✅       | ✅       | Rust       | [Code](https://github.com/ston-fi/ton-rs)                        |                                                                                              |                                    |\n|    | `ton-grpc`                         |      | ✅   |      |          |          | Rust       | [Code](https://github.com/getgems-io/ton-grpc)                   |                                                                                              |                                    |\n|    | `tonsdk.net`                       |      | ✅   | ✅   |          |          | C#         | [Code](https://github.com/continuation-team/TonSdk.NET)          |                                                                                              | [Chat](https://t.me/cont_team/104) |\n|    | `tonlib.net`                       |      | ✅   | ✅   | ✅       |          | C#         | [Code](https://github.com/justdmitry/TonLib.NET)                 |                                                                                              |                                    |\n|    | `ton`                              |      |      | ✅   |          |          | Elixir     | [Code](https://github.com/ayrat555/ton)                          |                                                                                              |                                    |\n|    | `@tetherto/wdk-wallet-ton`         | ✅   |      |      | ✅       |          | JavaScript | [Code](https://github.com/tetherto/wdk-wallet-ton)               | [Docs](https://github.com/tetherto/wdk-docs/tree/main/sdk/wallet-modules/wallet-ton)         |                                    |\n|    | `@tetherto/wdk-wallet-ton-gasless` | ✅   |      |      | ✅       |          | JavaScript | [Code](https://github.com/tetherto/wdk-wallet-ton-gasless)       | [Docs](https://github.com/tetherto/wdk-docs/tree/main/sdk/wallet-modules/wallet-ton-gasless) |                                    |\n|    | ~~`tonlib-go`~~                    |      | ✅   |      |          |          | Go         | [Code](https://github.com/ton-blockchain/tonlib-go)              |                                                                                              |                                    |\n|    | ~~`tonweb`~~                       | ✅   |      |      |          |          | JavaScript | [Code](https://github.com/toncenter/tonweb)                      |                                                                                              |                                    |\n|    | ~~`node-tonlib`~~                  |      | ✅   |      |          |          | JavaScript | [Code](https://github.com/labraburn/node-tonlib)                 |                                                                                              |                                    |\n|    | ~~`tontools`~~                     | ✅   | ✅   |      |          |          | Python     | [Code](https://github.com/yungwine/TonTools)                     |                                                                                              |                                    |\n|    | ~~`swiftyton`~~                    |      | ✅   |      |          |          | Swift      | [Code](https://github.com/labraburn/SwiftyTON)                   |                                                                                              |                                    |\n|    | ~~`tonlib-xcframework`~~           |      | ✅   |      |          |          | Swift      | [Code](https://github.com/labraburn/tonlib-xcframework)          |                                                                                              |                                    |\n|    | ~~`tonlib-rs`~~                    |      | ✅   | ✅   | ✅       | ✅       | Rust       | [Code](https://github.com/ston-fi/ton-rs)                        |                                                                                              |                                    |\n\nSee also:\n\n- [WDK Core](https://github.com/tetherto/wdk-core), JavaScript - Modular library from Tether, which supports wallet management and various swap, bridge, and lending services for many blockchains at once.\n"
  },
  {
    "path": "ecosystem/staking/liquid-staking.mdx",
    "content": "---\ntitle: \"Liquid staking contracts\"\nsidebarTitle: \"Liquid staking\"\n---\n\nThe [liquid staking contract](https://github.com/ton-blockchain/liquid-staking-contract) enables staking services to issue liquid staking tokens (LSTs) representing an underlying staking position. LSTs can be used in DeFi while the underlying TON earns rewards.\n\n## Staking providers\n\nThird-party staking providers who use a liquidity pool for staking:\n\n|                   Protocol                   | Min deposit |  Liquidity  | Voting |          Withdrawal          | Decentralized validation |\n| :------------------------------------------: | :---------: | :---------: | :----: | :--------------------------: | :----------------------: |\n|     [Tonstakers](https://tonstakers.com)     |    1 TON    | Yes (tsTON) |   Yes  | Up to 18h (instant possible) |            Yes           |\n|         [Bemo](https://bemo.finance)         |    1 TON    | Yes (bmTON) |   No   |        36-72h cooldown       |            No            |\n|         [Hipo](https://hipo.finance)         |    Varies   |  Yes (hTON) |   No   |  Avg 30h (instant possible)  |            No            |\n| [TON Nominators](https://tonvalidators.org/) |  10,000 TON |      No     |   Yes  |           Up to 18h          |            No            |\n\nTonstakers offers automated compounding and decentralized validation.\n\n<Aside type=\"note\">\n  All validators participating in these protocols use MyTonCtrl for validation. For validator setup instructions, see:\n\n  - [Tonstakers setup](/ecosystem/node/mytonctrl/liquid-staking)\n  - [Nominator pool setup](/ecosystem/node/mytonctrl/pools#nominator-pool-operations-nominator-pool-mode)\n  - [Single nominator pool setup](/ecosystem/node/mytonctrl/pools#single-nominator-pool-operations-single-nominator-mode)\n</Aside>\n\n## Combining staking with DeFi\n\nStaking can be combined with various DeFi strategies to maximize returns and unlock additional value from staked assets.\n\n### Liquid staking strategies\n\n1. Re-staking liquid tokens\n\n   After staking TON and receiving liquid tokens such as tsTON, stake these tokens again to earn additional yields. This creates a compounding effect where staking rewards are earned on both the original stake and the liquid token rewards.\n1. DeFi integration\n\n   Use liquid staking tokens in lending protocols, DEX liquidity pools, and other DeFi applications to earn multiple yield streams simultaneously.\n\n[Tonstakers Earn](https://tonstakers.com/) provides detailed strategies and examples covering leveraged staking, collateral staking, and DEX liquidity provision.\n\n### Vesting contracts with staking\n\nLocked token purchases:\n\nTokens acquired through vesting contracts remain locked but can be staked to participate in validation and earn rewards during the lock period.\nThis approach allows holders to generate rewards from locked assets throughout the vesting period.\n\nVesting contracts support multiple [staking options](/standard/vesting#staking-options).\n\n## See also\n\n- [Staking links on ton.org](https://ton.org/en/stake)\n- [MyTonCtrl validator guide](/ecosystem/node/mytonctrl/validator)\n- [MyTonCtrl nominator pools](/ecosystem/node/mytonctrl/pools)\n- [Vesting contracts](/standard/vesting)\n- [Catchain consensus](https://docs.ton.org/catchain.pdf)\n"
  },
  {
    "path": "ecosystem/staking/nominator-pools.mdx",
    "content": "---\ntitle: \"Nominator pool contracts\"\nsidebarTitle: \"Nominator pools\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\n\n[Nominator pool contracts](https://github.com/ton-blockchain/nominator-pool) allow multiple nominators to delegate their stake to a validator without running validator infrastructure themselves. Funds from nominators are combined with the validator's own stake and used for network validation. The pool contract handles rewards and penalties according to predefined rules.\n\n## Key parameters\n\n- Minimum nominator stake: 10,000 TON, recommended.\n- Maximum nominators per pool: 40.\n- Operational costs: approximately 5 TON per validation round, paid by the validator.\n- Withdrawals: full withdrawal only; partial withdrawals are not supported.\n- Governance: nominators can participate in network configuration voting.\n\n## When to use\n\n- Staking below the validator minimum of 300,000 TON.\n- Delegating stake to trusted validators without running infrastructure.\n- Participating in network governance.\n- Using a simple staking model without liquidity tokens or DeFi participation.\n\n## How it works\n\n1. Nominators deposit funds into a pool managed by a validator.\n1. The validator stakes the combined funds, including the validator's own and nominators' stakes, for validation.\n1. Rewards are distributed proportionally:\n   - The validator receives a commission defined by `validator_reward_share`.\n   - The remaining rewards are distributed to nominators based on their stake size.\n1. If the validator is penalized:\n   - The penalty is first deducted from the validator's balance.\n   - If the validator balance is insufficient, losses are deducted proportionally from nominators.\n1. The validator must maintain enough balance to cover the maximum possible penalties.\n\n## How to stake\n\n1. Choose a pool on [TON Nominators](https://tonvalidators.org/) and review its parameters, commission, and minimum stake.\n1. Send a message to the nominator pool contract with:\n   - The desired TON amount.\n   - The text comment \"d\" for deposit.\n1. The sent amount must be at least `min_nominator_stake + 1 TON`, while 1 TON is deducted as the deposit fee.\n1. If the pool is not currently validating, the deposit is credited immediately; otherwise, it is added to pending deposits.\n\n## How to withdraw\n\n1. Send a message to the nominator pool contract with:\n   - The text comment \"w\" for withdraw.\n   - Approximately 1 TON for network fees.\n1. If the pool has sufficient balance, the withdrawal is processed immediately.\n1. If not, a withdrawal request is created and processed later.\n1. Only full withdrawal is supported.\n\n<Aside\n  type=\"caution\"\n  title=\"Staking and withdrawal risks\"\n>\n  These steps transfer TON to a smart contract. Transactions are irreversible.\n\n  Verify the contract address and network (mainnet vs testnet) before sending funds. Withdrawals depend on pool liquidity and may be delayed if insufficient balance is available. Only full withdrawals are supported.\n\n  Incorrect comments or insufficient fees may result in failed or delayed operations.\n</Aside>\n\n## How to vote\n\n1. Find the proposal hash posted in [`@tonblockchain`](https://t.me/tonblockchain) or [`@tonstatus`](https://t.me/tonstatus).\n1. Send a message with comment `\"y<HASH>\"` to vote for or `\"n<HASH>\"` to vote against.\n   - Example: `\"yD855FFBCF813E50E10BEAB902D1177529CE79785CAE913EB96A72AE8EFBCBF47\"`.\n1. Attach approximately 1 TON for network fees.\n\n## Reward calculation\n\nReward data can be obtained using the [TON Center nominator pools API](https://toncenter.com/api/smc-index/):\n\n- [getPoolBookings](/ecosystem/api/toncenter/smc-index/get-pool-bookings-method) – get all the bookings, including debits and credits, in a specified pool.\n- [getNominatorBookings](/ecosystem/api/toncenter/smc-index/get-nominator-bookings-method) – get nominator bookings, including debits and credits, in a specified pool.\n- [getNominatorEarnings](/ecosystem/api/toncenter/smc-index/get-nominator-earnings-method) – get nominator income in a specified pool, including stake amounts on each time point.\n- [getNominator](/ecosystem/api/toncenter/smc-index/get-nominator-method) – get the nominator's balances across all pools in which the nominator participates.\n- [getPool](/ecosystem/api/toncenter/smc-index/get-pool-method) – get pool data, including all nominators.\n\n## Validator setup\n\n- Use [MyTonCtrl nominator pools](/ecosystem/node/mytonctrl/pools#nominator-pool-operations-nominator-pool-mode) for standard multi-nominator operation.\n- Pools can technically be configured with a minimum stake of 100 TON; however, 10,000 TON is the tested and recommended value.\n- Validators can deploy pools manually using the [nominator pool contract](https://github.com/ton-blockchain/nominator-pool) without MyTonCtrl.\n"
  },
  {
    "path": "ecosystem/staking/overview.mdx",
    "content": "---\ntitle: \"Staking overview\"\nsidebarTitle: \"Overview\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\nimport { Image } from '/snippets/image.jsx';\n\n[Staking in TON](https://ton.org/en/stake) enables earning rewards by locking Toncoin to support network security and validation. TON supports several staking solutions, each designed for different use cases and operational models.\n\nStaking secures the network through [proof-of-stake](https://en.wikipedia.org/wiki/Proof_of_stake). Depending on technical ability, stake size, and participation goals, users may choose between single nominator, nominator pools, or liquid staking. Some solutions are suitable only for technically experienced operators, while others are intended for businesses providing staking as a service. However, all solutions require non-trivial setup, and there are limited number of support tools.\n\n## Overview of staking solutions\n\nThe following smart contracts are commonly used in the TON ecosystem:\n\n|                                    Option                                   |                        Intention                       |                           Features                           |\n| :-------------------------------------------------------------------------: | :----------------------------------------------------: | :----------------------------------------------------------: |\n| [Liquid staking](https://github.com/ton-blockchain/liquid-staking-contract) |        Staking providers servicing retail users.       |  Liquidity and DeFi integration via wrapped staking tokens.  |\n|    [Single nominator](https://github.com/ton-blockchain/single-nominator)   |       Large holders staking only their own funds.      | Secure, contract-based self-staking; simple ownership model. |\n|      [Nominator pool](https://github.com/ton-blockchain/nominator-pool)     | Small group of nominators delegating to one validator. |    Has significant limitations; generally not recommended.   |\n\n<Aside\n  type=\"caution\"\n  title=\"Stake requirements\"\n>\n  The technical minimum stake required to participate in validation is 300,000 TON. However, the actual minimum stake is typically higher, approximately 1,000,000 TON.\n\n  Validator stakes can be viewed on [tonscan.org/validators](https://tonscan.org/validators). Scroll to the bottom of the list to see the validator with the lowest stake included in the current round.\n</Aside>\n\n## Liquid staking\n\nThe [liquid staking contract](/ecosystem/staking/liquid-staking) enables staking services to issue liquid staking tokens (LSTs) that represent the underlying staking position. LSTs can be used in DeFi while the underlying TON earns rewards.\n\n### Key characteristics\n\n- Users deposit TON and receive wrapped tokens, e.g. tsTON, that can be used in DeFi.\n- Liquidity remains accessible even when underlying funds are staked.\n- Flexible staker-validator connections without centralized pools.\n- Low minimum deposits for broader participation.\n- Some protocols allow governance influence.\n- Reduced slashing risks using diversification.\n- Easy fund spreading across validators.\n\n### Recommended use\n\n- Staking providers serving retail users.\n- Projects building liquid staking products or yield-bearing tokens.\n- Operators who want to run staking services without committing significant personal funds.\n\n## Single nominator pools\n\n[Single nominator pool contract](/ecosystem/staking/single-nominator) is the standard solution designed for large holders who want to stake their own funds while delegating validator operations to a trusted operator.\n\n<Aside type=\"note\">\n  The single nominator pool contract is the recommended staking solution.\n</Aside>\n\n### Key characteristics\n\n- Supports exactly one nominator.\n- Separates the owner's cold wallet from the validator's hot wallet to prevent theft if the validator node is compromised.\n- The owner can recover stakes even in extreme scenarios, such as elector contract upgrades.\n- Any modification would require a professional audit, which is costly and time-consuming; therefore, the contract remains intentionally unchanged.\n\n### Recommended use\n\nThis solution is suitable for:\n\n- Large TON holders who stake only their own funds.\n- Setups that require separation between fund custody (owner wallet) and validator node operations.\n\n## Nominator pools\n\n[Nominator pools](/ecosystem/staking/nominator-pools) are smart contracts that allow a small group of nominators to combine their funds and delegate to a validator for staking collectively. However, it has limitations and safety concerns.\n\n<Aside\n  type=\"caution\"\n>\n  The nominator pool is deprecated and is not recommended for use.\n</Aside>\n\n### Limitations\n\n- Only the owner can withdraw funds from the pool.\n- Supports up to approximately 40 nominators, which is not suitable for large pools.\n- Not designed for small deposits or retail participation.\n- Sending a message to the pool without a bounce flag may result in funds becoming locked.\n\n### Notes\n\n- The contract is not deprecated, but it is rarely an appropriate choice in practice.\n- For large holders, the single nominator contract is preferred.\n- This solution is not recommended for new staking services.\n\n## Differences from standard nominator pools\n\n- Lower minimum stake of 50 TON, compared to 10,000 TON in standard pools.\n- Custom contract architecture with separate owner, controller, proxy, and pool contracts.\n- Fee model where deposit and withdrawal fees vary by pool; users should check pool details before staking.\n\n## Recommendations for staking solutions\n\nFor large holders staking only their own funds:\n\n- Use a single nominator contract for direct self-staking, or\n- Stake through a reputable third-party staking provider.\n\nFor operators intending to run staking services for others:\n\n- Use liquid staking contracts, which are appropriate when accepting deposits from retail users or when building DeFi-compatible staking tokens.\n\nFor small holders:\n\n- Use a third-party staking service rather than running contracts directly.\n\nThe following recommendations are mapped onto the Cartesian plane below. The horizontal axis represents legal restrictions and setup complexity, while the vertical axis represents the operational model.\n\n<div\n  style={{ display: \"flex\", justifyContent: \"center\" }}\n>\n  <Image\n    src=\"/resources/images/staking-cartesian-light.png\"\n    darkSrc=\"/resources/images/staking-cartesian-dark.png\"\n    width={500}\n    height={500}\n    alt=\"Recommendations\"\n  />\n</div>\n\n## Staking providers\n\nThird-party staking providers who use a liquidity pool for staking:\n\n|                   Protocol                   | Min deposit |  Liquidity  | Voting |          Withdrawal          | Decentralized validation |\n| :------------------------------------------: | :---------: | :---------: | :----: | :--------------------------: | :----------------------: |\n|     [Tonstakers](https://tonstakers.com)     |    1 TON    | Yes (tsTON) |   Yes  | Up to 18h (instant possible) |            Yes           |\n|         [Bemo](https://bemo.finance)         |    1 TON    | Yes (bmTON) |   No   |        36-72h cooldown       |            No            |\n|         [Hipo](https://hipo.finance)         |    Varies   |  Yes (hTON) |   No   |  Avg 30h (instant possible)  |            No            |\n| [TON Nominators](https://tonvalidators.org/) |  10,000 TON |      No     |   Yes  |           Up to 18h          |            No            |\n\nTonstakers offers automated compounding and decentralized validation.\n\nAll validators participating in these third-party protocols use MyTonCtrl for validation. For validator setup instructions, see:\n\n- [Tonstakers setup](/ecosystem/node/mytonctrl/liquid-staking)\n- [Nominator pool setup](/ecosystem/node/mytonctrl/pools#nominator-pool-operations-nominator-pool-mode)\n- [Single nominator pool setup](/ecosystem/node/mytonctrl/pools#single-nominator-pool-operations-single-nominator-mode)\n"
  },
  {
    "path": "ecosystem/staking/single-nominator.mdx",
    "content": "---\ntitle: \"Single nominator pool contracts\"\nsidebarTitle: \"Single nominator pools\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\n\n[Single nominator pool contracts](https://github.com/ton-blockchain/single-nominator) are designed for validators with [sufficient self-stake](https://tonscan.org/validators) who want to validate independently, without involving other participants.\n\n## How it works\n\n1. The owner, a cold wallet, securely holds staking funds offline.\n1. The owner deposits funds into the single nominator pool contract.\n1. The validator, a hot wallet on the node, instructs the contract to participate in validation cycles.\n1. The contract transfers the stake to the elector for validation.\n1. After the validation cycle completes, the validator instructs the contract to recover the stake.\n1. The owner can withdraw funds at any time; withdrawals are restricted to the owner only.\n\n## Security properties\n\n- The validator's hot wallet cannot withdraw or steal funds.\n- If the validator is compromised, the owner can immediately update the validator address.\n- The owner can send raw messages to recover the stake in emergencies.\n- In extreme cases, the owner can upgrade the contract code.\n\n## Validator setup\n\nFollow the [MyTonCtrl single nominator pools guide](/ecosystem/node/mytonctrl/pools#single-nominator-pool-operations-single-nominator-mode).\n\n## Nominator instructions\n\n- To deposit, send an empty message with TON to the single nominator pool contract.\n- To withdraw, send a message with 1 TON and the text comment \"w\" (withdraw) to the contract.\n\n<Aside\n  type=\"caution\"\n  title=\"Verify contract and message parameters\"\n>\n  Depositing or withdrawing requires sending TON directly to a smart contract. Incorrect amounts, message comments, or contract addresses may result in irreversible fund loss.\n\n  Before using mainnet, verify the contract address and message format, and test on testnet where possible.\n</Aside>\n\n## Reward and penalty tracking\n\n- Separate APIs are typically unnecessary, as the validator and the nominator are usually the same entity. This is the original design assumption.\n- If validation and staking are managed by different parties, rewards, penalties, and fees must be calculated explicitly.\n  - Penalties should be attributed to the validator, as they result from operational or hardware issues.\n- TON Center does not provide a dedicated API for single nominator pools.\n  - This is similar to the limitations described for the [nominator pools API](/ecosystem/api/toncenter/smc-index/get-nominator-bookings-method).\n"
  },
  {
    "path": "ecosystem/status.mdx",
    "content": "---\ntitle: \"Network status\"\n---\n\nThis page lists websites that show if specific parts of TON blockchain are working normally.\n\n|                                |                                                               |\n|--------------------------------|---------------------------------------------------------------|\n| https://tonstat.us/            | HTTP and ADNL server availability and performance.            |\n| https://status.toncenter.com/  | Low-level metrics, such as latencies, rates, and loads.       |\n| https://validators.ton.org/    | Official validation dashboard.                                |\n| https://tonscan.com/validation | Pretty validation dashboard.                                  |\n| https://t.me/tonstatus         | Notifications and requests for action for mainnet validators. |\n| https://t.me/testnetstatus     | Notifications and requests for action for testnet validators. |\n| https://t.me/validators        | Bot for validator owners to track their status.               |\n"
  },
  {
    "path": "ecosystem/tma/analytics/analytics.mdx",
    "content": "---\ntitle: \"Telegram analytics\"\n---\n\n## Overview\n\nTelegram Analytics is a powerful SDK and API that enables your mini-application to become a rich source of actionable data. By tracking user activity within your app, it transforms that data into clear, useful analytics that can help you optimize your application and enhance user engagement.\n\nThis library does not collect or store any private user data. It tracks app launches, TON Connect interactions, and GDPR-compliant events in an anonymous format. This data is used solely to rank applications in the catalog based on their performance and Streaks.\n\n## Environment support\n\n- Modern browsers\n- Server-side Rendering\n- [All known](https://telegram.org/apps) Telegram clients\n\n| <Icon icon=\"/resources/images/tma-browsers-icons/edge_48x48.png\" /> Edge | <Icon icon=\"/resources/images/tma-browsers-icons/firefox_48x48.png\" /> Firefox | <Icon icon=\"/resources/images/tma-browsers-icons/chrome_48x48.png\" /> Chrome | <Icon icon=\"/resources/images/tma-browsers-icons/safari_48x48.png\" /> Safari | <Icon icon=\"/resources/images/tma-browsers-icons/safari_48x48.png\" /> iOS |\n| ------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------- |\n| >= 79                                                                    | >= 78                                                                          | >= 73                                                                        | >= 12.0                                                                      | >= 12.0                                                                   |\n\n## Resources\n\n- **Example Mini App:** Typescript version — [dApp](https://github.com/Dimitreee/demo-dapp-with-analytics).\n- **Docs:** Access latest docs at [gitbook](https://docs.tganalytics.xyz/).\n\n## Installation\n\nGenerate an access token through the [TON Builders](https://builders.ton.org). For detailed instructions on how to connect the SDK and receive a token, please refer to the [documentation](https://docs.tganalytics.xyz/).\nAfter token generation, you need to initialize the SDK.\n\nThere are two ways to initialize analytics: using CDN and the script tag, or using the NPM package.\n\n### Using a CDN\n\nTo add the Telegram Analytics SDK via CDN, include the following scripts in your HTML head:\n\n```html\n<script\n    async\n    src=\"https://tganalytics.xyz/index.js\"\n    onload=\"initAnalytics()\"\n    type=\"text/javascript\"\n></script>\n```\n\n```html\n<script>\n    function initAnalytics() {\n      window.telegramAnalytics.init({\n        token: 'YOUR_TOKEN', // SDK Auth token received via @DataChief_bot\n        appName: 'ANALYTICS_IDENTIFIER', // The analytics identifier you entered in @DataChief_bot\n      });\n    }\n</script>\n```\n\n- [Example](https://github.com/sorawalker/demo-dapp-with-analytics/blob/patch-1/index.html)\n\n### Using the NPM\n\nInstall using the npm:\n\n```sh icon=\"npm\"\nnpm install @telegram-apps/analytics\n```\n\nTo ensure that all events are collected correctly, you must initialize the SDK before the application starts rendering. For example, in React applications, before calling the render() function\n\n```javascript\nimport telegramAnalytics from '@telegram-apps/analytics';\n\ntelegramAnalytics.init({\n    token: 'YOUR_TOKEN', // SDK Auth token received via @DataChief_bot\n    appName: 'ANALYTICS_IDENTIFIER', // The analytics identifier you entered in @DataChief_bot\n});\n```\n\nAfter initializing the Telegram Analytics, you are all set to transfer the data, gain insights, and improve user engagement. Most of them will be tracked automatically without manual control.\n\n- [Example](https://github.com/sorawalker/demo-dapp-with-analytics/blob/master/src/main.tsx)\n\n## Contributing\n\nContributions are welcome! To contribute, fork the repository, make your changes, and submit a pull request. We look forward to your innovative [ideas](https://github.com/Telegram-Mini-Apps/TelegramAnalytics/pulls) and improvements.\n\n## License\n\nThis Telegram Analytics SDK is available under the [MIT License](https://opensource.org/license/mit). Feel free to use it in both personal and commercial projects.\n\nThe library was expertly developed by [`@sorawalker`](https://github.com/sorawalker), with generous support from [TON Foundation](https://github.com/ton-society/grants-and-bounties/).\n"
  },
  {
    "path": "ecosystem/tma/analytics/api-endpoints.mdx",
    "content": "---\ntitle: \"API Endpoints\"\n---\n\nHere, you can view information about existing endpoints and how to make\nrequests for them.\n\n## API URL\n\nURL for POST requests: [`/events`](https://tganalytics.xyz/events)\n\n## POST events\n\nThis request is needed to record an event in the database.\n\n### Body\n\nThe request body may contain an array rather than a single event. The main thing is that all events in the array satisfy the scheme below.\n\n#### Required\n\n| Field        | Type   | Description                                                                                                                                               |\n| ------------ | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `user_id`    | number | Unique identifier for the user.                                                                                                                           |\n| `event_name` | string | The name of the event from the supported events.                                                                                                          |\n| `session_id` | string | Session identifier for tracking user sessions. **Must be** [UUID](https://github.com/Telegram-Mini-Apps/analytics/blob/master/src/utils/generateUUID.ts). |\n| `app_name`   | string | The name of the application that you specified when creating the token                                                                                    |\n\n#### Optional\n\n| Field              | Type                                  | Description                                                                                   |\n| ------------------ | ------------------------------------- | --------------------------------------------------------------------------------------------- |\n| `is_premium`       | boolean                               | If the user has a premium account, by default - false                                         |\n| `is_success`       | boolean                               | Indicates whether a wallet is connected or the transaction was successful, by default - false |\n| `error_message`    | string                                | Error message if the wallet connection or transaction is unsuccessful                         |\n| `error_code`       | number                                | Description: error code if the wallet connection or transaction is unsuccessful               |\n| `wallet_address`   | string                                | Wallet address involved in the event                                                          |\n| `wallet_type`      | string                                | Type of the wallet                                                                            |\n| `wallet_version`   | string                                | Version of the wallet software                                                                |\n| `auth_type`        | enum                                  | Type of authorization used. `0` - `ton_addr`, `1` - `ton_proof`.                              |\n| `valid_until`      | string                                | Timestamp until when a transaction offer is valid                                             |\n| `from`             | string                                | Wallet address initiating the transaction                                                     |\n| `messages`         | `{ address: string; amount: string }` | List of transactions `{to, amount}` involved in the event                                     |\n| `custom_data`      | object                                | Object to store custom event details as needed                                                |\n| `client_timestamp` | string                                | The time when the event occurred on the client                                                |\n| `platform`         | string                                | The platform from which the MiniApp was opened                                                |\n| `locale`           | string                                | User language code                                                                            |\n| `start_param`      | string                                | `tgWebAppStartParam`                                                                          |\n| `url_referer`      | string                                | The URL of the web application from which the request was sent                                |\n| `scope`            | string                                | Event scope                                                                                   |\n\n### Request body example:\n\n```json\n[\n  {\n    \"event_name\": \"app-init\",\n    \"session_id\": \"10c574d9-6d2c-4e6d-a141-ce6da141ce6d\",\n    \"user_id\": 111111111,\n    \"app_name\": \"docs\",\n    \"is_premium\": true,\n    \"platform\": \"tdesktop\",\n    \"locale\": \"en\",\n    \"client_timestamp\": \"1743503599534\"\n  }\n]\n```\n\n```json\n[\n  {\n    \"event_name\": \"connection-started\",\n    \"custom_data\": {\n      \"ton_connect_sdk_lib\": \"3.0.3\",\n      \"ton_connect_ui_lib\": \"2.0.5\"\n    },\n    \"session_id\": \"10c574d9-6d2c-4e6d-a141-ce6da141ce6d\",\n    \"user_id\": 111111111,\n    \"app_name\": \"docs\",\n    \"is_premium\": true,\n    \"platform\": \"tdesktop\",\n    \"locale\": \"en\",\n    \"client_timestamp\": \"1743503647541\"\n  }\n]\n```\n\n```json\n[\n  {\n    \"event_name\": \"connection-error\",\n    \"is_success\": false,\n    \"error_message\": \"Connection was cancelled\",\n    \"error_code\": null,\n    \"custom_data\": {\n      \"ton_connect_sdk_lib\": \"3.0.3\",\n      \"ton_connect_ui_lib\": \"2.0.5\"\n    },\n    \"session_id\": \"10c574d9-6d2c-4e6d-a141-ce6da141ce6d\",\n    \"user_id\": 111111111,\n    \"app_name\": \"docs\",\n    \"is_premium\": true,\n    \"platform\": \"tdesktop\",\n    \"locale\": \"en\",\n    \"client_timestamp\": \"1743503683701\"\n  }\n]\n```\n\n### Headers\n\nInstead of `YOUR_TOKEN`, you need to specify the token received using the managing integration. (TO DO link)\n\n```json\n{\n    \"TGA-Auth-Token\": \"YOUR_TOKEN\",\n    \"Content-Type\": \"application/json\"\n}\n```\n\n### Responses\n\n#### HTTP201\n\n- Description: The event has been successfully recorded\n- Content:\n\n```json\n{\n    \"message\": \"Success record.\"\n}\n```\n\n#### HTTP400\n\n- Description: The event was not recorded due to server issues\n- Content:\n\n```json\n{\n    \"message\": \"Failed to record\"\n}\n```\n\n#### HTTP400\n\n- Description: The token was entered incorrectly or in the wrong format\n- Content:\n\n```json\n{\n    \"message\": \"The token is not specified in the headers or is specified incorrectly.\"\n}\n```\n\n#### HTTP400\n\n- Description: The entered token is invalid (was not created through a Data Chief bot)\n- Content:\n\n```json\n{\n    \"message\": \"Token is invalid.\"\n}\n```\n\n#### HTTP400\n\n- Description: The request body contains the application name that does not match the token\n- Content:\n\n```json\n{\n    \"message\": \"Invalid app_name is specified.\"\n}\n```\n\n#### HTTP400\n\n- Description: the body specified in the request was not validated (for example, the type of one of the fields does not match)\n- Content:\n\n```json\n{\n    \"status\": 400,\n    \"message\": \"VALIDATION_MISMATCH_REPORT\"\n}\n```\n\n#### HTTP403\n\n- Description: an attempt to use the API on a domain name that does not match the token\n- Content:\n\n```json\n{\n    \"message\": \"The domain name does not match.\"\n}\n```\n\n#### HTTP429\n\n- Description: too many requests from the client in a certain amount of time\n- Content:\n\n```json\n{\n    \"message\": \"Too many requests. Try again later.\"\n}\n```\n"
  },
  {
    "path": "ecosystem/tma/analytics/faq.mdx",
    "content": "---\ntitle: \"FAQ\"\n---\n\n## How can I check the integration status of the SDK?\n\n### Using a bot\n\nAfter [completing the integration process](/ecosystem/tma/analytics/preparation#initialize-sdk), the bot [`@DataChief_bot`](https://t.me/DataChief_bot) will display the time of the last recorded event in our database. If it shows something like \"one minute ago\", then everything is working correctly.\n\n### Using DevTools\n\n#### Desktop version\n\nGo to Telegram settings, then to Advanced Settings, and then to Experimental Settings. Toggle on the \"Enable webview inspecting\" function.\n\nNext, open your application and right-click to open the developer console. In the Network section, you should see the SDK script (index.js) loading and sending events. If this is not observed, try refreshing the application without closing TMA.\n\n#### Web version\n\nGo to [Telegram's web version](https://web.telegram.org/), open the developer tools, go to the network section, open your TMA, and filter queries by `'tganalytics.xyz'`. You'll see the SDK being loaded (index.js) and events being sent afterward.\n"
  },
  {
    "path": "ecosystem/tma/analytics/install-via-npm.mdx",
    "content": "---\ntitle: \"Installation via NPM package\"\n---\n\n## How to install it?\n\n**1. Install the NPM package in  your project**\n\n```shell\nnpm install @telegram-apps/analytics\n```\n\n```shell\nyarn add @telegram-apps/analytics\n```\n\n```sh\npnpm add @telegram-apps/analytics\n```\n\n**2. Add Telegram Mini Apps Analytics in code**\n\nOnce you have your unique access token (if not, see [Preparations](/ecosystem/tma/analytics/preparation) page) and installed the NPM package, you can initialize the Telegram Analytics SDK in your code. To ensure that all events are collected correctly, you must initialize the SDK before the application starts rendering. For example, in React applications, before calling the `render()` function\n\n```jsx\nimport TelegramAnalytics from '@telegram-apps/analytics'\n\nTelegramAnalytics.init({\n    token: 'YOUR_TOKEN',\n    appName: 'ANALYTICS_IDENTIFIER',\n});\n```\n\n### Supported events\n\nAfter initializing the **Telegram analytics**, you are all set to transfer the data, gain insights, and improve user engagement. (99% of them will be tracked **automatically** without manual control)\n- [Supported events](/ecosystem/tma/analytics/supported-events)\n"
  },
  {
    "path": "ecosystem/tma/analytics/install-via-script.mdx",
    "content": "---\ntitle: \"Installation via script tag\"\n---\n\n## How to install it?\n\n### 1.Add Telegram Mini Apps Analytics to your project**\n\nInclude the Telegram Mini Apps Analytics script in the header of your HTML document. This script will allow you to track and analyze user interactions effectively.\n\n```html\n<!-- Add Telegram Analytics script to HTML head -->\n<script\n    async\n    src=\"https://tganalytics.xyz/index.js\"\n    onload=\"initAnalytics()\"\n    type=\"text/javascript\"\n></script>\n```\n\nAlternative solution (not recommended)\n\n```html\n<!-- Add Telegram Analytics script to HTML head -->\n<script\n    async\n    src=\"https://unpkg.com/@telegram-apps/analytics@latest/dist/index.js\"\n    onload=\"initAnalytics()\"\n    type=\"text/javascript\"\n></script>\n```\n\n### 2. Initialize the **Telegram Mini Apps Analytics** SDK\n\nOnce you have your unique access token and analytics identifier (if not, see Preparations (TO DO link)  page), you can initialize the Telegram Analytics SDK in your code. This step is crucial for enabling the tracking of events without repeatedly transferring the token.\n\n```html\n<script>\n    function initAnalytics() {\n      window.telegramAnalytics.init({\n        token: 'YOUR_TOKEN',\n        appName: 'ANALYTICS_IDENTIFIER',\n      });\n    }\n</script>\n```\n\n### Supported events\n\nAfter initializing the **Telegram Analytics**, you are all set to transfer the data, gain insights, and improve user engagement. (99% of them will be tracked **automatically** without manual control)\n\n- [Supported events](/ecosystem/tma/analytics/supported-events)\n"
  },
  {
    "path": "ecosystem/tma/analytics/managing-integration.mdx",
    "content": "---\ntitle: \"Managing integration\"\n---\n\nimport { Image } from '/snippets/image.jsx';\n\n[TON Builders](https://builders.ton.org) helps you manage your SDK keys and participate in various support programs from TON Foundation.\n\nRegister your project and go to the **Analytics** tab.\n\n<Image\n  src=\"/resources/images/tma-analytics/analytics-preparations-1.png\"\n  darkSrc=\"/resources/images/tma-analytics/analytics-preparations-1.png\"\n  alt=\"Analytics tab in TON Builders\"\n/>\n\nEnter your Telegram Bot URL and mini app domain to receive an **API key** for SDK initialization. You can also manage your existing keys from the same section.\n"
  },
  {
    "path": "ecosystem/tma/analytics/preparation.mdx",
    "content": "---\ntitle: \"Preparations\"\n---\n\nimport { Image } from '/snippets/image.jsx';\n\n### Connect the TON Connect SDK\n\nWeb3 events for the Telegram Mini Apps Analytics SDK are supported by the [`@tonconnect/ui`](https://www.npmjs.com/package/@tonconnect/ui) and [`@tonconnect/ui-react`](https://www.npmjs.com/package/@tonconnect/ui-react) libraries since version 2.0.3, [`@tonconnect/sdk`](https://www.npmjs.com/package/@tonconnect/sdk) since version 3.0.3.\n\n[Read more about TON Connect integration](https://github.com/ton-connect)\n\nDon't worry if your app doesn't use TON Connect; the analytics SDK will still work and collect non-Web3 events.\n\n### Get the token with TON Builders\n\nRegister your project on [TON Builders](https://builders.ton.org) and go to the Analytics tab.\n\n<Image\n  src=\"/resources/images/tma-analytics/analytics-preparations-1.png\"\n  darkSrc=\"/resources/images/tma-analytics/analytics-preparations-1.png\"\n  alt=\"Analytics tab in TON Builders\"\n/>\n\nEnter your Telegram Bot URL and mini app domain to receive an **API key** for SDK initialization. You can also manage your existing keys from the same section. Enter your Telegram Bot URL and mini app domain to receive a token for SDK initialization.\n\n### Initialize SDK\n\nNow you can initialize the SDK in your application. There are two ways to do this:\n\n- [Install with script tag](/ecosystem/tma/analytics/install-via-script)\n- [Install with NPM package](/ecosystem/tma/analytics/install-via-npm)\n"
  },
  {
    "path": "ecosystem/tma/analytics/supported-events.mdx",
    "content": "---\ntitle: \"Supported events\"\n---\n\nEvents from TON Connect will be sent only if `@tonconnect/ui-react@2.0.3`, `@tonconnect/ui@2.0.3` or `@tonconnect/sdk@3.0.3` and higher versions packages are used.\n\n| Event name                       | Description                                                                              | TON Connect required |\n| -------------------------------- | ---------------------------------------------------------------------------------------- | -------------------- |\n| `app-init`                       | Connection attempts and their initiation                                                 | false                |\n| `app-hide`                       | Hiding the app from the screen                                                           | false                |\n| `custom-event`                   | The event specified by the user                                                          | false                |\n| `connection-started`             | The user starts connecting the wallet                                                    | true                 |\n| `connection-completed`           | Successful connection to a wallet                                                        | true                 |\n| `connection-error`               | Errors in connection specifying reasons (e.g., user canceled)                            | true                 |\n| `connection-restoring-completed` | The connection was restored successfully                                                 | true                 |\n| `connection-restoring-error`     | Connection restoration failed                                                            | true                 |\n| `transaction-sent-for-signature` | The user submits the transaction for signature                                           | true                 |\n| `transaction-signed`             | The user successfully signs the transaction                                              | true                 |\n| `transaction-signing-failed`     | The user cancels the transaction signature or an error occurs during the signing process | true                 |\n| `disconnection\tuser-initiated`   | Disconnection events, specifying scope (dApp or wallet)                                  | true                 |\n"
  },
  {
    "path": "ecosystem/tma/create-mini-app.mdx",
    "content": "---\ntitle: \"TMA create CLI\"\n---\n\n`@telegram-apps/create-mini-app` is a CLI tool designed to scaffold your new\nmini application on the Telegram Mini Apps platform. It generates a project with pre-configured libraries and template files,\nallowing you to customize the content based on your specific requirements.\n\n## Usage\n\nTo run the tool, use one of the following scripts depending on your package manager.\n\n```bash npm icon=\"npm\"\nnpx @telegram-apps/telegram-apps-tools@latest\n```\n\n## Creating a new application\n\nThe above command executes a script that guides you through the creation of\nyour application by sequentially prompting for the following information:\n\n### Project directory name\n\n- **Prompt**: Enter the name of the folder where the project files will be located.\n\n- **Default**: mini-app\n  The script will create a subfolder with the specified name in the current directory.\n\n### Preferred technologies\n\n#### TMA SDKs\n\n- **`tma.js`** [`@telegram-apps/sdk`](https://www.npmjs.com/package/@telegram-apps/sdk)  – A TypeScript library for seamless communication with Telegram Mini Apps functionality.\n- **Telegram SDK** [`@twa-dev/sdk`](https://www.npmjs.com/package/@twa-dev/sdk) – This package allows you to work with the SDK as an npm package.\n\n#### Frameworks\n\n- **React.js** [template](https://github.com/Telegram-Mini-Apps/reactjs-template)\n- **Next.js** [template](https://github.com/Telegram-Mini-Apps/nextjs-template)\n- **Solid.js** [template](https://github.com/Telegram-Mini-Apps/solidjs-js-template)\n- **Vue.js** [template](https://github.com/Telegram-Mini-Apps/vuejs-template)\n\n### Git remote repository URL\n\nEnter the git remote repository URL. This value will be used to connect the created project with your\nremote git repository. It should be either an HTTPS link or an SSH connection string.\n\n## Build configuration\n\nProjects created with `create-mini-app` are configured to use the [Vite](https://vite.dev/) bundler. The project includes a `vite.config.js` file,\nwhich you can customize to adjust the build settings according to your needs.\n"
  },
  {
    "path": "ecosystem/tma/overview.mdx",
    "content": "---\ntitle: \"TMA: Telegram Mini Apps overview\"\nsidebarTitle: \"Overview\"\n---\n\nTelegram Mini Apps (TMAs) are web applications that run within the Telegram messenger. They are built using web technologies — HTML, CSS, and JavaScript.\n\n<video\n  autoPlay\n  muted\n  loop\n  className=\"w-full rounded-xl\"\n  src=\"/resources/videos/TMA.mp4\"\n>\n  Your browser does not support the \\<video> tag.\n</video>\n\nMini Apps run within Telegram and are instantly accessible — without the need for installation or redirects.\n\n## TMA developer tools\n\n- [TMA create CLI](/ecosystem/tma/create-mini-app)\n- [Telegram UI Kit](/ecosystem/tma/telegram-ui/overview)\n- [Analytics](/ecosystem/tma/analytics/analytics)\n"
  },
  {
    "path": "ecosystem/tma/telegram-ui/getting-started.mdx",
    "content": "---\ntitle: \"Getting started\"\n---\n\nDive into our sleek design on [Figma](https://figma.com/community/file/1348989725141777736/) to get a glimpse of what awaits you.\n\n## Easy installation\n\nGetting started is a breeze with npm or yarn. Simply run:\n\n```sh icon=\"npm\"\nnpm install @telegram-apps/telegram-ui\n```\n\n\n## Import styles\n\nBefore diving into the development, ensure to import the necessary styles:\n\n```jsx\nimport '@telegram-apps/telegram-ui/dist/styles.css';\n```\n\n## Wrap your App\n\nWrap your application with `AppRoot` to leverage this platform's features:\n\n```jsx\nimport { AppRoot } from '@telegram-apps/telegram-ui';\n\nReactDOM.render(\n  <AppRoot>\n    <App />\n  </AppRoot>,\n  document.getElementById('root')\n);\n```\n\n## Usage example\n\n```jsx\n// Import the necessary styles globally\nimport '@telegram-apps/telegram-ui/dist/styles.css';\n\n// Import components from the library\nimport { AppRoot, Cell, List, Section } from '@telegram-apps/telegram-ui';\n\n// Example data for rendering list cells\nconst cellsTexts = ['Chat Settings', 'Data and Storage', 'Devices'];\n\nexport const App = () => (\n  <AppRoot>\n    {/* List component to display a collection of items */}\n    <List>\n      {/* Section component to group items within the list */}\n      <Section header=\"Header for the section\" footer=\"Footer for the section\">\n        {/* Mapping through the cells data to render Cell components */}\n        {cellsTexts.map((cellText, index) => (\n          <Cell key={index}>\n            {cellText}\n          </Cell>\n        ))}\n      </Section>\n    </List>\n  </AppRoot>\n);\n```\n\nWith these steps, you're all set to explore the potential of this library.\n\n### More UI components\nFind more demo components [here](https://tgui.xelene.me/?path=/docs/getting-started--documentation).\n"
  },
  {
    "path": "ecosystem/tma/telegram-ui/overview.mdx",
    "content": "---\ntitle: \"Overview\"\n---\n\nTelegram UI kit equips you with a variety of pre-designed components and tools to help you quickly develop high-quality Telegram applications. Whether you're aiming to create custom client apps, integrate Telegram functionality, or develop unique bots, this toolkit is your go-to resource.\n\n## Installation\n\n```sh icon=\"npm\"\nnpm i @telegram-apps/telegram-ui\n```\n\n## Usage\n\n```jsx\nimport '@telegram-apps/telegram-ui/dist/styles.css';\n\nimport { AppRoot, Placeholder } from '@telegram-apps/telegram-ui';\n\nconst App = () => (\n  <AppRoot>\n    <Placeholder\n      header=\"Title\"\n      description=\"Description\"\n    >\n      <img\n        alt=\"Telegram sticker\"\n        src=\"https://xelene.me/telegram.gif\"\n        style={{ display: 'block', width: '144px', height: '144px' }}\n      />\n    </Placeholder>\n  </AppRoot>\n);\n\nexport default App;\n```\n\n## Features\n\n- **Cross-Platform Design Consistency:** Use built-in support for iOS’s Human Interface Guidelines and Android’s Material Design to maintain a uniform look and functionality across both platforms.\n- **Pre-designed UI Components:** Access a variety of ready-to-use UI components inspired by Telegram’s interface, designed for easy integration and customization.\n- **Responsive Design:** Create apps that look and work great on any device, using flexible layouts and media queries to ensure optimal display and functionality.\n- **Telegram Color Scheme Support:** Apply Telegram’s native color schemes to your apps for consistent branding and a familiar user experience.\n\n## Environment support\n\n- Modern browsers\n- Server-side Rendering\n- [All known](https://telegram.org/apps) Telegram clients\n\n## Resources\n\n- **Example Mini App:** [GitHub](https://github.com/Telegram-Mini-Apps/TGUI-Example).\n- **Playground and Storybook:** Experiment with components and visualize changes in real-time at [Playground and Storybook](https://tgui.xelene.me/).\n- **Figma Resources:** Design and prototype with ease using our comprehensive Figma files available at [Figma](https://figma.com/community/file/1348989725141777736/).\n\n## Contribute\n\nContributions are welcome! To contribute, fork the repository, make your changes, and [submit a pull request](https://github.com/Telegram-Mini-Apps/TelegramUI/pulls). We look forward to your innovative [ideas](https://github.com/Telegram-Mini-Apps/TelegramUI/pulls) and improvements.\n\n## License\nThis Telegram UI Kit is available under the [MIT License](https://opensource.org/license/mit). Use it freely in both personal and commercial projects.\n\nThe library was skillfully crafted by [`@mainsmirnov`](https://github.com/mainsmirnov) and [`@heyqbnk`](https://github.com/heyqbnk), with the generous sponsorship of [TON Foundation](https://github.com/ton-society/grants-and-bounties/issues/364).\n"
  },
  {
    "path": "ecosystem/tma/telegram-ui/platform-and-palette.mdx",
    "content": "---\ntitle: \"AppRoot component\"\n---\n\nThe `AppRoot` component is pivotal in implementing a dynamic theming system within your application. It employs a sophisticated approach to CSS variables and React context to seamlessly adapt to various themes and platforms. This section delves into the inner workings of this system, explaining how themes are managed and applied internally.\n\n## CSS variables: the backbone of theming\n\nAt the heart of the `AppRoot` theming system lie CSS variables, which are utilized to create a flexible and adaptable styling framework. These variables are divided into two main categories: **Basic Variables** and **Custom Variables**. Both play a crucial role in tailoring the application's appearance to match both Telegram's theme and any additional stylistic preferences.\n\n### Basic variables\n\nBasic Variables are designed to inherit styles directly from Telegram or fall back on predefined styles within the library. This ensures that the application remains consistent with the user's current Telegram theme settings.\n\n- **Telegram Style Inheritance**: When available, Basic Variables dynamically adopt values from Telegram's theme, aligning the application's appearance with the platform's chosen theme.\n- **Library Defaults**: In scenarios where Telegram theme data isn't available or not supported in the current version, these variables revert to a set of default styles specified within the library, maintaining a coherent and user-friendly interface.\n\n### Custom variables\n\nCustom Variables offer an extension to the theming capabilities, allowing for more nuanced and specific styling adjustments that go beyond the scope of Telegram's native themes.\n\n- **Enhanced Styling Flexibility**: These variables enable the definition of unique stylistic elements like accent colors, providing opportunities for brand alignment and distinct visual design.\n- **Brand Identity Support**: By leveraging Custom Variables, developers can ensure that the application not only adheres to Telegram's theming but also reflects the brand's identity through consistent use of colors, typography, and other design elements.\n\n## Internal mechanism for theme and platform adaptation\n\n`AppRoot` intelligently leverages React context and CSS variables to dynamically adjust the application's styling based on the current theme (light, dark, or Telegram custom themes) and platform (iOS, Android, web). Here's an overview of how this process unfolds internally:\n\n- **Theme Detection and Application**: Upon initialization, `AppRoot` detects the current theme settings (from Telegram or manually set preferences) and updates the CSS variables accordingly. This process ensures that the theme is consistently applied across the application.\n- **Platform-Specific Styling**: In addition to theme management, `AppRoot` also detects the user's platform and applies platform-specific styles to optimize the user experience. This might include adjustments to typography, element sizing, and interaction feedback, aligning with platform conventions.\n- **Contextual Theme and Platform Information**: Through the use of React context, `AppRoot` provides nested components with access to current theme and platform information. This allows for conditional rendering or styling adjustments deep within the component tree, based on the overall application context.\n\n## Summary\n\nThe `AppRoot` theming system is a sophisticated framework designed to ensure visual consistency and adaptability across different themes and platforms. By combining CSS variables with React context, it offers a robust solution for managing theme and platform-specific styling, all while keeping the application aligned with Telegram's theming capabilities and the brand's visual identity.\n\nThrough this internal mechanism, `AppRoot` abstracts away the complexities of dynamic theming, allowing developers to focus on building feature-rich and visually appealing applications that provide a seamless user experience across all platforms and themes."
  },
  {
    "path": "ecosystem/tma/telegram-ui/reference/avatar.mdx",
    "content": "---\ntitle: \"Avatar\"\n---\n\nRenders an image with specific styles for an avatar presentation, including optional acronym display and badge support. Utilizes the Image component for core functionality, enhancing it with avatar-specific features like acronyms and badges.\n\n- [External avatar documentation](https://tgui.xelene.me/?path=/docs/blocks-avatar--documentation)\n"
  },
  {
    "path": "ecosystem/ton-connect/dapp.mdx",
    "content": "---\ntitle: \"How to integrate a decentralized application (dApp)\"\nsidebarTitle: \"Integrate a dApp\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nThis guide helps you integrate your dApp with TON or build one from scratch using [TON Connect](/ecosystem/ton-connect/overview) and auxiliary libraries.\n\nTON Connect is a standard wallet connection protocol in TON. It consists of supplementary SDKs and supervises two major use cases: dApps integrations with TON and custom wallet integrations.\n\nTo proceed with a dApp integration, select your framework or environment:\n\n<Columns cols={3}>\n  <Card\n    icon=\"react\"\n    title=\"React\"\n    href=\"#react\"\n  />\n\n  <Card\n    icon=\"square-n\"\n    title=\"Next.js\"\n    href=\"#next-js\"\n  />\n\n  <Card\n    icon=\"js\"\n    title=\"Vanilla JS\"\n    href=\"#vanilla-js\"\n  />\n</Columns>\n\n## Integration\n\n### React\n\n<Steps>\n  <Step\n    title=\"Install necessary libraries\"\n  >\n    Install the `@tonconnect/ui-react` package:\n\n    ```shell\n    npm i @tonconnect/ui-react\n    ```\n\n    That is enough for the most basic usage. However, to allow for more complex examples, install the following packages as well:\n\n    ```shell\n    npm i @ton-community/assets-sdk @ton/ton @ton/core\n    ```\n  </Step>\n\n  <Step\n    title=\"Create a TON Connect manifest\"\n  >\n    [TON Connect manifest](/ecosystem/ton-connect/manifest) is a small JSON file that lets wallets discover information about your dApp. It should be named `tonconnect-manifest.json`, placed at `https://<YOUR_APP_URL>/tonconnect-manifest.json`, and be accessible with a direct GET request.\n\n    <Aside>\n      Notice that [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS) should be disabled, and there should be no authorization or intermediate proxies like CloudFlare or similar services. The connection also won’t work when using a VPN.\n    </Aside>\n\n    Here's an example of such a file:\n\n    ```json title=\"tonconnect-manifest.json\"\n    {\n      \"url\": \"https://tonconnect-sdk-demo-dapp.vercel.app/\",\n      \"name\": \"Demo Dapp with React UI\",\n      \"iconUrl\": \"https://tonconnect-sdk-demo-dapp.vercel.app/apple-touch-icon.png\",\n      \"termsOfUseUrl\": \"https://tonconnect-sdk-demo-dapp.vercel.app/terms-of-use.txt\",\n      \"privacyPolicyUrl\": \"https://tonconnect-sdk-demo-dapp.vercel.app/privacy-policy.txt\"\n    }\n    ```\n\n    After creating the manifest file, import `TonConnectUIProvider` to the root of your dApp and pass the manifest URL:\n\n    ```tsx\n    import { TonConnectUIProvider } from '@tonconnect/ui-react';\n\n    export function App() {\n      return (\n        <TonConnectUIProvider\n          manifestUrl=\"https://<YOUR_APP_URL>/tonconnect-manifest.json\"\n        >\n          { /* Your app */ }\n        </TonConnectUIProvider>\n      );\n    }\n    ```\n\n    See more detailed information here: [TON Connect manifest](/ecosystem/ton-connect/manifest).\n  </Step>\n\n  <Step\n    title=\"Add a button in the UI\"\n  >\n    Users need a clear way of connecting their wallets to your app, so you must give a clear UI element to do so. Usually, that is a <kbd>Connect wallet</kbd> button.\n\n    Some in-wallet browsers automatically open a wallet connection modal when your dApp loads. Still, always provide a button alternative in case the user dismissed the modal window or wants to connect a wallet after doing their research.\n\n    Adding `TonConnectButton` is straightforward:\n\n    ```tsx\n    import { TonConnectButton } from '@tonconnect/ui-react';\n\n    export const Header = () => {\n      return (\n        <header>\n          <span>My App with React UI</span>\n          <TonConnectButton />\n        </header>\n      );\n    };\n    ```\n\n    The `TonConnectButton` is a universal UI component for initializing a connection. After the wallet is connected, it transforms into a wallet menu. Prefer to place the <kbd>Connect wallet</kbd> button in the top right corner of your app.\n\n    You can add the `className` and style props to the button:\n\n    ```jsx\n    <TonConnectButton className=\"my-button-class\" style={{ float: \"right\" }}/>\n    ```\n\n    <Aside\n      type=\"caution\"\n    >\n      You cannot pass a child element to the `TonConnectButton`.\n    </Aside>\n  </Step>\n\n  <Step\n    title=\"Utilize TON Connect in your dApp\"\n  >\n    <Card\n      title=\"Common usage recipes\"\n      href=\"#usage\"\n    />\n  </Step>\n</Steps>\n\n#### Manual connection initiation\n\nYou can always initiate the connection manually using the `useTonConnectUI` hook and [openModal](https://github.com/ton-connect/sdk/tree/main/packages/ui#open-connect-modal) method.\n\n```tsx\nimport { useTonConnectUI } from '@tonconnect/ui-react';\n\nexport const Header = () => {\n  const [tonConnectUI, setOptions] = useTonConnectUI();\n  return (\n    <header>\n      <span>My App with React UI</span>\n      <button onClick={() => tonConnectUI.openModal()}>\n        Connect Wallet\n      </button>\n    </header>\n  );\n};\n```\n\nTo open a modal window for a specific wallet, use the `openSingleWalletModal()` method. It takes the wallet's `app_name` and opens the corresponding wallet modal, returning a promise that resolves once the modal window opens.\n\nTo find the correct `app_name` of the target wallet, refer to the [wallets-list.json](https://github.com/ton-blockchain/wallets-list/blob/main/wallets-v2.json) file.\n\n```tsx\n<button onClick={() => tonConnectUI.openSingleWalletModal('tonwallet')}>\n  Connect Wallet\n</button>\n```\n\n#### UI customization\n\nTo customize the UI of the modal, use the `tonConnectUI` object provided by the `useTonConnectUI()` hook, and then assign designated values as an object to the `uiOptions` property.\n\n```tsx\n// Somewhere early in the component:\nconst [tonConnectUI] = useTonConnectUI();\n\n// ...\n\n// Somewhere later in the same component:\ntonConnectUI.uiOptions = {\n  language: 'ru', // sets the target language\n  uiPreferences: {\n    theme: THEME.DARK, // dark theme of the modal\n  }\n};\n```\n\nIn the object assigned, you should only pass options that you want to change — they will be merged with the current UI options. UI element will be re-rendered after such assignment.\n\n<Aside\n  type=\"caution\"\n>\n  Note that you have to pass an object and never set individual sub-properties under `uiOptions`. That is, **DO NOT** do this:\n\n  ```tsx\n  /* WRONG, WILL NOT WORK */\n  tonConnectUI.uiOptions.language = 'ru';\n  ```\n</Aside>\n\nSee all available `uiOptions` in the external reference: [`TonConnectUiOptions` Interface](https://ton-connect.github.io/sdk/interfaces/_tonconnect_ui.TonConnectUiOptions.html).\n\n#### Minimal React setup\n\nPutting all the above together, here's a most minimal React dApp integration example.\n\nFirst, start by creating a new project with React and Vite:\n\n```shell\nnpm create vite@latest demo-react-dapp -- --template react-ts\n```\n\nThen, go into the project and add the `@tonconnect/ui-react` dependency:\n\n```shell\ncd demo-react-dapp\nnpm i @tonconnect/ui-react # this will also install other missing dependencies\n```\n\nEdit your `App.tsx` to have the following imports present:\n\n```tsx title=\"src/App.tsx\"\nimport {\n  TonConnectUIProvider,\n  TonConnectButton,\n  useTonConnectUI,\n  useTonWallet,\n  CHAIN,\n} from '@tonconnect/ui-react';\n```\n\nFinally, in the same `App.tsx` file, replace your `App()` function with the following:\n\n```tsx title=\"src/App.tsx\" expandable\nfunction App() {\n  const [tonConnectUI] = useTonConnectUI();\n  const wallet = useTonWallet();\n\n  const sendToncoin = async (amount: string) => {\n    if (!wallet) return;\n\n    // Once the user has connected,\n    // you can prepare and send a message from the wallet:\n    try {\n      await tonConnectUI.sendTransaction({\n        validUntil: Math.floor(Date.now() / 1000) + 300,\n        network: CHAIN.TESTNET,\n        messages: [{ address: wallet.account.address, amount }],\n      });\n    }\n  };\n\n  return (\n    <TonConnectUIProvider\n      {/*\n        We re-use an existing manifest here. To specify your own while developing locally,\n        setup a tunnel and an https domain with the help of ngrok or similar tools.\n      */}\n      manifestUrl=\"https://tonconnect-sdk-demo-dapp.vercel.app/tonconnect-manifest.json\"\n    >\n      <TonConnectButton />\n      <button\n        {/*\n          Notice that it is important to specify Toncoin in nanoToncoin format,\n          where 1 Toncoin is equal to 10⁹ nanoToncoin:\n        */}\n        onClick={() => sendToncoin(String(100_000_000))}\n      >\n        Send 0.1 TON\n      </button>\n    </TonConnectUIProvider>\n  );\n}\n```\n\nNow, execute `npm run dev` to launch and preview your app in the browser at `http://localhost:5173`. All changes in code will be reflected live.\n\nConnect a wallet and try using the <kbd>Send 0.1 TON</kbd> button. Notice that the exact sum of Toncoin shown in your wallet **will be different**, because there are certain fees required for such a transfer by the blockchain itself.\n\nWhen building apps, make sure to **always take fees into consideration** and show them to the end-user.\n\n<Aside\n  type=\"caution\"\n>\n  This example sends **real TON** from the connected wallet. Try it with a testnet wallet first or send less Toncoin, e.g., 0.001 TON instead of 1 TON, to avoid surprises.\n</Aside>\n\n### Next.js\n\n`TonConnectUIProvider` relies on browser APIs and should be rendered only on the client side, i.e., on the frontend. As such, in a Next.js application, you should mark the component that wraps the provider with [`'use client'` directive](https://nextjs.org/docs/app/api-reference/directives/use-client).\n\nAlternatively, dynamically import the provider to disable server-side rendering.\n\nBoth approaches ensure that the provider is invoked only in the browser and works correctly there.\n\nExample for the `app` router:\n\n```tsx title=\"app/providers.tsx\"\n'use client';\n\nimport { TonConnectUIProvider } from '@tonconnect/ui-react';\n\nexport function Providers({ children }: { children: React.ReactNode }) {\n  return (\n    <TonConnectUIProvider\n      manifestUrl=\"https://<YOUR_APP_URL>/tonconnect-manifest.json\"\n    >\n      {children}\n    </TonConnectUIProvider>\n  );\n}\n```\n\nFor the `pages` router, you can dynamically import the provider:\n\n```tsx\nimport dynamic from 'next/dynamic';\n\nconst TonConnectUIProvider = dynamic(\n  () => import('@tonconnect/ui-react').then(m => m.TonConnectUIProvider),\n  { ssr: false }\n);\n\nfunction MyApp({ Component, pageProps }) {\n  return (\n    <TonConnectUIProvider\n      manifestUrl=\"https://<YOUR_APP_URL>/tonconnect-manifest.json\"\n    >\n      <Component {...pageProps} />\n    </TonConnectUIProvider>\n  );\n}\n```\n\n### Vanilla JS\n\nFor quick testing, use the following single-file HTML example.\n\n<Aside\n  type=\"caution\"\n>\n  This example sends **real Toncoin** from the connected wallet. Try it with a testnet wallet first or send less Toncoin, e.g., 0.001 TON instead of 1, to avoid surprises.\n</Aside>\n\n```html title=\"index.html\" expandable\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\" />\n  <title>TON Connect sandbox</title>\n  <script src=\"https://unpkg.com/@tonconnect/ui@latest/dist/tonconnect-ui.min.js\"></script>\n</head>\n<body>\n  <div id=\"ton-connect\"></div>\n  <button id=\"send\" disabled>Send 0.1 TON</button>\n  <script>\n    const ui = new TON_CONNECT_UI.TonConnectUI({\n      // Let's re-use the manifest from the demo app\n      manifestUrl: 'https://tonconnect-sdk-demo-dapp.vercel.app/tonconnect-manifest.json',\n      buttonRootId: 'ton-connect', // anchor id with the element to hook the \"Connect wallet\" button onto\n    });\n    ui.onStatusChange(w => document.getElementById('send').disabled = !w);\n    document.getElementById('send').onclick = async () => {\n      // This will send 0.1 Toncoin from the connected wallet, beware!\n      try {\n        await ui.sendTransaction({\n          validUntil: Math.floor(Date.now()/1000) + 300,\n          messages: [{ address: ui.account.address, amount: String(100_000_000) }],\n        });\n      }\n    };\n  </script>\n</body>\n</html>\n```\n\n## See also\n\n- [TON Connect overview](/ecosystem/ton-connect/overview)\n- [TON Connect manifests](/ecosystem/ton-connect/manifest)\n- [Integrate a wallet](/ecosystem/ton-connect/wallet)\n- [WalletKit overview](/ecosystem/walletkit/overview)\n"
  },
  {
    "path": "ecosystem/ton-connect/manifest.mdx",
    "content": "---\ntitle: \"TON Connect manifests\"\nsidebarTitle: \"Manifests\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nTON Connect manifests are specially formatted JSON files that define meta information to either pass it from your dApp to the wallet ([app manifest](#app-manifest)) or to set up subsequent wallet interactions with the TON Connect protocol ([wallet manifest](#wallet-manifest)).\n\n## App manifest\n\nApp manifest is a small JSON file that lets wallets discover information about your dApp. It should be named `tonconnect-manifest.json` and correspond to the following definition.\n\n| Field              | Requirement | Description                                                                                                                                                                                                            |\n| ------------------ | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `url`              | required    | Defines the app URL. It will be used to open the dApp after clicking its icon in the wallet. It is recommended to pass the URL without closing the slash, e.g., `https://mydapp.com` instead of `https://mydapp.com/`. |\n| `name`             | required    | Defines the app name. Typically, a simple word. Shouldn't be used as an identifier.                                                                                                                                    |\n| `iconUrl`          | required    | Defines the URL to the app icon. It must be in `PNG` or `ICO` format. `SVG` icons are not supported. An 180x180 px PNG icon is optimal.                                                                                |\n| `termsOfUseUrl`    | optional    | Only needed for apps to be featured in the wallet's recommendation lists.                                                                                                                                              |\n| `privacyPolicyUrl` | optional    | Only needed for apps to be featured in the wallet's recommendation lists.                                                                                                                                              |\n\nHere is a generic example of an app manifest:\n\n```jsonc\n{\n  \"url\": \"<app-url>\",                        // required\n  \"name\": \"<app-name>\",                      // required\n  \"iconUrl\": \"<app-icon-url>\",               // required\n  \"termsOfUseUrl\": \"<terms-of-use-url>\",     // optional\n  \"privacyPolicyUrl\": \"<privacy-policy-url>\" // optional\n}\n```\n\nFor a web dApp, place its manifest at `https://[myapp.com]/tonconnect-manifest.json` so that wallets can fetch it with a simple GET request.\n\n<Aside>\n  Application manifest must be publicly available with CORS disabled, without any authorization required, and without a Cloudflare or similar service proxying them. If hosting that way is troublesome on your own, consider using a trusted CDN.\n</Aside>\n\n## Wallet manifest\n\nWallet manifest is a JSON configuration that defines how your wallet interacts with the TON Connect.\n\nHere is an example of a custodian manifest:\n\n```json\n{\n  \"app_name\": \"[custodian]\",\n  \"name\": \"[Custodian]\",\n  \"image\": \"https://cdn.[custodian].com/ton-connect-icon.png\",\n  \"about_url\": \"https://[custodian].com\",\n  \"universal_url\": \"https://wallet.[custodian].com/ton-connect\",\n  \"bridge\": [\n    {\n      \"type\": \"sse\",\n      \"url\": \"https://bridge.[custodian].com/bridge\"\n    }\n  ],\n  \"platforms\": [\"ios\", \"android\", \"web\", \"windows\", \"macos\", \"linux\"],\n  \"features\": [\n    {\n      \"name\": \"SendTransaction\",\n      \"maxMessages\": 4,\n      \"extraCurrencySupported\": false\n    }\n  ]\n}\n```\n\n<Aside>\n  There, the bridge refers to the way connectivity between the wallet and dApp is achieved. It can either be a JavaScript one, extending the `window` object, or an HTTP one, requiring a separate service to be running.\n\n  For more details, see the respective reference section: [WalletKit reference](/ecosystem/walletkit/overview).\n</Aside>\n\n### Primary properties\n\n- `app_name`: A unique identifier for the wallet. This string should be lowercase, without spaces or special characters. It will be used as an identifier in connection events and must match the `ConnectEventSuccess.device.appName` value.\n\n- `name`: The display name of the wallet that will be shown to users in dApp interfaces. For your custodian, simply use \"\\[Custodian]\" or \"\\[Custodian] Wallet\" as appropriate.\n\n- `image`: A URL pointing to the wallet's icon. This should be a high-quality image with the following specifications:\n\n  - Resolution: 288×288 pixels\n  - Background: Non-transparent\n  - Corners: Non-rounded\n  - Format: PNG\n\n  Examples:\n\n  - `https://wallet.tg/images/logo-288.png`\n  - `https://tonkeeper.com/assets/tonconnect-icon.png`\n\n### Connection properties\n\n- `about_url`: A URL to the wallet information or landing page. This helps new TON users learn about your wallet.\n\n- `universal_url`: The base part of the wallet's universal URL that will handle TON Connect parameters. This is a critical component for enabling connections via universal links. For your custodian, this could be something like `https://wallet.[custodian].com/ton-connect`.\n\n- `bridge`: An array specifying connectivity options between dApps and the wallet.\n  - HTTP bridge setups should include:\n\n    ```json\n    \"bridge\": [\n      {\n        \"type\": \"sse\",\n        \"url\": \"https://bridge.[custodian].com/bridge\"\n      }\n    ]\n    ```\n\n    There, `url` points to the publicly exposed bridge.\n\n  - JavaScript bridge setups should include:\n\n    ```json\n    \"bridge\": [\n      {\n        \"type\": \"js\",\n        \"key\": \"[custodian]\"\n      }\n    ]\n    ```\n\n    In the above, `key` points to the property name within the `window` object on the same web page.\n\n### Platform and feature support\n\n- `platforms`: An array listing all platforms where the wallet is available. This can include any of the following values: `\"ios\"`, `\"android\"`, `\"chrome\"`, `\"firefox\"`, `\"safari\"`, `\"windows\"`, `\"macos\"`, `\"linux\"`, `\"web\"`. Include only the platforms that you actually support.\n\n- `features`: This section defines the capabilities of the wallet:\n\n  ```json\n  \"features\": [\n    {\n      \"name\": \"SendTransaction\",\n      \"maxMessages\": 4,\n      \"extraCurrencySupported\": false\n    }\n  ]\n  ```\n\n  - `name`: Currently, only \"SendTransaction\" is defined in the protocol.\n  - `maxMessages`: The maximum number of messages the wallet can sign in a single transaction (4 is standard for many wallets).\n  - `extraCurrencySupported`: Whether the wallet supports additional currencies beyond TON. Set to `false` initially; you can update this later if you add support.\n"
  },
  {
    "path": "ecosystem/ton-connect/message-lookup.mdx",
    "content": "---\ntitle: \"Message lookup\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\n\n<Aside\n  type=\"danger\"\n>\n  You should never use external message tracking for payment processing purposes. Check out [payment processing](/payments/overview) for more details.\n</Aside>\n\n## Introduction\n\nThe process of seeking a transaction associated with an `external-in` message is called **message lookup**. It should only be used for better UX to display, for example, the progress of the operation and its result.\n\n### Message normalization\n\nNormalization is a standardization process that converts different external-in message representations into a consistent format. This needs to be done because the structure of external-in messages allows the same message to be constructed in different forms, which results in different possible hashes for the same external message.\n\nTo address this, the ecosystem defines a standard that ensures consistent hash calculation. The normalization rules are specified in detail in the [TEP-467 proposal](https://github.com/ton-blockchain/TEPs/pull/467). Message lookup by its normalized hash is already implemented in most TON [RPC providers](/ecosystem/api/overview).\n\n**How normalization works:**\n\nThe normalized hash is computed by applying the following standardization rules to an external-in message:\n\n1. **Source Address (`src`)**: set to `addr_none$00`\n1. **Import Fee (`import_fee`)**: set to `0`\n1. **InitState (`init`)**: set to an empty value\n1. **Body**: always stored as a reference\n\n## Transaction lookup using external message from TON Connect\n\n```ts\n/**\n * Generates a normalized hash of an \"external-in\" message for comparison.\n *\n * This function ensures consistent hashing of external-in messages by following [TEP-467](https://github.com/ton-blockchain/TEPs/blob/8b3beda2d8611c90ec02a18bec946f5e33a80091/text/0467-normalized-message-hash.md):\n *\n * @param {Message} message - The message to be normalized and hashed. Must be of type `\"external-in\"`.\n * @returns {Buffer} The hash of the normalized message.\n * @throws {Error} if the message type is not `\"external-in\"`.\n */\nexport function getNormalizedExtMessageHash(message: Message) {\n    if (message.info.type !== 'external-in') {\n        throw new Error(`Message must be \"external-in\", got ${message.info.type}`);\n    }\n\n    const info = {\n         ...message.info,\n         src: undefined,\n         importFee: 0n\n    };\n\n    const normalizedMessage = {\n        ...message,\n        init: null,\n        info: info,\n    };\n\n    return beginCell()\n        .store(storeMessage(normalizedMessage, { forceRef: true }))\n        .endCell()\n        .hash();\n}\n```\n\n## Retrying API calls\n\nSometimes API requests may fail due to rate limits or network issues. Use the `retry` function presented below to deal with api failures:\n\n```ts\nexport async function retry<T>(fn: () => Promise<T>, options: { retries: number; delay: number }): Promise<T> {\n    let lastError: Error | undefined;\n    for (let i = 0; i < options.retries; i++) {\n        try {\n            return await fn();\n        } catch (e) {\n            if (e instanceof Error) {\n                lastError = e;\n            }\n            await new Promise((resolve) => setTimeout(resolve, options.delay));\n        }\n    }\n    throw lastError;\n}\n```\n\n## Find the transaction by incoming message\n\nThe `getTransactionByInMessage` function searches the account’s transaction history for a match by normalized external message hash:\n\n```ts\n/**\n * Tries to find transaction by ExternalInMessage\n */\nasync function getTransactionByInMessage(\n    inMessageBoc: string,\n    client: TonClient,\n): Promise<Transaction | undefined> {\n    // Step 1. Convert Base64 BoC to Message if input is a string\n    const inMessage = loadMessage(Cell.fromBase64(inMessageBoc).beginParse());\n\n    // Step 2. Ensure the message is an external-in message\n    if (inMessage.info.type !== 'external-in') {\n        throw new Error(`Message must be \"external-in\", got ${inMessage.info.type}`);\n    }\n    const account = inMessage.info.dest;\n\n    // Step 3. Compute the normalized hash of the input message\n    const targetInMessageHash = getNormalizedExtMessageHash(inMessage);\n\n    let lt: string | undefined = undefined;\n    let hash: string | undefined = undefined;\n\n    // Step 4. Paginate through the transaction history of the account\n    while (true) {\n        const transactions = await retry(\n            () =>\n                client.getTransactions(account, {\n                    hash,\n                    lt,\n                    limit: 10,\n                    archival: true,\n                }),\n            { delay: 1000, retries: 3 },\n        );\n\n        if (transactions.length === 0) {\n            // No more transactions found - message may not be processed yet\n            return undefined;\n        }\n\n        // Step 5. Search for a transaction whose input message matches the normalized hash\n        for (const transaction of transactions) {\n            if (transaction.inMessage?.info.type !== 'external-in') {\n                continue;\n            }\n\n            const inMessageHash = getNormalizedExtMessageHash(transaction.inMessage);\n            if (inMessageHash.equals(targetInMessageHash)) {\n                return transaction;\n            }\n        }\n\n        const last = transactions.at(-1)!;\n        lt = last.lt.toString();\n        hash = last.hash().toString('base64');\n    }\n}\n```\n\nIf found, it returns a `Transaction` object. Otherwise, it returns `undefined`.\n\n### Example\n\n```ts\nimport { TonClient } from '@ton/ton';\n\nconst client = new TonClient({ endpoint: 'https://toncenter.com/api/v2/jsonRPC' });\n\nconst tx = await getTransactionByInMessage(\n  'te6ccgEBAQEA...your-base64-message...',\n  client\n);\n\nif (tx) {\n  console.log('Found transaction:', tx);\n} else {\n  console.log('Transaction not found');\n}\n```\n\n## Waiting for transaction confirmation\n\nIf you’ve just sent a message, it may take a few seconds before it appears on-chain.\nThe function `waitForTransaction` to poll the blockchain and wait for the corresponding transaction should be used in this case:\n\n```ts\n/**\n * Waits for a transaction to appear on-chain by incoming external message.\n *\n * Useful when the message has just been sent.\n */\nasync function waitForTransaction(\n    inMessageBoc: string,\n    client: TonClient,\n    retries: number = 10,\n    timeout: number = 1000,\n): Promise<Transaction | undefined> {\n    const inMessage = loadMessage(Cell.fromBase64(inMessageBoc).beginParse());\n\n    if (inMessage.info.type !== 'external-in') {\n        throw new Error(`Message must be \"external-in\", got ${inMessage.info.type}`);\n    }\n    const account = inMessage.info.dest;\n\n    const targetInMessageHash = getNormalizedExtMessageHash(inMessage);\n\n    let attempt = 0;\n    while (attempt < retries) {\n        console.log(`Waiting for transaction to appear in network. Attempt: ${attempt}`);\n\n        const transactions = await retry(\n            () =>\n                client.getTransactions(account, {\n                    limit: 10,\n                    archival: true,\n                }),\n            { delay: 1000, retries: 3 },\n        );\n\n        for (const transaction of transactions) {\n            if (transaction.inMessage?.info.type !== 'external-in') {\n                continue;\n            }\n\n            const inMessageHash = getNormalizedExtMessageHash(transaction.inMessage);\n            if (inMessageHash.equals(targetInMessageHash)) {\n                return transaction;\n            }\n        }\n\n        await new Promise((resolve) => setTimeout(resolve, timeout));\n    }\n\n    // Transaction was not found - message may not be processed\n    return undefined;\n}\n```\n\n### Example\n\n```typescript\nimport { TonClient } from '@ton/ton';\n\nconst client = new TonClient({ endpoint: 'https://toncenter.com/api/v2/jsonRPC' });\n\nconst [tonConnectUI, setOptions] = useTonConnectUI();\n\n// Obtain ExternalInMessage BoC\nconst { boc } = await tonConnectUI.sendTransaction({\n    messages: [\n        {\n            address: \"UQBSzBN6cnxDwDjn_IQXqgU8OJXUMcol9pxyL-yLkpKzYpKR\",\n            amount: \"20000000\"\n        }\n    ]\n});\n\nconst tx = await waitForTransaction(\n    boc,\n    client,\n    10, // retries\n    1000, // timeout before each retry\n);\n\nif (tx) {\n    console.log('Found transaction:', tx);\n} else {\n    console.log('Transaction not found');\n}\n```\n\n## See also\n\n- [TEP-467: Normalized Message Hash](https://github.com/ton-blockchain/TEPs/blob/8b3beda2d8611c90ec02a18bec946f5e33a80091/text/0467-normalized-message-hash.md)\n- [Messages and transactions](/foundations/messages/ordinary-tx)\n- [TON Connect: Sending messages](/ecosystem/ton-connect/overview)\n"
  },
  {
    "path": "ecosystem/ton-connect/overview.mdx",
    "content": "---\ntitle: \"TON Connect overview\"\nsidebarTitle: \"Overview\"\n---\n\nimport { Image } from '/snippets/image.jsx';\n\nTo integrate with TON, the standard wallet connection protocol is used — TON Connect. It is similar to WalletConnect on Ethereum, but made specifically for TON and covers basic integration aspects. For deeper integrations, it is common to utilize various supplementary SDKs and APIs.\n\n<Image\n  src=\"/resources/images/ton-connect/basic-schema.svg\"\n  darkSrc=\"/resources/images/ton-connect/basic-schema-dark.svg\"\n  alt=\"Basic communication schema of TON Connect\"\n/>\n\n## About TON Connect\n\n<video\n  autoPlay\n  muted\n  loop\n  className=\"w-full rounded-xl\"\n  src=\"/resources/videos/TonConnect.mp4\"\n>\n  Your browser does not support the \\<video> tag.\n</video>\n\nTON Connect enables secure communication between wallets and decentralized applications, allowing users to authorize transactions while maintaining control of their private keys.\n\nCurrently, TON Connect supports over 30 wallets and connects to hundreds of major applications across the TON ecosystem. As the mandatory connection protocol for all Telegram Mini Apps, it serves as the gateway to TON's entire ecosystem of applications and services.\n\nThink of it as the essential infrastructure that your institutional clients will need to access any TON-based services — from DeFi protocols to gaming applications to payment systems.\n\nFor technical architecture details: [TON Connect protocol specification on GitHub](https://github.com/ton-blockchain/ton-connect).\n\n## Are you building a web3 app?\n\nExplore the demo apps made with React.\n\n<Columns cols={2}>\n  <Card\n    title=\"Demo TON dApp with React\"\n    icon=\"link\"\n    horizontal=\"true\"\n    href=\"https://tonconnect-sdk-demo-dapp.vercel.app/\"\n    arrow=\"true\"\n  />\n\n  <Card\n    title=\"Demo TON dApp GitHub repository\"\n    icon=\"github\"\n    horizontal=\"true\"\n    arrow=\"true\"\n    href=\"https://github.com/ton-connect/demo-dapp-with-react-ui\"\n  />\n</Columns>\n\nProceed with integration and usage recipes.\n\n<Columns cols={2}>\n  <Card\n    icon=\"flask\"\n    horizontal=\"true\"\n    title=\"How to integrate a dApp with TON\"\n    href=\"/ecosystem/ton-connect/dapp\"\n  />\n\n  <Card\n    icon=\"wrench\"\n    horizontal=\"true\"\n    title=\"Common usage examples\"\n    href=\"/ecosystem/ton-connect/dapp#usage\"\n  />\n</Columns>\n\nSkim the related reference pages.\n\n<Columns cols={2}>\n  <Card\n    title=\"App manifest\"\n    icon=\"book\"\n    horizontal=\"true\"\n    href=\"/ecosystem/ton-connect/manifest#app-manifest\"\n  />\n\n  <Card\n    title=\"@tonconnect/sdk\"\n    horizontal=\"true\"\n    arrow=\"true\"\n    href=\"https://ton-connect.github.io/sdk/modules/_tonconnect_sdk.html\"\n  />\n\n  <Card\n    title=\"@tonconnect/ui\"\n    horizontal=\"true\"\n    arrow=\"true\"\n    href=\"https://ton-connect.github.io/sdk/modules/_tonconnect_ui.html\"\n  />\n\n  <Card\n    title=\"@tonconnect/ui-react\"\n    horizontal=\"true\"\n    arrow=\"true\"\n    href=\"https://ton-connect.github.io/sdk/modules/_tonconnect_ui-react.html\"\n  />\n</Columns>\n\n## Are you building a web3 wallet?\n\nFollow the step-by-step guide.\n\n<Card\n  icon=\"flask\"\n  horizontal=\"true\"\n  title=\"How to make a wallet on TON\"\n  href=\"/ecosystem/ton-connect/wallet\"\n/>\n\nOr skim the related reference pages.\n\n<Columns cols={2}>\n  <Card\n    title=\"Wallet manifest\"\n    icon=\"book\"\n    horizontal=\"true\"\n    href=\"/ecosystem/ton-connect/manifest#wallet-manifest\"\n  />\n\n  <Card\n    title=\"WalletKit reference\"\n    icon=\"book\"\n    horizontal=\"true\"\n    href=\"/ecosystem/walletkit/overview\"\n  />\n\n  <Card\n    title=\"@tonconnect/protocol\"\n    arrow=\"true\"\n    horizontal=\"true\"\n    href=\"https://ton-connect.github.io/sdk/modules/_tonconnect_protocol.html\"\n  />\n</Columns>\n\nFor more, see the TON Connect articles from Google Docs.\n\n<Columns cols={3}>\n  <Card\n    title=\"QA Guide\"\n    icon=\"book\"\n    href=\"/ecosystem/walletkit/qa-guide\"\n  />\n\n  <Card\n    title=\"Native or web wallets\"\n    icon=\"book\"\n    href=\"/ecosystem/walletkit/native-web\"\n  />\n\n  <Card\n    title=\"In-app or browser extension wallets\"\n    icon=\"book\"\n    href=\"/ecosystem/walletkit/browser-extension\"\n  />\n</Columns>\n\n{/* ## Complete integration recipes\n\n  Comprehensive guides that walk you through complete integration scenarios, covering everything from initial setup to production deployment. Each recipe includes code examples, best practices, and troubleshooting tips.\n\n  <Columns cols={1}>\n  <Card\n    icon=\"flask\"\n    horizontal=\"true\"\n    title=\"How to integrate TON into a Centralized Exchange (CEX)\"\n    href=\"/guides/cex\"\n  />\n  </Columns> */}\n\n{/* ## Curated guides and tutorials from the community\n\n  Tutorials and guides created by the TON community to help developers integrate TON into their applications. They provide practical, real-world examples and alternative approaches to common integration challenges.\n\n  <Columns cols={1}>\n  <Card\n    icon=\"scroll\"\n    horizontal=\"true\"\n    title=\"Index of curated community tutorials\"\n    href=\"/guides/more\"\n  />\n  </Columns> */}\n\n## Join the community\n\nIf you have questions about integrating TON into your project, need help troubleshooting issues, or want to discuss best practices with other developers, join our community channels.\n\n<Columns cols={2}>\n  <Card\n    icon=\"telegram\"\n    horizontal=\"true\"\n    title=\"Telegram folder with many developer chats\"\n    arrow=\"true\"\n    href=\"https://t.me/addlist/1r5Vcb8eljk5Yzcy\"\n  />\n\n  <Card\n    icon=\"user-group\"\n    horizontal=\"true\"\n    title=\"List of skilled professionals and agencies\"\n    arrow=\"true\"\n    href=\"https://ton.org/en/talents\"\n  />\n</Columns>\n\n## See also\n\n- [Technical specification of the TON Connect protocol (GitHub)](https://github.com/ton-blockchain/ton-connect)\n- [Official list of wallets that support TON Connect (GitHub)](https://github.com/ton-blockchain/wallets-list)\n- [HTTP bridge for TON Connect](https://github.com/ton-connect/bridge)\n"
  },
  {
    "path": "ecosystem/ton-connect/wallet.mdx",
    "content": "---\ntitle: \"How to integrate a wallet with TON\"\nsidebarTitle: \"Integrate a wallet\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nThis guide helps you integrate your custodial or non-custodial wallet with TON or partially build a basic, fresh one from scratch with the help of [TON Connect](/ecosystem/ton-connect/overview) and [WalletKit](/ecosystem/walletkit/overview).\n\nTON Connect is a standard wallet connection protocol used on TON. It consists of many supplementary SDKs and supervises two major use-cases: dApp integrations with TON and custom wallet integrations. The latter are done via the WalletKit.\n\nTo proceed with a WalletKit integration, select your framework or environment:\n\n<Columns cols={3}>\n  <Card\n    title=\"Web\"\n    href=\"/ecosystem/walletkit/web/init\"\n  />\n\n  <Card\n    title=\"Android\"\n    href=\"/ecosystem/walletkit/android/init\"\n  />\n\n  <Card\n    title=\"iOS\"\n    href=\"/ecosystem/walletkit/ios/init\"\n  />\n</Columns>\n\nAdditionally, explore the complete demo wallets:\n\n- [Demo wallet with WalletKit integration](https://walletkit-demo-wallet.vercel.app)\n- [Demo wallet, GitHub repository](https://github.com/ton-connect/kit/tree/main/apps/demo-wallet)\n\n## See also\n\nRead more about the TON Connect and WalletKit themselves:\n\n- [TON Connect overview](/ecosystem/ton-connect/overview)\n- [WalletKit overview](/ecosystem/walletkit/overview)\n\nSkim the reference pages with more in-depth information:\n\n<Columns cols={2}>\n  <Card\n    title=\"TON Connect manifests\"\n    href=\"/ecosystem/ton-connect/manifest\"\n  />\n\n  <Card\n    title=\"WalletKit integration QA guide\"\n    href=\"/ecosystem/walletkit/qa-guide\"\n  />\n\n  <Card\n    title=\"Native and web wallets\"\n    href=\"/ecosystem/walletkit/native-web\"\n  />\n\n  <Card\n    title=\"Browser extensions and in-wallet browsers\"\n    href=\"/ecosystem/walletkit/browser-extension\"\n  />\n</Columns>\n"
  },
  {
    "path": "ecosystem/ton-pay/api-reference.mdx",
    "content": "---\ntitle: \"API reference\"\nsidebarTitle: \"API reference\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\n\nTypeScript exports for the TON Pay SDK packages `@ton-pay/api` and `@ton-pay/ui-react`. To install the packages, use:\n\n```bash\nnpm install @ton-pay/api @ton-pay/ui-react\n```\n\n## Imports\n\n```ts\n// API helpers\nimport {\n  createTonPayTransfer,\n  getTonPayTransferByBodyHash,\n  getTonPayTransferByReference,\n  type CompletedTonPayTransferInfo,\n  type CreateTonPayTransferParams,\n  type CreateTonPayTransferResponse,\n} from \"@ton-pay/api\";\n\n// React UI\nimport { TonPayButton, useTonPay } from \"@ton-pay/ui-react\";\n```\n\n## Functions\n\n### `createTonPayTransfer(params, options?)`\n\nBuild a canonical message and return tracking identifiers.\n\n- `params`: `CreateTonPayTransferParams`.\n- `options`: `APIOptions`.\n- `options.chain`: `mainnet | testnet`.\n\n### `getTonPayTransferByBodyHash(bodyHash, options?)`\n\nFetch a transfer by Base64 hash of the signed message body content (payload).\n\n- `bodyHash`: Base64 hash of the signed message body content (payload). Use `bodyBase64Hash` from `createTonPayTransfer`.\n- `options`: `APIOptions`.\n- Return `CompletedTonPayTransferInfo`.\n\n### `getTonPayTransferByReference(reference, options?)`\n\nFetch a transfer by reference.\n\n- `reference`: use the `reference` returned by `createTonPayTransfer`.\n- `options`: `APIOptions`.\n- Return `CompletedTonPayTransferInfo`.\n\n### `useTonPay(options?)`\n\nA React hook. Connect a wallet through [TON Connect](/ecosystem/ton-connect/overview) and send a transaction.\n\n- `pay(getMessage)`: Receive `senderAddr`, request `{ message }` from the factory, and send through TON Connect. Resolve `{ txResult, ...factoryReturn }`.\n\n### `TonPayButton`\n\nPrebuilt button. Handle wallet connect or disconnect flow and call `handlePay`.\n\n## Types: `@ton-pay/api`\n\n### `CreateTonPayTransferParams`\n\nRequest payload for `createTonPayTransfer`.\n\n```ts\ntype CreateTonPayTransferParams = {\n  amount: number;\n  asset: string;\n  recipientAddr?: string;\n  senderAddr: string;\n  queryId?: number;\n  commentToSender?: string;\n  commentToRecipient?: string;\n};\n```\n\nSpecify `amount` in asset units. Follow asset decimals. For example: TON 9 decimals, USDT 6 decimals.\n\n### `CreateTonPayTransferResponse`\n\n```ts\ntype CreateTonPayTransferResponse = {\n  message: { address: string; amount: string; payload: string };\n  bodyBase64Hash: string;\n  reference: string;\n};\n```\n\n### `CompletedTonPayTransferInfo`\n\n```ts\ntype CompletedTonPayTransferInfo = {\n  amount: string;\n  rawAmount: string;\n  senderAddr: string;\n  recipientAddr: string;\n  asset: string;\n  assetTicker?: string;\n  status: string;\n  reference: string;\n  bodyBase64Hash: string;\n  txHash: string;\n  traceId: string;\n  commentToSender?: string;\n  commentToRecipient?: string;\n  date: string;\n  errorCode?: number;\n  errorMessage?: string;\n};\n```\n\n- `status`: `pending`, `success`, or `error`;\n- `errorCode`: TON Pay error codes in [Check status and retrieve info](/ecosystem/ton-pay/payment-integration/status-info).\n\n### `APIOptions`\n\n```ts\ntype APIOptions = {\n  chain: \"mainnet\" | \"testnet\";\n};\n```\n\n<Aside type=\"note\">\n  Default: `mainnet`.\n</Aside>\n\n## Constants: `@ton-pay/api`\n\n```ts\nimport { TON, USDT } from \"@ton-pay/api\";\n// TON: the string constant \"TON\" (use for Toncoin transfers)\n// USDT: mainnet USDT jetton master address\n```\n\n<Aside\n  type=\"danger\"\n  title=\"Mainnet address risk\"\n>\n  Token constants such as `USDT` always reference mainnet jetton master addresses and are not affected by the `chain` option. Using them on testnet may send transactions to mainnet contracts.\n\n  For testnet, explicitly pass the correct testnet jetton master address instead of using token constants.\n</Aside>\n\n## Errors\n\nAll API helpers throw `Error` with an HTTP `cause` if the network call fails. For example, `createTonPayTransfer` may throw \"Failed to create TON Pay transfer\".\n\n## Peer dependencies\n\n- [`@tonconnect/ui-react`](https://www.npmjs.com/package/@tonconnect/ui-react) – React UI kit for TON Connect SDK.\n- [React 18](https://react.dev/) or later and `react-dom` 18 or later.\n"
  },
  {
    "path": "ecosystem/ton-pay/on-ramp.mdx",
    "content": "---\ntitle: \"On-ramp in TON Pay SDK\"\nsidebarTitle: \"On-ramp\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nThe TON Pay SDK includes a built-in fiat-to-crypto on-ramp powered by [MoonPay](https://www.moonpay.com/). It allows users to top up their wallets with a bank card directly from the payment modal.\n\n## How it works\n\nWhen a user opens the payment modal and the connected wallet balance is insufficient, the SDK offers a \"Top up by card\" option. The flow proceeds as follows:\n\n1. Balance check. The SDK verifies whether the connected wallet has funds to complete the payment.\n1. Geographic and limit check. The SDK verifies that card purchases are supported in the user's region and retrieves the provider's minimum and maximum purchase limits.\n1. Amount calculation. The SDK computes the required top-up amount, clamped to the provider's minimum.\n1. Widget rendering. The MoonPay purchase widget loads in an iframe. The purchase transfers funds directly to the user's wallet.\n1. Balance polling. After the provider reports transaction completion, the SDK polls the wallet balance every 5 seconds.\n1. Auto-pay. Once the wallet balance becomes sufficient, the SDK displays a modal to complete the merchant payment.\n\nFunds are always credited to the user’s wallet before any transfer to the merchant occurs.\n\n## How to enable\n\nThe [`TonPayButton` React component](/ecosystem/ton-pay/ui-integration/button-react) enables the on-ramp by default. To turn it off, set `isOnRampAvailable` to `false`:\n\n```tsx\n<TonPayButton\n  isOnRampAvailable={false}\n  // ... other props\n/>\n```\n\nWhen `isOnRampAvailable` is `false`, the \"Top up by card\" option is hidden. Payments can only be completed using the current wallet balance.\n\n## Supported assets\n\nThe SDK supports the following assets for on-ramp top-ups:\n\n| Token          | Master address                                     |\n| :------------- | :------------------------------------------------- |\n| TON            | Native                                             |\n| USDT           | `EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs` |\n| DOGS           | `EQCvxJy4eG8hyHBFsZ7eePxrRsUQSFE_jpptRAYBmcG_DOGS` |\n| Notcoin        | `EQAvlWFDxGF2lXm67y4yzC17wYKD9A0guwPkMs1gOsM__NOT` |\n| Hamster Kombat | `EQAJ8uWd7EBqsmpSWaRdf_I-8R8-XHwh3gsNKhy-UrdrPcUo` |\n| Catizen        | `EQD-cvR0Nz6XAyRBvbhz-abTrRC6sI5tvHvvpeQraV9UAAD7` |\n\n## Geographic restrictions\n\nBefore displaying the card top-up option, the SDK checks the user's geographic eligibility with the MoonPay provider. If card purchases are not supported in the user's country, the option is not displayed.\n\nThe SDK performs this check using the user's IP address. If the integration proxies requests or omits the original client IP address, provide the user's IP explicitly using the `userIp` prop.\n\n## Purchase limits\n\nThe SDK retrieves minimum and maximum purchase limits from MoonPay for the target asset. These limits are enforced automatically:\n\n- If the calculated top-up amount is below the minimum, the SDK increases it to `minAmount * 1.05`.\n- The provider determines the maximum purchase amount; this cannot be overridden.\n\nLimits use the quote currency returned by the provider, e.g., USD, and vary by region and payment method.\n\n## Props reference\n\n| Prop                | Type      | Default | Description                                           |\n| :------------------ | :-------- | :------ | :---------------------------------------------------- |\n| `isOnRampAvailable` | `boolean` | `true`  | Show or hide the card top-up option.                  |\n| `userIp`            | `string`  | –       | User's IP address for the geographic check; optional. |\n\n## Iframe events\n\nThe on-ramp widget communicates through `postMessage`. The SDK handles the following events internally:\n\n| Event                                             | Description                                                                             |\n| :------------------------------------------------ | :-------------------------------------------------------------------------------------- |\n| `TONPAY_IFRAME_LOADED`                            | The on-ramp widget loaded successfully.                                                 |\n| `TONPAY_MOONPAY_EVENT` (`onTransactionCompleted`) | The MoonPay purchase completes successfully. The SDK starts polling the wallet balance. |\n| `TONPAY_MOONPAY_EVENT` (`onTransactionFailed`)    | The MoonPay purchase failed. The user may retry the transaction.                        |\n| `TONPAY_PAYMENT_ERROR`                            | On-ramp widget initialization error; e.g., the link expired.                            |\n\nMerchants using `TonPayButton` do not need to handle these events manually.\n\n<Aside\n  type=\"note\"\n  title=\"Processing times and fees\"\n>\n  MoonPay purchases require on-chain confirmation and are not processed immediately. The SDK monitors the transaction status through automatic balance polling.\n\n  The SDK adds a 5% buffer to top-up amounts to account for MoonPay fees and price fluctuations.\n</Aside>\n"
  },
  {
    "path": "ecosystem/ton-pay/overview.mdx",
    "content": "---\ntitle: \"TON Pay SDK overview\"\nsidebarTitle: \"Overview\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nTON Pay SDK is a developer toolkit for integrating payment functionality on the TON blockchain. It supports web applications, [Telegram Mini Apps](/ecosystem/tma/overview), backend services, and bots. The SDK provides a unified interface for creating, verifying, and managing payments, abstracting blockchain-specific logic.\n\n<Aside\n  type=\"caution\"\n>\n  TON Pay is not a payment processor.\n</Aside>\n\n<Columns cols={2}>\n  <Card\n    title=\"For business\"\n    icon=\"credit-card\"\n  >\n    Accept TON and jettons as fiat-equivalent funds in the TON wallet, without intermediaries.\n  </Card>\n\n  <Card\n    title=\"For developers\"\n    icon=\"code\"\n  >\n    Integrate payments into web applications, bots, and services using the\n    SDK interface.\n  </Card>\n</Columns>\n\n## Supported wallets\n\nTON Pay SDK is compatible with TON wallets through the [TON Connect protocol](/ecosystem/ton-connect/overview) :\n\n<CardGroup cols={3}>\n  <Card\n    title=\"Tonkeeper\"\n    icon=\"mobile\"\n  >\n    iOS, Android, web, desktop\n  </Card>\n\n  <Card\n    title=\"MyTonWallet\"\n    icon=\"laptop\"\n  >\n    iOS, Android, desktop\n  </Card>\n\n  <Card\n    title=\"Tonhub\"\n    icon=\"mobile\"\n  >\n    iOS, Android\n  </Card>\n\n  <Card\n    title=\"OpenMask\"\n    icon=\"globe\"\n  >\n    Web extension\n  </Card>\n\n  <Card\n    title=\"TON Wallet\"\n    icon=\"desktop\"\n  >\n    Web, desktop\n  </Card>\n\n  <Card\n    title=\"Wallet bot\"\n    icon=\"paper-plane\"\n  >\n    Telegram\n  </Card>\n</CardGroup>\n\n## Features\n\n- Payment creation: one-time transfers, recurring payments, and subscriptions, with\n  customizable reference IDs and memo fields.\n- Transaction tracking: transaction status tracking, confirmation handling, error reporting, and\n  analytics.\n- UI components: React hooks, ready-to-use payment components, and built-in\n  status indicators.\n\n## UI integration\n\nWhile the SDK provides full programmatic control over payments, built-in UI components reduce integration time.\n\nThe `TonPayButton` React component handles wallet connection, transaction signing, loading states, and error notifications out of the box without requiring manual integration with TON Connect hooks or UI state management. It also covers common edge cases such as duplicate submissions, wallet disconnects, and user-visible errors.\n\nFor most web applications, the UI layer provides a functional checkout flow. The guide on [how to add a TON Pay button using React](/ecosystem/ton-pay/ui-integration/button-react) provides step-by-step instructions.\n\n## How TON Pay works\n\n1. TON Pay backend generates a transaction message.\n1. The user reviews and signs the transaction in the wallet.\n1. The transaction is executed and confirmed on the TON blockchain.\n1. TON Pay backend monitors the transaction status and sends webhook notifications to the application upon completion.\n\n## Security\n\n- Non-custodial: funds always remain under user control.\n- Standard protocols: built on proven TON standards.\n- Transparency: all transactions are verifiable on-chain.\n\n## Next steps\n\nInstall the [SDK](https://www.npmjs.com/package/@ton-pay/api) and configure the development environment.\n\n<sub>\n  TON Pay SDK is open source software licensed under the Apache License 2.0.\n</sub>\n"
  },
  {
    "path": "ecosystem/ton-pay/payment-integration/payments-react.mdx",
    "content": "---\ntitle: \"How to send payments using TON Pay React hook\"\nsidebarTitle: \"Send payments React\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nThe `useTonPay` hook provides a React interface for creating TON Pay transfers. It integrates with [TON Connect](/ecosystem/ton-connect/overview) to connect a wallet, sign transactions, and surface transfer errors through the hook state.\n\n## How `useTonPay` works\n\nThe `useTonPay` hook manages the client-side flow for sending a TON Pay transfer. It performs the following steps:\n\n1. Checks whether a wallet is connected and, if not, opens the TON Connect modal and waits for a successful connection.\n1. Calls an application-provided factory function that builds the transaction message, either in the client-side or by requesting it from a backend service.\n1. Sends the transaction message to the connected wallet for user approval and signing.\n1. Returns the transaction result along with tracking identifiers that can be used for reconciliation.\n\n## Integration approaches\n\n`useTonPay` can be integrated in two ways, depending on where the transaction message is created.\n\n### Client-side message building\n\n- Message construction happens in the browser.\n- All transaction fields are provided by the client.\n\n### Server-side message building\n\n- Message construction happens on the backend.\n- Tracking identifiers are stored on the server before the message is returned to the client for signing.\n\n## Client-side implementation\n\n### Prerequisites\n\nThe application must be wrapped with the TON Connect UI provider:\n\n```tsx\nimport { TonConnectUIProvider } from \"@tonconnect/ui-react\";\n\nexport function App() {\n  return (\n    <TonConnectUIProvider manifestUrl=\"/tonconnect-manifest.json\">\n      {/* Application components */}\n    </TonConnectUIProvider>\n  );\n}\n```\n\n[The TON Connect manifest](/ecosystem/ton-connect/manifest) file must be publicly accessible and include valid application metadata.\n\n### Basic implementation\n\n```tsx expandable\nimport { useTonPay } from \"@ton-pay/ui-react\";\nimport { createTonPayTransfer } from \"@ton-pay/api\";\n\nexport function PaymentButton() {\n  const { pay } = useTonPay();\n\n  const handlePayment = async () => {\n    try {\n      const { txResult, message, reference, bodyBase64Hash } = await pay(\n        async (senderAddr: string) => {\n          const result = await createTonPayTransfer(\n            {\n              amount: 3.5,\n              asset: \"TON\",\n              recipientAddr: \"<RECIPIENT_WALLET_ADDRESS>\",\n              senderAddr,\n              commentToSender: \"Payment for Order #8451\",\n            },\n            {\n              chain: \"testnet\",\n              // Optional API key can be shown on the client-side, but the secret key never\n              apiKey: \"<TONPAY_API_KEY>\", // optional\n            }\n          );\n\n          return {\n            message: result.message,\n            reference: result.reference,\n            bodyBase64Hash: result.bodyBase64Hash,\n          };\n        }\n      );\n\n      console.log(\"Transaction completed:\", txResult.boc);\n      console.log(\"Reference for tracking:\", reference);\n      console.log(\"Body hash:\", bodyBase64Hash);\n\n      // Store tracking identifiers in the database\n      await savePaymentRecord({\n        reference,\n        bodyBase64Hash,\n        amount: 3.5,\n        asset: \"TON\",\n      });\n    } catch (error) {\n      console.error(\"Payment failed:\", error);\n      // Handle error appropriately\n    }\n  };\n\n  return <button onClick={handlePayment}>Pay 3.5 TON</button>;\n}\n```\n\n### Response fields\n\nThe `pay` function returns the following fields:\n\n<ResponseField\n  name=\"txResult\"\n  type=\"SendTransactionResponse\"\n  required\n>\n  Transaction result returned by TON Connect. It contains the signed transaction [bag of cells](/foundations/serialization/boc) and additional transaction details.\n</ResponseField>\n\n<ResponseField\n  name=\"message\"\n  type=\"TonPayMessage\"\n  required\n>\n  The transaction message that was sent, including the recipient address, amount, and payload.\n</ResponseField>\n\n<ResponseField\n  name=\"reference\"\n  type=\"string\"\n>\n  Unique tracking identifier for this transaction. Use it to correlate webhook notifications with orders.\n\n  <Aside\n    type=\"caution\"\n  >\n    Store the reference after creation. It is required to match incoming webhook notifications to specific orders.\n  </Aside>\n</ResponseField>\n\n<ResponseField\n  name=\"bodyBase64Hash\"\n  type=\"string\"\n>\n  Base64-encoded hash of the transaction body. Can be used for advanced transaction verification.\n</ResponseField>\n\n## Server-side implementation\n\n### Backend endpoint\n\nCreate an API endpoint that builds the transaction message and stores tracking data:\n\n```typescript expandable\nimport { createTonPayTransfer } from \"@ton-pay/api\";\n\napp.post(\"/api/create-payment\", async (req, res) => {\n  const { amount, senderAddr, orderId } = req.body;\n\n  try {\n    const { message, reference, bodyBase64Hash } = await createTonPayTransfer(\n      {\n        amount,\n        asset: \"TON\",\n        recipientAddr: \"<MERCHANT_WALLET_ADDRESS>\",\n        senderAddr,\n        commentToSender: `Payment for Order ${orderId}`,\n        commentToRecipient: `Order ${orderId}`,\n      },\n      {\n        chain: \"testnet\",\n        apiKey: \"yourTonPayApiKey\", // optional\n      }\n    );\n\n    // Store tracking identifiers in your database\n    await db.createPayment({\n      orderId,\n      reference,\n      bodyBase64Hash,\n      amount,\n      asset: \"TON\",\n      status: \"pending\",\n      senderAddr,\n    });\n\n    // Return only the message to the client\n    res.json({ message });\n  } catch (error) {\n    console.error(\"Failed to create payment:\", error);\n    res.status(500).json({ error: \"Failed to create payment\" });\n  }\n});\n```\n\n<Aside\n  type=\"caution\"\n  title=\"Persist tracking identifiers before responding\"\n>\n  Always persist tracking identifiers such as `reference` and `bodyBase64Hash` in the database before returning the message to the client. If the client loses connection or closes the browser, these identifiers are still required to process incoming webhooks.\n</Aside>\n\n### Frontend implementation\n\n```tsx expandable\nimport { useTonPay } from \"@ton-pay/ui-react\";\n\nexport function ServerPaymentButton({\n  orderId,\n  amount,\n}: {\n  orderId: string;\n  amount: number;\n}) {\n  const { pay } = useTonPay();\n\n  const handlePayment = async () => {\n    try {\n      const { txResult } = await pay(async (senderAddr: string) => {\n        const response = await fetch(\"/api/create-payment\", {\n          method: \"POST\",\n          headers: { \"Content-Type\": \"application/json\" },\n          body: JSON.stringify({ amount, senderAddr, orderId }),\n        });\n\n        if (!response.ok) {\n          throw new Error(\"Failed to create payment\");\n        }\n\n        const { message } = await response.json();\n        return { message };\n      });\n\n      console.log(\"Transaction sent:\", txResult.boc);\n\n      // Optionally redirect or show success message\n      window.location.href = `/orders/${orderId}/success`;\n    } catch (error) {\n      console.error(\"Payment failed:\", error);\n      alert(\"Payment failed. Please try again.\");\n    }\n  };\n\n  return <button onClick={handlePayment}>Pay {amount} TON</button>;\n}\n```\n\n## Error handling\n\nThe `useTonPay` hook throws errors in the following scenarios:\n\n### Wallet connection errors\n\n```typescript\nconst { pay } = useTonPay();\n\ntry {\n  await pay(getMessage);\n} catch (error) {\n  if (error.message === \"Wallet connection modal closed\") {\n    // User closed the connection modal without connecting\n    console.log(\"User cancelled wallet connection\");\n  } else if (error.message === \"Wallet connection timeout\") {\n    // Connection attempt exceeded 5-minute timeout\n    console.log(\"Connection timeout - please try again\");\n  }\n}\n```\n\n### Transaction errors\n\n```typescript\ntry {\n  await pay(getMessage);\n} catch (error) {\n  // User rejected the transaction in their wallet\n  if (error.message?.includes(\"rejected\")) {\n    console.log(\"User rejected the transaction\");\n  }\n\n  // Network or API errors\n  else if (error.message?.includes(\"Failed to create TON Pay transfer\")) {\n    console.log(\"API error - check your configuration\");\n  }\n\n  // Other unexpected errors\n  else {\n    console.error(\"Unexpected error:\", error);\n  }\n}\n```\n\n## Best practices\n\n- Persist tracking identifiers immediately.\n\n  ```typescript\n  // Good: Store before transaction\n  const { message, reference } = await createTonPayTransfer(...);\n  await db.createPayment({ reference, status: \"pending\" });\n  return { message };\n\n  // Bad: Only storing after successful transaction\n  const { txResult, reference } = await pay(...);\n  await db.createPayment({ reference }); // Too late if network fails\n  ```\n\n- Always validate or generate amounts server-side to prevent manipulation. Never trust amount values sent from the client.\n\n  ```typescript\n  // Server-side endpoint\n  app.post('/api/create-payment', async (req, res) => {\n      const { orderId, senderAddr } = req.body;\n\n      // Fetch the actual amount from your database\n      const order = await db.getOrder(orderId);\n\n      // Use the verified amount, not req.body.amount\n      const { message } = await createTonPayTransfer({\n          amount: order.amount,\n          asset: order.currency,\n          recipientAddr: '<RECIPIENT_WALLET_ADDRESS>',\n          senderAddr,\n      });\n\n      res.json({ message });\n  });\n  ```\n\n- Wrap the payment components with React error boundaries to handle failures.\n\n  ```tsx\n  class PaymentErrorBoundary extends React.Component {\n      componentDidCatch(error: Error) {\n          console.error('Payment component error:', error);\n          // Log to the error tracking service\n      }\n\n      render() {\n          return this.props.children;\n      }\n  }\n  ```\n\n- Payment processing can take several seconds. Provide clear feedback to users during wallet connection and transaction signing.\n\n  ```tsx\n  const [loading, setLoading] = useState(false);\n\n  const handlePayment = async () => {\n      setLoading(true);\n      try {\n          await pay(getMessage);\n      } finally {\n          setLoading(false);\n      }\n  };\n\n  return (\n      <button onClick={handlePayment} disabled={loading}>\n          {loading ? 'Processing...' : 'Pay Now'}\n      </button>\n  );\n  ```\n\n- Use environment variables for sensitive data and chain configuration.\n\n  ```typescript\n  const { message } = await createTonPayTransfer(params, {\n    chain: process.env.TON_CHAIN as 'mainnet' | 'testnet',\n    apiKey: process.env.TONPAY_API_KEY, // optional\n  });\n  ```\n\n## Troubleshooting\n\n<Accordion\n  title=\"If the hook throws TonConnect provider not found\"\n>\n  Wrap the application with `TonConnectUIProvider`:\n\n  ```tsx\n  import { TonConnectUIProvider } from \"@tonconnect/ui-react\";\n\n  function App() {\n    return (\n      <TonConnectUIProvider manifestUrl=\"/tonconnect-manifest.json\">\n        <YourComponents />\n      </TonConnectUIProvider>\n    );\n  }\n  ```\n</Accordion>\n\n<Accordion\n  title=\"If the wallet connection modal does not open\"\n>\n  1. Verify that the TON Connect manifest URL is accessible and valid.\n  1. Check the browser console for TON Connect initialization errors.\n  1. Ensure the manifest file is served with correct [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS) headers.\n  1. Open the manifest URL directly in the browser to verify it loads.\n</Accordion>\n\n<Accordion\n  title=\"If the transaction fails with Invalid recipient address\"\n>\n  1. Verify that the recipient address is [a valid TON address](/foundations/addresses/formats).\n  1. Ensure the address format matches the selected chain; mainnet or testnet.\n  1. Verify that the address includes the full base64 representation with workchain.\n</Accordion>\n\n<Accordion\n  title=\"If the factory function throws Failed to create TON Pay transfer\"\n>\n  1. Check whether the optional API key is missing or invalid for endpoints that require authentication.\n  1. Verify network connectivity.\n  1. Validate parameter values. For example, non-negative amounts and valid addresses.\n  1. Confirm the correct chain configuration; mainnet or testnet.\n\n  To inspect the underlying API error:\n\n  ```ts\n  try {\n    await createTonPayTransfer(...);\n  } catch (error) {\n    console.error(\"API Error:\", error.cause); // HTTP status text\n  }\n  ```\n</Accordion>\n\n<Accordion\n  title=\"If the user rejects the transaction and no error is reported\"\n>\n  1. Note that TON Connect may not emit an explicit error on rejection.\n  1. Add timeout handling:\n\n  ```ts\n  const paymentPromise = pay(getMessage);\n  const timeoutPromise = new Promise((_, reject) =>\n    setTimeout(() => reject(new Error(\"Transaction timeout\")), 60000)\n  );\n\n  await Promise.race([paymentPromise, timeoutPromise]);\n  ```\n</Accordion>\n\n## Optional API key configuration\n\nWhen using `useTonPay` with server-side message building, the optional API key can be included in the backend endpoint to enable dashboard features and webhooks:\n\n```typescript\n// Backend endpoint\napp.post(\"/api/create-payment\", async (req, res) => {\n  const { amount, senderAddr, orderId } = req.body;\n\n  const { message, reference, bodyBase64Hash } = await createTonPayTransfer(\n    {\n      amount,\n      asset: \"TON\",\n      recipientAddr: process.env.MERCHANT_WALLET_ADDRESS!,\n      senderAddr,\n    },\n    {\n      chain: \"testnet\",\n      apiKey: process.env.TONPAY_API_KEY, // Optional: enables dashboard features\n    }\n  );\n\n  await db.createPayment({ orderId, reference, bodyBase64Hash });\n  res.json({ message });\n});\n```\n\n## Testnet configuration\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  Running tests on mainnet can result in irreversible loss of real TON. Always use `chain: \"testnet\"` and testnet wallet addresses during development. Verify the network before switching to mainnet.\n</Aside>\n\nA complete description of testnet configuration, including obtaining testnet TON, testing jetton transfers, verifying transactions, and preparing for mainnet deployment, is available in the [Testnet configuration](/ecosystem/ton-pay/payment-integration/transfer#testnet-configuration) section.\n\n## Next steps\n\n<CardGroup cols={2}>\n  <Card\n    title=\"Webhook integration\"\n    icon=\"webhook\"\n    href=\"/ecosystem/ton-pay/webhooks\"\n  >\n    Receive real-time notifications when payments complete.\n  </Card>\n\n  <Card\n    title=\"Transaction status\"\n    icon=\"magnifying-glass\"\n    href=\"/ecosystem/ton-pay/payment-integration/status-info\"\n  >\n    Query payment status using reference or body hash.\n  </Card>\n</CardGroup>\n"
  },
  {
    "path": "ecosystem/ton-pay/payment-integration/payments-tonconnect.mdx",
    "content": "---\ntitle: \"How to send payments using TON Connect\"\nsidebarTitle: \"Send payments TON Connect\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nUse TON Connect native `sendTransaction` method when:\n\n- The application manages wallet connection UI and transaction flow directly.\n- TON Connect is already used elsewhere in the application.\n- Access to TON Connect-specific APIs is required, such as status change listeners or custom wallet adapters.\n\n## Integration overview\n\nDirect TON Connect integration follows these steps:\n\n1. Configure the TON Connect UI provider with the application manifest.\n1. Manage wallet connection state and provide UI for users to connect the wallets.\n1. Create a transaction message on the client or backend using `createTonPayTransfer`.\n1. Send the transaction using TON Connect's `sendTransaction` method.\n1. Observe connection state changes and transaction status updates.\n\n## React implementation\n\n### Set up application\n\nWrap the application with the TON Connect UI provider:\n\n```tsx\nimport { TonConnectUIProvider } from \"@tonconnect/ui-react\";\n\nexport function Providers({ children }: { children: React.ReactNode }) {\n  return (\n    <TonConnectUIProvider manifestUrl=\"/tonconnect-manifest.json\">\n      {children}\n    </TonConnectUIProvider>\n  );\n}\n```\n\nThe manifest URL must be publicly accessible and served over HTTPS in production. [The manifest file](/ecosystem/ton-connect/manifest) provides application metadata required for wallet identification.\n\n### Payment component\n\n```tsx expandable\nimport {\n  useTonAddress,\n  useTonConnectModal,\n  useTonConnectUI,\n} from \"@tonconnect/ui-react\";\nimport { createTonPayTransfer } from \"@ton-pay/api\";\nimport { useState } from \"react\";\n\nexport function PaymentComponent({ orderId, amount }: { orderId: string; amount: number }) {\n  const address = useTonAddress(true); // Get user-friendly address format\n  const { open } = useTonConnectModal();\n  const [tonConnectUI] = useTonConnectUI();\n  const [loading, setLoading] = useState(false);\n\n  const handlePayment = async () => {\n    // Check if wallet is connected\n    if (!address) {\n      open();\n      return;\n    }\n\n    setLoading(true);\n\n    try {\n      // Create the transaction message\n      // Note: For production, consider moving this to a server endpoint\n      const { message, reference, bodyBase64Hash } = await createTonPayTransfer(\n        {\n          amount,\n          asset: \"TON\",\n          recipientAddr: \"<RECIPIENT_WALLET_ADDRESS>\",\n          senderAddr: address,\n          commentToSender: `Payment for Order ${orderId}`,\n          commentToRecipient: `Order ${orderId}`,\n        },\n        {\n          chain: \"testnet\",\n          // Optional API key can be used client-side\n          apiKey: \"<TONPAY_API_KEY>\", // optional\n        }\n      );\n\n      // Store tracking identifiers\n      await fetch(\"/api/store-payment\", {\n        method: \"POST\",\n        headers: { \"Content-Type\": \"application/json\" },\n        body: JSON.stringify({ reference, bodyBase64Hash, orderId, amount }),\n      });\n\n      // Send transaction through TonConnect\n      const result = await tonConnectUI.sendTransaction({\n        messages: [message],\n        validUntil: Math.floor(Date.now() / 1000) + 300, // 5 minutes\n        from: address,\n      });\n\n      console.log(\"Transaction sent:\", result.boc);\n\n      // Handle success\n      window.location.href = `/orders/${orderId}/success`;\n    } catch (error) {\n      console.error(\"Payment failed:\", error);\n      alert(\"Payment failed. Please try again.\");\n    } finally {\n      setLoading(false);\n    }\n  };\n\n  return (\n    <button onClick={handlePayment} disabled={loading}>\n      {loading ? \"Processing...\" : address ? `Pay ${amount} TON` : \"Connect Wallet\"}\n    </button>\n  );\n}\n```\n\n### Manage connection state\n\nListen for wallet connection status changes using the TON Connect UI API:\n\n```tsx\nimport { useEffect } from \"react\";\nimport { useTonConnectUI } from \"@tonconnect/ui-react\";\n\nexport function WalletStatus() {\n  const [tonConnectUI] = useTonConnectUI();\n  const [walletInfo, setWalletInfo] = useState(null);\n\n  useEffect(() => {\n    // Listen for connection status changes\n    const unsubscribe = tonConnectUI.onStatusChange((wallet) => {\n      if (wallet) {\n        console.log(\"Wallet connected:\", wallet.account.address);\n        setWalletInfo({\n          address: wallet.account.address,\n          chain: wallet.account.chain,\n          walletName: wallet.device.appName,\n        });\n      } else {\n        console.log(\"Wallet disconnected\");\n        setWalletInfo(null);\n      }\n    });\n\n    return () => {\n      unsubscribe();\n    };\n  }, [tonConnectUI]);\n\n  if (!walletInfo) {\n    return <div>No wallet connected</div>;\n  }\n\n  return (\n    <div>\n      <p>Connected: {walletInfo.walletName}</p>\n      <p>Address: {walletInfo.address}</p>\n    </div>\n  );\n}\n```\n\n## Server-side message building\n\nFor production applications, build transaction messages on the server to centralize tracking and validation.\n\n### Backend endpoint\n\n```typescript expandable\nimport { createTonPayTransfer } from \"@ton-pay/api\";\nimport { validateWalletAddress } from \"./utils/validation\";\n\napp.post(\"/api/create-transaction\", async (req, res) => {\n  const { orderId, senderAddr } = req.body;\n\n  try {\n    // Validate inputs\n    if (!validateWalletAddress(senderAddr)) {\n      return res.status(400).json({ error: \"Invalid wallet address\" });\n    }\n\n    // Fetch order details from database\n    const order = await db.orders.findById(orderId);\n    if (!order) {\n      return res.status(404).json({ error: \"Order not found\" });\n    }\n\n    if (order.status !== \"pending\") {\n      return res.status(400).json({ error: \"Order already processed\" });\n    }\n\n    // Create transaction message\n    const { message, reference, bodyBase64Hash } = await createTonPayTransfer(\n      {\n        amount: order.amount,\n        asset: order.currency || \"TON\",\n        recipientAddr: \"<RECIPIENT_WALLET_ADDRESS>\",\n        senderAddr,\n        commentToSender: `Payment for Order ${order.id}`,\n        commentToRecipient: `Order ${order.id} - ${order.description}`,\n      },\n      {\n        chain: \"testnet\",\n        apiKey: \"TONPAY_API_KEY\", // optional\n      }\n    );\n\n    // Store tracking identifiers\n    await db.payments.create({\n      orderId: order.id,\n      reference,\n      bodyBase64Hash,\n      amount: order.amount,\n      asset: order.currency || \"TON\",\n      senderAddr,\n      status: \"pending\",\n      createdAt: new Date(),\n    });\n\n    // Return message to client\n    res.json({ message });\n  } catch (error) {\n    console.error(\"Failed to create transaction:\", error);\n    res.status(500).json({ error: \"Failed to create transaction\" });\n  }\n});\n```\n\n### Frontend implementation\n\n```tsx expandable\nexport function ServerManagedPayment({ orderId }: { orderId: string }) {\n  const address = useTonAddress(true);\n  const { open } = useTonConnectModal();\n  const [tonConnectUI] = useTonConnectUI();\n  const [loading, setLoading] = useState(false);\n\n  const handlePayment = async () => {\n    if (!address) {\n      open();\n      return;\n    }\n\n    setLoading(true);\n\n    try {\n      // Request transaction message from server\n      const response = await fetch(\"/api/create-transaction\", {\n        method: \"POST\",\n        headers: { \"Content-Type\": \"application/json\" },\n        body: JSON.stringify({ orderId, senderAddr: address }),\n      });\n\n      if (!response.ok) {\n        const error = await response.json();\n        throw new Error(error.error || \"Failed to create transaction\");\n      }\n\n      const { message } = await response.json();\n\n      // Send transaction\n      const result = await tonConnectUI.sendTransaction({\n        messages: [message],\n        validUntil: Math.floor(Date.now() / 1000) + 300,\n        from: address,\n      });\n\n      console.log(\"Transaction completed:\", result.boc);\n\n      // Navigate to success page\n      window.location.href = `/orders/${orderId}/success`;\n    } catch (error) {\n      console.error(\"Payment error:\", error);\n      alert(error.message || \"Payment failed\");\n    } finally {\n      setLoading(false);\n    }\n  };\n\n  return (\n    <button onClick={handlePayment} disabled={loading}>\n      {loading ? \"Processing...\" : \"Complete Payment\"}\n    </button>\n  );\n}\n```\n\n## Vanilla JavaScript implementation\n\nFor non-React applications, use the TON Connect SDK directly:\n\n```javascript expandable\nimport TonConnectUI from \"@tonconnect/ui\";\nimport { createTonPayTransfer } from \"@ton-pay/api\";\n\nconst tonConnectUI = new TonConnectUI({\n  manifestUrl: \"https://yourdomain.com/tonconnect-manifest.json\",\n});\n\n// Connect wallet\nasync function connectWallet() {\n  await tonConnectUI.connectWallet();\n}\n\n// Send payment\nasync function sendPayment(amount, orderId) {\n  const wallet = tonConnectUI.wallet;\n\n  if (!wallet) {\n    await connectWallet();\n    return;\n  }\n\n  try {\n    // Create transaction message\n    const { message, reference, bodyBase64Hash } = await createTonPayTransfer(\n      {\n        amount,\n        asset: \"TON\",\n        recipientAddr: \"<RECIPIENT_WALLET_ADDRESS>\",\n        senderAddr: wallet.account.address,\n        commentToSender: `Order ${orderId}`,\n      },\n      { chain: \"testnet\" }\n    );\n\n    // Store tracking data\n    await fetch(\"/api/store-payment\", {\n      method: \"POST\",\n      headers: { \"Content-Type\": \"application/json\" },\n      body: JSON.stringify({ reference, bodyBase64Hash, orderId }),\n    });\n\n    // Send transaction\n    const result = await tonConnectUI.sendTransaction({\n      messages: [message],\n      validUntil: Math.floor(Date.now() / 1000) + 300,\n      from: wallet.account.address,\n    });\n\n    console.log(\"Payment successful:\", result.boc);\n  } catch (error) {\n    console.error(\"Payment failed:\", error);\n  }\n}\n\n// Listen for connection changes\ntonConnectUI.onStatusChange((wallet) => {\n  if (wallet) {\n    console.log(\"Wallet connected:\", wallet.account.address);\n    document.getElementById(\"wallet-address\").textContent = wallet.account.address;\n  } else {\n    console.log(\"Wallet disconnected\");\n    document.getElementById(\"wallet-address\").textContent = \"Not connected\";\n  }\n});\n```\n\n## Transaction parameters\n\n### Message structure\n\nThe message object passed to `sendTransaction` must include these fields:\n\n<ResponseField\n  name=\"address\"\n  type=\"string\"\n  required\n>\n  Recipient wallet address in [user-friendly format](/foundations/addresses/formats).\n</ResponseField>\n\n<ResponseField\n  name=\"amount\"\n  type=\"string\"\n  required\n>\n  Amount to send in nanotons.\n</ResponseField>\n\n<ResponseField\n  name=\"payload\"\n  type=\"string\"\n  required\n>\n  Base64-encoded message payload containing transfer details and tracking information.\n</ResponseField>\n\n### Transaction options\n\n<ResponseField\n  name=\"validUntil\"\n  type=\"number\"\n  required\n>\n  Unix timestamp indicating when the transaction expires. Typically is 5 minutes.\n\n  ```typescript\n  validUntil: Math.floor(Date.now() / 1000) + 300\n  ```\n</ResponseField>\n\n<ResponseField\n  name=\"from\"\n  type=\"string\"\n  required\n>\n  Sender's wallet address. Must match the connected wallet address.\n</ResponseField>\n\n<ResponseField\n  name=\"network\"\n  type=\"string\"\n>\n  Network identifier. Usually omitted as it is inferred from the connected wallet.\n</ResponseField>\n\n## Error handling\n\n```typescript\nasync function handleTransaction() {\n  try {\n    const result = await tonConnectUI.sendTransaction({\n      messages: [message],\n      validUntil: Math.floor(Date.now() / 1000) + 300,\n      from: address,\n    });\n\n    return result;\n  } catch (error) {\n    // User rejected the transaction\n    if (error.message?.includes(\"rejected\")) {\n      console.log(\"User cancelled the transaction\");\n      return null;\n    }\n\n    // Wallet not connected\n    if (error.message?.includes(\"Wallet is not connected\")) {\n      console.log(\"Connect the wallet first\");\n      tonConnectUI.connectWallet();\n      return null;\n    }\n\n    // Transaction expired\n    if (error.message?.includes(\"expired\")) {\n      console.log(\"Transaction expired, please try again\");\n      return null;\n    }\n\n    // Network or other errors\n    console.error(\"Transaction failed:\", error);\n    throw error;\n  }\n}\n```\n\n## Best practices\n\n- Check wallet connection status before attempting to send transactions. Provide clear UI feedback for connection state.\n\n  ```typescript\n  const wallet = tonConnectUI.wallet;\n\n  if (!wallet) {\n      // Show connect button\n      return;\n  }\n\n  // Proceed with transaction\n  ```\n\n- Use a reasonable `validUntil` value, typically 5 minutes, to prevent stale transactions while allowing enough time for user confirmation.\n\n  ```typescript\n  const validUntil = Math.floor(Date.now() / 1000) + 300; // 5 minutes\n  ```\n\n- Ensure the sender address from TON Connect matches the format expected by the backend. Use the [user-friendly format](/foundations/addresses/formats) consistently.\n\n  ```typescript\n  const address = useTonAddress(true); // true = user-friendly format\n  ```\n\n- Always persist `reference` and `bodyBase64Hash` before sending the transaction. This allows payment reconciliation through webhooks even if the client flow fails after submission.\n\n  ```typescript\n  // Good: Store first, then send\n  await storePaymentTracking(reference, bodyBase64Hash);\n  await tonConnectUI.sendTransaction(...);\n\n  // Bad: Send first, then store\n  await tonConnectUI.sendTransaction(...);\n  await storePaymentTracking(reference, bodyBase64Hash); // Might not execute\n  ```\n\n- Implement connection state listeners to update the UI and handle wallet disconnections.\n\n  ```typescript\n  useEffect(() => {\n      const unsubscribe = tonConnectUI.onStatusChange((wallet) => {\n          if (wallet) {\n              setConnectedWallet(wallet.account.address);\n          } else {\n              setConnectedWallet(null);\n          }\n      });\n\n      return unsubscribe;\n  }, [tonConnectUI]);\n  ```\n\n- Handle transaction rejection explicitly. Treat user rejection as a normal cancellation, not as an error.\n\n  ```typescript\n  try {\n    await tonConnectUI.sendTransaction(transaction);\n  } catch (error) {\n    if (error.message?.includes(\"rejected\")) {\n      // Don't show error - user intentionally cancelled\n      console.log(\"Transaction cancelled by user\");\n    } else {\n      // Show error for unexpected failures\n      showErrorMessage(\"Transaction failed\");\n    }\n  }\n  ```\n\n## Troubleshooting\n\n<Accordion\n  title=\"If a transaction fails with Wallet is not connected\"\n>\n  Ensure the wallet is connected before calling `sendTransaction`:\n\n  ```typescript\n  if (!tonConnectUI.wallet) {\n    await tonConnectUI.connectWallet();\n    // Wait for connection before proceeding\n  }\n  ```\n\n  Add a connection state check:\n\n  ```typescript\n  const isConnected = tonConnectUI.wallet !== null;\n  ```\n</Accordion>\n\n<Accordion\n  title=\"If sendTransaction throws Invalid address format\"\n>\n  1. Ensure the `from` address matches the connected wallet address.\n  1. Verify that the recipient address is [a valid TON address](/foundations/addresses/formats).\n  1. Use the wallet address provided by the SDK to avoid format mismatches:\n\n  ```typescript\n  const address = useTonAddress(true); // Ensure consistent format\n  ```\n</Accordion>\n\n<Accordion\n  title=\"If a transaction expires before the user signs it\"\n>\n  The `validUntil` timestamp may be too short. Increase the validity period to give the user more time to confirm the transaction:\n\n  ```typescript\n  // Increase from 5 to 10 minutes if needed\n  validUntil: Math.floor(Date.now() / 1000) + 600\n  ```\n</Accordion>\n\n<Accordion\n  title=\"If the manifest URL fails to load\"\n>\n  Check for the following common issues:\n\n  - The URL is not publicly accessible.\n  - [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS) headers are not configured correctly.\n  - The manifest JSON is malformed.\n  - The URL is not HTTPS; required in production.\n\n  Open the manifest URL directly in a browser to verify that it is accessible.\n</Accordion>\n\n<Accordion\n  title=\"If onStatusChange is not triggered\"\n>\n  Ensure that the status change subscription is created once and remains active for the lifetime of the component.\n\n  ```typescript\n  useEffect(() = >{\n    const unsubscribe = tonConnectUI.onStatusChange(handleWalletChange);\n    return () = >unsubscribe(); // Clean up subscription\n  },\n  [tonConnectUI]);\n  ```\n</Accordion>\n\n<Accordion\n  title=\"If multiple wallet connection prompts appear\"\n>\n  `connectWallet()` may be called more than once. Track the connection state:\n\n  ```typescript\n  const[isConnecting, setIsConnecting] = useState(false);\n\n  const connect = async() = >{\n    if (isConnecting) return;\n    setIsConnecting(true);\n    try {\n      await tonConnectUI.connectWallet();\n    } finally {\n      setIsConnecting(false);\n    }\n  };\n  ```\n</Accordion>\n\n## Optional API key configuration\n\nWhen using TON Connect with server-side message building, [the optional API key can be included](/ecosystem/ton-pay/payment-integration/payments-tonconnect#api-key-configuration) in the backend:\n\n```typescript\nimport { createTonPayTransfer } from \"@ton-pay/api\";\n\napp.post(\"/api/create-transaction\", async (req, res) => {\n  const { orderId, senderAddr } = req.body;\n  const order = await db.orders.findById(orderId);\n\n  const { message, reference, bodyBase64Hash } = await createTonPayTransfer(\n    {\n      amount: order.amount,\n      asset: \"TON\",\n      recipientAddr: \"<RECIPIENT_WALLET_ADDRESS>\",\n      senderAddr: \"<SENDER_WALLET_ADDRESS>\",\n    },\n    {\n      chain: \"testnet\",\n      apiKey: \"TONPAY_API_KEY\", // optional\n    }\n  );\n\n  await db.payments.create({ orderId, reference, bodyBase64Hash });\n  res.json({ message });\n});\n```\n\n## Testnet configuration\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  Running tests on mainnet can result in irreversible loss of real TON. Always use `chain: \"testnet\"` and testnet wallet addresses during development. Verify the network before switching to mainnet.\n</Aside>\n\n### Set up testnet\n\nConfigure the environment to use testnet:\n\n```bash\n# .env.development\nTON_CHAIN=testnet\nMERCHANT_WALLET_ADDRESS=TESTNET_ADDRESS\n```\n\n```tsx\nimport { useTonAddress, useTonConnectUI } from \"@tonconnect/ui-react\";\nimport { createTonPayTransfer } from \"@ton-pay/api\";\n\nexport function TestnetPayment({ amount }: { amount: number }) {\n  const address = useTonAddress(true);\n  const [tonConnectUI] = useTonConnectUI();\n\n  const handlePayment = async () => {\n    if (!address) {\n      tonConnectUI.connectWallet();\n      return;\n    }\n\n    const { message } = await createTonPayTransfer(\n      {\n        amount,\n        asset: \"TON\",\n        recipientAddr: \"<RECIPIENT_WALLET_ADDRESS>\",\n        senderAddr: \"<SENDER_WALLET_ADDRESS>\",\n      },\n      { chain: \"testnet\" } // Use testnet\n    );\n\n    const result = await tonConnectUI.sendTransaction({\n      messages: [message],\n      validUntil: Math.floor(Date.now() / 1000) + 300,\n      from: address,\n    });\n\n    console.log(\"Testnet transaction:\", result.boc);\n  };\n\n  return <button onClick={handlePayment}>Test Payment</button>;\n}\n```\n\n## Next steps\n\n<CardGroup cols={2}>\n  <Card\n    title=\"Webhook integration\"\n    icon=\"webhook\"\n    href=\"/ecosystem/ton-pay/payment-integration/transfer\"\n  >\n    Receive real-time notifications when payments complete.\n  </Card>\n\n  <Card\n    title=\"Transaction status\"\n    icon=\"magnifying-glass\"\n    href=\"/ecosystem/ton-pay/payment-integration/status-info\"\n  >\n    Query payment status using reference or body hash.\n  </Card>\n</CardGroup>\n"
  },
  {
    "path": "ecosystem/ton-pay/payment-integration/status-info.mdx",
    "content": "---\ntitle: \"How to check status and retrieve info\"\nsidebarTitle: \"Check status and retrieve info\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nAfter sending, look up the final result and details. The SDK exposes two lookup functions.\n\n## By body hash\n\nUse the Base64 hash of the signed message body payload.\n\n```ts\nimport { getTonPayTransferByBodyHash } from \"@ton-pay/api\";\n\nconst info = await getTonPayTransferByBodyHash(bodyBase64Hash, {\n  chain: \"testnet\",\n});\n```\n\n## By reference\n\nUse the `reference` returned by `createTonPayTransfer`.\n\n```ts\nimport { getTonPayTransferByReference } from \"@ton-pay/api\";\n\nconst info = await getTonPayTransferByReference(reference, {\n  chain: \"testnet\",\n});\n```\n\n### Return shape\n\n```ts\ntype CompletedTonPayTransferInfo = {\n  amount: string;\n  rawAmount: string;\n  senderAddr: string;\n  recipientAddr: string;\n  asset: string;\n  assetTicker?: string;\n  status: string;\n  reference: string;\n  bodyBase64Hash: string;\n  txHash: string;\n  traceId: string;\n  commentToSender?: string;\n  commentToRecipient?: string;\n  date: string;\n  errorCode?: number;\n  errorMessage?: string;\n};\n```\n\nUse `status` to drive UI state and use `reference`, `bodyBase64Hash`, and `txHash` for reconciliation.\n\n<Aside\n  type=\"caution\"\n>\n  For Toncoin payments, the recipient amount may be reduced by [network fees](/foundations/fees). Use jettons or slightly overpay in TON when an exact settlement amount is\n  required.\n</Aside>\n\n## Response fields\n\n<ResponseField\n  name=\"amount\"\n  type=\"string\"\n  required\n>\n  Human-readable amount with decimals.\n</ResponseField>\n\n<ResponseField\n  name=\"rawAmount\"\n  type=\"string\"\n  required\n>\n  Amount in base units; nano for TON and jetton base units.\n</ResponseField>\n\n<ResponseField\n  name=\"senderAddr\"\n  type=\"string\"\n  required\n>\n  Sender wallet address.\n</ResponseField>\n\n<ResponseField\n  name=\"recipientAddr\"\n  type=\"string\"\n  required\n>\n  Recipient wallet address.\n</ResponseField>\n\n<ResponseField\n  name=\"asset\"\n  type=\"string\"\n  required\n>\n  Asset address. \"TON\" for coin or jetton master address.\n</ResponseField>\n\n<ResponseField\n  name=\"status\"\n  type=\"string\"\n  required\n>\n  Possible values:\n\n  - `pending` – the transfer is created and awaits confirmation on the blockchain.\n  - `success` – the transfer is completed successfully; the trace completes without errors.\n  - `error` – the transfer fails; the trace completes with an error.\n</ResponseField>\n\n<ResponseField\n  name=\"reference\"\n  type=\"string\"\n  required\n>\n  Tracking reference returned at creation time.\n</ResponseField>\n\n<ResponseField\n  name=\"bodyBase64Hash\"\n  type=\"string\"\n  required\n>\n  Base64 hash of the signed message body content (payload). Used for lookups.\n</ResponseField>\n\n<ResponseField\n  name=\"txHash\"\n  type=\"string\"\n  required\n>\n  Transaction hash assigned by the network.\n</ResponseField>\n\n<ResponseField\n  name=\"traceId\"\n  type=\"string\"\n  required\n>\n  Trace identifier for explorer.\n</ResponseField>\n\n<ResponseField\n  name=\"commentToSender\"\n  type=\"string\"\n>\n  Optional note shown to the payer while signing. Public on-chain; avoid confidential data and keep under 120 characters to reduce gas.\n</ResponseField>\n\n<ResponseField\n  name=\"commentToRecipient\"\n  type=\"string\"\n>\n  Optional note shown to the payee after receipt. Public on-chain; avoid confidential data and keep under 120 characters to reduce gas.\n</ResponseField>\n"
  },
  {
    "path": "ecosystem/ton-pay/payment-integration/transfer.mdx",
    "content": "---\ntitle: \"How to build a transfer\"\nsidebarTitle: \"Build a transfer\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nUse this server-side helper to generate a canonical TON message payload and a tracking reference.\n\n```ts\nimport { createTonPayTransfer } from \"@ton-pay/api\";\n\nconst { message, bodyBase64Hash, reference } = await createTonPayTransfer(\n  {\n    amount: 10.5,\n    asset: \"TON\",\n    recipientAddr: \"<RECIPIENT_ADDRESS>\",\n    senderAddr: \"<SENDER_ADDRESS>\",\n    commentToSender: \"Payment for Order #1234\",\n    commentToRecipient: \"Order #1234\",\n  },\n  {\n    chain: \"testnet\",\n    apiKey: \"<TONPAY_API_KEY>\", // optional\n  }\n);\n```\n\n<Aside type=\"tip\">\n  The TON Pay API key is optional, but providing it enables transaction visibility in the TON Pay Merchant Dashboard, webhook notifications, and wallet management features.\n</Aside>\n\n## Function signature\n\n```ts\ncreateTonPayTransfer(\n  params: CreateTonPayTransferParams,\n  options?: APIOptions\n): Promise<CreateTonPayTransferResponse>\n```\n\n### Transfer parameters\n\n```ts\ntype CreateTonPayTransferParams = {\n  amount: number;\n  asset: string;\n  recipientAddr?: string;\n  senderAddr: string;\n  queryId?: number;\n  commentToSender?: string;\n  commentToRecipient?: string;\n};\n```\n\n### API options\n\n```ts\ntype APIOptions = {\n  chain?: \"mainnet\" | \"testnet\";\n  apiKey?: string; // optional\n};\n```\n\n<ParamField\n  body=\"chain\"\n  type=\"string\"\n  default=\"mainnet\"\n>\n  Target blockchain network. Use `\"mainnet\"` for production or `\"testnet\"` for development and testing.\n</ParamField>\n\n<ParamField\n  body=\"apiKey\"\n  type=\"string\"\n>\n  The optional TON Pay API key from the Merchant Dashboard. When provided, it enables:\n\n  - Transaction visibility in the TON Pay Merchant Dashboard.\n  - Webhook notifications for completed transactions.\n  - Receiving wallet management from the Merchant Dashboard.\n</ParamField>\n\n## Parameter details\n\n<ParamField\n  body=\"amount\"\n  type=\"number\"\n  required\n>\n  Human-readable payment amount. Decimals are allowed, for example, 10.5 TON.\n</ParamField>\n\n<ParamField\n  body=\"asset\"\n  type=\"string\"\n  required\n>\n  Asset to transfer. Use \"TON\" for Toncoin or a jetton master address or constant, for example, USDT.\n</ParamField>\n\n<Aside\n  type=\"danger\"\n  title=\"Mainnet address risk\"\n>\n  Token constants such as `USDT` always reference mainnet jetton master addresses and are not affected by the `chain` option. Using them on testnet may send transactions to mainnet contracts.\n\n  For testnet, explicitly pass the correct testnet jetton master address instead of using token constants.\n</Aside>\n\n<ParamField\n  body=\"recipientAddr\"\n  type=\"string\"\n>\n  Payee wallet address. Optional if an API key is provided. Defaults to the merchant’s default wallet address configured in the Merchant Dashboard.\n</ParamField>\n\n<ParamField\n  body=\"senderAddr\"\n  type=\"string\"\n  required\n>\n  Payer wallet address. In UI flows, obtain it from TON Connect.\n</ParamField>\n\n<ParamField\n  body=\"queryId\"\n  type=\"number\"\n>\n  Jetton only. Numeric identifier embedded into the jetton payload for idempotency and tracking. Ignored for Toncoin payments.\n</ParamField>\n\n<ParamField\n  body=\"commentToSender\"\n  type=\"string\"\n>\n  Short note visible to the user in the wallet while signing.\n\n  <Aside>\n    Comments are on-chain and publicly visible in blockchain explorers. Do not include confidential data. Keep comments under 120 characters to avoid increased gas fees.\n  </Aside>\n</ParamField>\n\n<ParamField\n  body=\"commentToRecipient\"\n  type=\"string\"\n>\n  Note visible to the recipient after the transfer is received.\n\n  <Aside>\n    Comments are on-chain and publicly visible in blockchain explorers. Do not include confidential data. Keep comments under 120 characters to avoid increased gas fees.\n  </Aside>\n</ParamField>\n\n## Predefined asset constants\n\nBuilt-in constants can be used instead of raw addresses.\n\n```ts\nimport { createTonPayTransfer, TON, USDT } from \"@ton-pay/api\";\n\n// Toncoin transfer\nawait createTonPayTransfer(\n  {\n    amount: 1,\n    asset: TON, // same as \"TON\"\n    recipientAddr: \"<RECIPIENT_ADDRESS>\", // shortened example; replace with a full wallet address\n    senderAddr: \"<SENDER_ADDRESS>\",       // shortened example; replace with a full wallet address\n  },\n  {\n    chain: \"testnet\",\n    apiKey: \"<TONPAY_API_KEY>\", // optional\n  }\n);\n\n// USDT jetton transfer\nawait createTonPayTransfer(\n  {\n    amount: 25,\n    asset: USDT, // mainnet USDT jetton master address\n    recipientAddr: \"<RECIPIENT_ADDRESS>\", // shortened example; replace with a full wallet address\n    senderAddr: \"<SENDER_ADDRESS>\",       // shortened example; replace with a full wallet address\n  },\n  {\n    chain: \"testnet\",\n    apiKey: \"<TONPAY_API_KEY>\", // optional\n  }\n);\n```\n\n<Aside\n  type=\"danger\"\n  title=\"Mainnet address risk\"\n>\n  In `asset`, token constants such as `USDT` always reference mainnet jetton master addresses and are not affected by the `chain` option. Using them on testnet may send transactions to mainnet contracts.\n\n  For testnet, explicitly pass the correct testnet jetton master address instead of using token constants.\n</Aside>\n\nResponse:\n\n```ts\ntype CreateTonPayTransferResponse = {\n  message: {\n    address: string;\n    amount: string;\n    payload: string;\n  };\n  bodyBase64Hash: string;\n  reference: string;\n};\n```\n\n## Response fields\n\n<ResponseField\n  name=\"message\"\n  type=\"object\"\n  required\n>\n  Prebuilt TON Connect transaction message. Intended to be passed to `sendTransaction` as `messages: [message]`.\n</ResponseField>\n\n<ResponseField\n  name=\"bodyBase64Hash\"\n  type=\"string\"\n  required\n>\n  Base64 hash of the signed message body content (payload). Used with `getTonPayTransferByBodyHash`.\n</ResponseField>\n\n<ResponseField\n  name=\"reference\"\n  type=\"string\"\n  required\n>\n  Tracking reference string. Used with `getTonPayTransferByReference`.\n</ResponseField>\n\nThe SDK call returns a ready-to-send message along with identifiers for subsequent status lookups. Always persist tracking identifiers server-side before sending the transaction to the user.\n\n## Optional API key configuration\n\nThe TON Pay API key is optional but enables merchant features, including transaction visibility in the dashboard, webhook notifications, and centralized wallet management in the TON Pay Merchant Dashboard.\n\n### Obtain an optional API key\n\n<Steps>\n  <Step\n    title=\"Open the Merchant Dashboard\"\n  >\n    Open the TON Pay Merchant Dashboard and sign in to the merchant account.\n  </Step>\n\n  <Step\n    title=\"Open Developer settings\"\n  >\n    Navigate to <kbd>Developer</kbd> → <kbd>API Keys</kbd> sections to set up the optional API key.\n  </Step>\n\n  <Step\n    title=\"Generate or copy an optional API key\"\n  >\n    Generate a new API key (optional) or copy an existing one and store it securely.\n  </Step>\n</Steps>\n\n### Usage in code\n\n```typescript\nimport { createTonPayTransfer } from \"@ton-pay/api\";\n\nconst { message, reference, bodyBase64Hash } = await createTonPayTransfer(\n  {\n    amount: 10.5,\n    asset: \"TON\",\n    // recipientAddr is optional when API key is provided\n    // Will use merchant's default wallet from the Merchant Dashboard\n    senderAddr: userWalletAddress,\n  },\n  {\n    chain: \"testnet\",\n    apiKey: \"<TONPAY_API_KEY>\", // optional\n  }\n);\n```\n\n### Optional API key capabilities\n\n| Capability                            | With optional API key                                                                                             | Without API key                                                                       |\n| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |\n| Transaction visibility and monitoring | Transfers appear in the TON Pay Merchant Dashboard with status tracking and full transaction history.             | Transfers are processed on-chain but are not visible in the Merchant dashboard.       |\n| Webhook notifications                 | Real-time HTTP POST notifications are sent for completed and failed payments.                                     | No webhook notifications; payment status must be obtained through the manual polling. |\n| Receiving wallet management           | Receiving wallets are managed from the TON Pay Merchant Dashboard; addresses can be updated without code changes. | Receiving wallet addresses must be hard-coded in the application.                     |\n| `recipientAddr` handling              | Optional; when omitted, the merchant’s default wallet from the Merchant Dashboard is used automatically.          | Required for every transfer.                                                          |\n\nWith optional API key: `recipientAddr` is optional.\n\n```ts\nconst result = await createTonPayTransfer(\n  {\n    amount: 10,\n    asset: \"TON\",\n    senderAddr: \"<SENDER_ADDRESS>\",\n  },\n  {\n    chain: \"testnet\",\n    apiKey: \"<TONPAY_API_KEY>\", // optional\n  }\n);\n```\n\nWithout API key (the API key remains optional): `recipientAddr` is required.\n\n```ts\n// Works without API key (it is optional) - transaction processes normally\nconst result = await createTonPayTransfer(\n{\n  amount: 10,\n  asset: \"TON\",\n  recipientAddr: \"<RECIPIENT_ADDRESS>\",\n  senderAddr: \"<SENDER_ADDRESS>\",\n},\n{ chain: \"testnet\" } // No optional apiKey - transaction works but no dashboard features\n);\n```\n\n## Testnet configuration\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  Running tests on mainnet can result in irreversible loss of real TON. Always use `chain: \"testnet\"` and testnet wallet addresses during development. Verify the network before switching to mainnet.\n</Aside>\n\n### Set up testnet\n\n<Steps>\n  <Step\n    title=\"Set chain to testnet\"\n  >\n    Configure the `chain` option to `\"testnet\"` in the API calls:\n\n    ```typescript\n    const { message, reference, bodyBase64Hash } = await createTonPayTransfer(\n    {\n      amount: 5.0,\n      asset: \"TON\",\n      recipientAddr: \"<RECIPIENT_ADDRESS>\",\n      senderAddr: \"<SENDER_ADDRESS>\",\n    },\n    {\n      chain: \"testnet\", // Use testnet\n      apiKey: \"<TONPAY_API_KEY>\", // optional\n    }\n    );\n    ```\n  </Step>\n\n  <Step\n    title=\"Use testnet wallet addresses\"\n  >\n    Ensure all wallet addresses are valid [testnet addresses](/foundations/addresses/formats).\n  </Step>\n\n  <Step\n    title=\"Obtain testnet TON\"\n  >\n    - Use testnet wallet account: [Tonkeeper](/ecosystem/wallet-apps/tonkeeper) or other TON wallets.\n    - [Get testnet TON](/ecosystem/wallet-apps/get-coins) from a faucet to test transactions.\n  </Step>\n\n  <Step\n    title=\"Configure testnet jettons\"\n  >\n    If testing with jettons, use the correct testnet jetton master addresses; not mainnet addresses.\n\n    ```typescript\n    // Example: Testnet USDT (use actual testnet address)\n    await createTonPayTransfer(\n    {\n      amount: 10,\n      asset: \"<TESTNET_USDT_MASTER_ADDRESS>\", // Testnet jetton address\n      recipientAddr: \"<RECIPIENT_ADDRESS>\",\n      senderAddr: \"<SENDER_ADDRESS>\",\n    },\n    { chain: \"testnet\" }\n    );\n    ```\n  </Step>\n</Steps>\n\n### Configure environment\n\nUse environment variables to switch between mainnet and testnet:\n\n```typescript\n// .env.development\nTON_CHAIN=testnet\nMERCHANT_WALLET_ADDRESS=EQC...TESTNET_ADDRESS\n\n// .env.production\nTON_CHAIN=mainnet\nMERCHANT_WALLET_ADDRESS=EQC...MAINNET_ADDRESS\n```\n\n```typescript\n// In the application code\nconst { message, reference, bodyBase64Hash } = await createTonPayTransfer(\n  {\n    amount: orderAmount,\n    asset: \"TON\",\n    recipientAddr: \"<WALLET_ADDRESS>\",\n    senderAddr: \"<CUSTOMER_WALLET_ADDRESS>\",\n  },\n  {\n    chain: \"testnet\",\n    apiKey: \"<TONPAY_API_KEY>\", // optional\n  }\n);\n```\n\n### Verify testnet transactions\n\nVerify testnet transactions using testnet block [explorers](/ecosystem/explorers/overview):\n\n- [Testnet Tonviewer](https://testnet.tonviewer.com/)\n- [Testnet Tonscan](https://testnet.tonscan.org/)\n\n```typescript\n// Replace txHash with the actual transaction hash.\n// After transaction completes:\nconsole.log(`View on explorer: https://testnet.tonscan.org/tx/${txHash}`);\n```\n\n### Apply testing best practices\n\n- Test all payment outcomes on testnet, including success, failures, user rejections, and edge cases.\n- Verify webhook endpoint correctly processes testnet webhooks; payload structure matches mainnet.\n- Validate behavior across different amounts, including small, large, and fractional values.\n- Ensure `reference` and `bodyBase64Hash` are persisted and usable for status lookups.\n- Exercise error paths such as insufficient balance, invalid addresses, and network issues.\n"
  },
  {
    "path": "ecosystem/ton-pay/quick-start.mdx",
    "content": "---\ntitle: \"Quick start\"\nsidebarTitle: \"Quick start\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n## TON Connect manifest\n\nBefore installing and setting up the TON Pay SDK, the application must provide a TON Connect manifest, which is a JSON file that defines application metadata. Wallets use [this manifest](/ecosystem/ton-connect/manifest) to discover the application.\n\n## First payment\n\n<Steps>\n  <Step\n    title=\"Install necessary libraries\"\n  >\n    <Tabs>\n      <Tab\n        title=\"React\"\n      >\n        ```bash\n        # API\n        npm i @ton-pay/api\n\n        # UI (install separately from API)\n        npm i @ton-pay/ui-react @tonconnect/ui-react\n        ```\n      </Tab>\n\n      <Tab\n        title=\"Vanilla JS\"\n      >\n        ```bash\n        # API\n        npm i @ton-pay/api\n\n        # UI (install separately from API)\n        npm i @ton-pay/ui @tonconnect/ui\n        ```\n      </Tab>\n    </Tabs>\n\n    <Aside\n      type=\"tip\"\n    >\n      The UI package does not depend on the API. Install `@ton-pay/api` only when API helpers are required.\n    </Aside>\n  </Step>\n\n  <Step\n    title=\"Add TON Connect provider\"\n  >\n    TON Pay UI uses TON Connect UI for wallet communication.\n\n    The application must be wrapped with `TonConnectUIProvider` and configured with an absolute URL to the TON Connect manifest. Add `TonConnectUIProvider` at the root of the application.\n\n    ```tsx\n    import { TonConnectUIProvider } from '@tonconnect/ui-react';\n    import AppContent from \"./AppContent\";\n\n    export default function App() {\n      return (\n        <TonConnectUIProvider\n          manifestUrl=\"https://myapp.com/tonconnect-manifest.json\">\n          <AppContent />\n        </TonConnectUIProvider>\n      );\n    }\n    ```\n  </Step>\n\n  <Step\n    title=\"Add a payment button\"\n  >\n    Add a `TonPayButton` and provide a handler. The handler uses `useTonPay` to connect a wallet if needed, send a transaction through TON Connect, and track the transaction result.\n\n    - `TonPayButton` wraps wallet connect and disconnect UX and invokes the provided handler.\n    - `useTonPay` accepts an async message factory that receives `senderAddr` and returns `{ message }` along with any tracking fields to propagate.\n\n    The returned `{ message }` is a TON Connect transaction message. `useTonPay` forwards it to the wallet through TON Connect and initiates the transaction send; direct calls to the wallet SDK are not required.\n\n    ```tsx\n    import { TonPayButton, useTonPay } from \"@ton-pay/ui-react\";\n    import { useTonConnectUI } from \"@tonconnect/ui-react\";\n    import { createTonPayTransfer } from \"@ton-pay/api\";\n\n    export default function PayButton() {\n      const { pay } = useTonPay();\n      const [tonConnectUI] = useTonConnectUI();\n\n      async function createMessage(senderAddr: string) {\n        const { message, reference } = await createTonPayTransfer(\n          {\n            amount: 12.34,\n            asset: \"TON\",\n            recipientAddr: \"<WALLET_ADDRESS>\",\n            senderAddr,\n            commentToSender: \"<THE_ORDER>\",\n          },\n          {\n            chain: \"testnet\", // use \"mainnet\" for production\n            apiKey: \"<TONPAY_API_KEY>\" // optional\n          }\n        );\n        return { message, reference };\n      }\n\n      return (\n        <TonPayButton handlePay={() => pay(createMessage)} />\n      );\n    }\n    ```\n\n    <Aside\n      type=\"danger\"\n      title=\"Client-only processing is fragile\"\n    >\n      Users can close the tab before transaction results are persisted, which breaks tracking and confirmation logic. Build messages and track transactions on the [server side](/ecosystem/ton-pay/payment-integration/payments-react).\n    </Aside>\n\n    <AccordionGroup\n\n    >\n      <Accordion\n        title=\"Minimal server‑side flow quick sample\"\n      >\n        ```ts\n        // Backend: POST /api/create-payment\n        import { createTonPayTransfer } from \"@ton-pay/api\";\n        import { TON } from \"@ton-pay/api\";\n\n        app.post(\"/api/create-payment\", async (req, res) => {\n            const { productId, senderAddr } = req.body;\n\n            // Use the backend to create an order and calculate the amount using productId price\n            const amount = 12.23; // order amount\n            const orderId = 1; // ID of a new order\n\n            // 1) Create transfer + get tracking identifiers\n            const { message, reference, bodyBase64Hash } = await createTonPayTransfer(\n                { amount, asset: TON, recipientAddr: \"<WALLET_ADDRESS>\", senderAddr },\n                { chain: \"testnet\", apiKey: \"<TONPAY_API_KEY>\" } // API key is optional\n            );\n\n            // 2) Persist identifiers the DB (orderId, reference, bodyBase64Hash) immediately\n\n            // 3) Return only the message to the client\n            res.json({ message });\n        });\n\n        ```\n\n        ```typescript\n        // Frontend\n        import { TonPayButton, useTonPay } from \"@ton-pay/ui-react\";\n\n        export function PayOrder({ productId }: { productId: any }) {\n          const { pay } = useTonPay();\n\n          async function createMessage(senderAddr: string) {\n            const response = await fetch(\"/api/create-payment\", {\n              method: \"POST\",\n              headers: { \"Content-Type\": \"application/json\" },\n              body: JSON.stringify({ productId, senderAddr }),\n            });\n            const { message } = await response.json();\n            return { message };\n          }\n\n          return <TonPayButton handlePay={() => pay(createMessage)} />;\n        }\n        ```\n      </Accordion>\n    </AccordionGroup>\n\n    <Aside>\n      The TON Pay API key is optional. If available from the dashboard, pass it to `createTonPayTransfer` options to enable automatic tracking and webhook notifications.\n    </Aside>\n\n    <AccordionGroup\n\n    >\n      <Accordion\n        title=\"Loading state and result handling\"\n      >\n        This example shows a minimal loading state and how to surface the reference. If a transaction hash is available, an explorer link can be rendered.\n\n        ```tsx\n        import { useState } from \"react\";\n        import { TonPayButton, useTonPay } from \"@ton-pay/ui-react\";\n        import { createTonPayTransfer, getTonPayTransferByReference, type CompletedTonPayTransferInfo } from \"@ton-pay/api\";\n\n        export default function Checkout() {\n            const { pay } = useTonPay();\n            const [loading, setLoading] = useState(false);\n            const [reference, setReference] = useState<string | null>(null);\n            const [result, setResult] = useState<CompletedTonPayTransferInfo | null>(null);\n\n            const options = { chain: \"testnet\", apiKey: \"yourTonPayApiKey\" } as const; // API key is optional\n\n            async function createMessage(senderAddr: string) {\n              const { message, reference } = await createTonPayTransfer(\n                { amount: 12.34, asset: \"TON\", recipientAddr: \"EQC...yourWalletAddress\", senderAddr },\n                options\n              );\n              setReference(reference);\n              return { message, reference };\n            }\n\n            async function handlePay() {\n              setLoading(true);\n              try {\n                const { reference } = await pay(createMessage);\n                  // Poll status until success\n                  for (;;) {\n                    try {\n                      const t = await getTonPayTransferByReference(reference, options);\n                      if (t.status === \"success\") {\n                        setResult(t);\n                        break;\n                      }\n                    } catch {}\n                    await new Promise(r => setTimeout(r, 1000));\n                  }\n              } finally {\n                setLoading(false);\n              }\n            }\n\n            return (\n              <>\n                <TonPayButton handlePay={handlePay} isLoading={loading} />\n\n                {reference && !result && <div>Payment sent. Reference: {reference}</div>}\n                {result && <div>Payment successful! Tx hash: {result.txHash}</div>}\n                {/* If a transaction hash is available, render an explorer link:\n                      <ExplorerLink txHash={result?.txHash!} />\n                 */}\n              </>\n            );\n        }\n        ```\n\n        ```tsx\n        import { useTonWallet } from \"@tonconnect/ui-react\";\n        import { CHAIN } from \"@tonconnect/ui\";\n\n        function ExplorerLink({ txHash }: { txHash: string }) {\n            const wallet = useTonWallet();\n            const isTestnet = wallet?.account?.chain === CHAIN.TESTNET;\n            const tonviewer = isTestnet\n                ? `https://testnet.tonviewer.com/transaction/${txHash}`\n                : `https://tonviewer.com/transaction/${txHash}`;\n            const tonscan = isTestnet\n                ? `https://testnet.tonscan.org/tx/${txHash}`\n                : `https://tonscan.org/tx/${txHash}`;\n\n            return (\n                <div>\n                    <a href={tonviewer} target=\"_blank\" rel=\"noreferrer\">TonViewer</a>\n                    {\" • \"}\n                    <a href={tonscan} target=\"_blank\" rel=\"noreferrer\">Tonscan</a>\n                </div>\n            );\n        }\n        ```\n      </Accordion>\n    </AccordionGroup>\n  </Step>\n</Steps>\n\n## Full example\n\nThis minimal example scaffolds a React app, installs TON Pay dependencies, and renders a working button wired to TON Connect. Replace the manifest URL and `recipientAddr` with the necessary values.\n\n```bash\nnpx create-react-app my-app --template typescript\ncd my-app\nnpm i @ton-pay/api @ton-pay/ui-react @tonconnect/ui-react\n```\n\n```tsx\n// src/App.tsx\nimport { TonConnectUIProvider } from \"@tonconnect/ui-react\";\nimport { TonPayButton, useTonPay } from \"@ton-pay/ui-react\";\nimport { createTonPayTransfer } from \"@ton-pay/api\";\n\nfunction AppContent() {\n    const { pay } = useTonPay();\n\n    async function createMessage(senderAddr: string) {\n        const { message, reference } = await createTonPayTransfer(\n            {\n                amount: 12.34,\n                asset: \"TON\",\n                recipientAddr: \"<WALLET_ADDRESS>\",\n                senderAddr,\n                commentToSender: \"Order #123\",\n            },\n            {\n                chain: \"testnet\",\n                apiKey: \"<TONPAY_API_KEY>\" // optional\n            }\n        );\n        return { message, reference };\n    }\n\n    return (\n        <TonPayButton handlePay={() => pay(createMessage)} />\n    );\n}\n\nexport default function App() {\n    return (\n        <TonConnectUIProvider\n          manifestUrl=\"https://ton-connect.github.io/demo-dapp-with-wallet/tonconnect-manifest.json\"\n        >\n          <AppContent />\n        </TonConnectUIProvider>\n    );\n}\n```\n\n## See also\n\n- [Build a transfer](/ecosystem/ton-pay/payment-integration/transfer)\n- [Send payments using React](/ecosystem/ton-pay/payment-integration/payments-react)\n- [Webhooks](/ecosystem/ton-pay/webhooks)\n- [API reference](/ecosystem/ton-pay/api-reference)\n"
  },
  {
    "path": "ecosystem/ton-pay/ui-integration/button-js.mdx",
    "content": "---\ntitle: \"How to add a TON Pay button using JS\"\nsidebarTitle: \"Add TON Pay button JS\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\nimport { Image } from \"/snippets/image.jsx\";\n\nAdd a TON Pay button to a plain HTML/JavaScript page using the embed script or TON Pay client. The default button appearance is shown below.\n\n<div\n  style={{ display: \"flex\", justifyContent: \"center\" }}\n>\n  <Image\n    src=\"/resources/images/ton-pay/button.png\"\n    alt=\"TON Pay button\"\n    width={300}\n    noZoom={true}\n  />\n</div>\n\n## Installation\n\n<Steps>\n  <Step\n    title=\"Choose an installation method\"\n  >\n    Choose one of the installation methods:\n\n    1. npm\n\n       ```bash\n       npm install @ton-pay/ui @tonconnect/ui\n       ```\n\n    1. CDN: no installation needed\n\n       ```html\n       <!-- Use the unpkg CDN directly in HTML -->\n       <script src=\"https://unpkg.com/@ton-pay/ui@0.1.1/dist/ton-pay-embed.js\"></script>\n       ```\n\n    1. Local copy\n\n       After npm install, copy `node_modules/@ton-pay/ui/dist/ton-pay-embed.js` to a public assets folder. For example, the site's `public/` directory.\n       Then include it with a `<script src=\"...\">` tag in HTML.\n  </Step>\n\n  <Step\n    title=\"Create a TON Connect manifest\"\n  >\n    Create a [`tonconnect-manifest.json` file](/ecosystem/ton-connect/manifest) and host it on a public HTTPS URL.\n\n    ```json\n    {\n      \"url\": \"<APP_URL>\",\n      \"name\": \"<APP_NAME>\",\n      \"iconUrl\": \"<APP_ICON_URL>\"\n    }\n    ```\n\n    Placeholders:\n\n    - `<APP_URL>` – public HTTPS URL of the app.\n    - `<APP_NAME>` – display name shown in the wallet.\n    - `<APP_ICON_URL>` – public HTTPS URL of the app icon.\n  </Step>\n</Steps>\n\n## Option 1: embed script\n\nPlaceholders:\n\n- `<CONTAINER_ID>` – HTML element ID where the button is mounted.\n- `<CALLBACK_NAME>` – global function name invoked by the embed script.\n- `<RECIPIENT_ADDR>` – recipient wallet address.\n\n<Steps>\n  <Step\n    title=\"Add the container\"\n  >\n    ```html\n    <div id=\"<CONTAINER_ID>\"></div>\n    ```\n  </Step>\n\n  <Step\n    title=\"Add the embed script\"\n  >\n    ```html\n    <script src=\"https://unpkg.com/@ton-pay/ui@0.1.1/dist/ton-pay-embed.js?preset=gradient&variant=long&borderRadius=8&containerId=<CONTAINER_ID>&callback=<CALLBACK_NAME>\"></script>\n    ```\n  </Step>\n\n  <Step\n    title=\"Add the import map\"\n  >\n    ```html\n    <script type=\"importmap\">\n      {\n          \"imports\": {\n          \"@tonconnect/ui\": \"https://esm.sh/@tonconnect/ui@2.0.9\"\n        }\n      }\n    </script>\n    ```\n  </Step>\n\n  <Step\n    title=\"Create the payment handler\"\n  >\n    ```html\n    <script type=\"module\">\n        import { createTonPay } from \"https://unpkg.com/@ton-pay/ui@0.1.1/dist/ton-pay-vanilla.mjs\";\n\n        // Initialize TonPay client\n        const tonPay = createTonPay({\n          manifestUrl: \"/tonconnect-manifest.json\"\n        });\n\n        // Define payment handler\n        window[\"<CALLBACK_NAME>\"] = async () => {\n          try {\n            const result = await tonPay.pay(async (senderAddr) => {\n            // Build the payment message\n              const message = {\n                address: \"<RECIPIENT_ADDR>\",\n                amount: \"1000000\", // 0.001 TON in nanotons\n                payload: \"dGVzdA==\", // optional base64 payload\n              };\n              return { message };\n            });\n\n            console.log(\"Payment successful:\", result.txResult);\n            alert(\"Payment sent!\");\n          } catch (error) {\n            console.error(\"Payment failed:\", error);\n            alert(\"Payment failed: \" + error.message);\n      }\n    };\n    </script>\n    ```\n  </Step>\n</Steps>\n\n<Aside type=\"note\">\n  The `callback` parameter in the embed script must match the global function name in the handler.\n</Aside>\n\n## Option 2: use TON Pay client\n\nUse `createTonPay` for custom UI and payment flow control.\n\n<Steps>\n  <Step\n    title=\"Set up the HTML\"\n  >\n    ```html\n    <!DOCTYPE html>\n    <html>\n    <head>\n      <title>My TON Payment App</title>\n      <script type=\"importmap\">\n        {\n          \"imports\": {\n          \"@tonconnect/ui\": \"https://esm.sh/@tonconnect/ui@2.0.9\"\n        }\n        }\n      </script>\n    </head>\n    <body>\n      <button id=\"pay-btn\">Pay with TON</button>\n      <div id=\"status\"></div>\n    </body>\n    </html>\n    ```\n  </Step>\n\n  <Step\n    title=\"Import the TON Pay client and create an instance\"\n  >\n    ```html\n    <script type=\"module\">\n      import { createTonPay } from \"https://unpkg.com/@ton-pay/ui@0.1.1/dist/ton-pay-vanilla.mjs\";\n\n      const tonPay = createTonPay({\n        manifestUrl: \"/tonconnect-manifest.json\",\n        connectTimeoutMs: 300000 // 5 minutes (optional)\n    });\n    </script>\n    ```\n  </Step>\n\n  <Step\n    title=\"Implement the payment logic\"\n  >\n    ```html\n    <script type=\"module\">\n      const payButton = document.getElementById(\"pay-btn\");\n      const statusDiv = document.getElementById(\"status\");\n\n      payButton.addEventListener(\"click\", async () => {\n        payButton.disabled = true;\n        payButton.textContent = \"Processing...\";\n\n        try {\n          const result = await tonPay.pay(async (senderAddr) => {\n            statusDiv.textContent = `Sending from ${senderAddr}...`;\n\n            // Build payment message\n            const message = {\n              address: \"<RECIPIENT_ADDR>\",\n              amount: \"1000000\",\n            };\n\n            return { message };\n          });\n\n          statusDiv.textContent = \"Payment successful!\";\n          console.log(\"Transaction:\", result.txResult);\n        } catch (error) {\n          statusDiv.textContent = \"Payment failed: \" + error.message;\n          console.error(error);\n        } finally {\n          payButton.disabled = false;\n          payButton.textContent = \"Pay with TON\";\n        }\n      });\n    </script>\n    ```\n\n    <Aside\n      type=\"note\"\n    >\n      `createTonPay` opens TON Connect modal when `pay()` is called and no wallet is connected.\n    </Aside>\n  </Step>\n</Steps>\n\n## Create messages with createTonPayTransfer\n\nUse `createTonPayTransfer` to build a canonical payment message with tracking identifiers.\n\nCombine the snippets in this section into one HTML page.\n\n<Steps>\n  <Step\n    title=\"Add the API package script\"\n  >\n    ```html\n    <script type=\"module\">\n      import { createTonPayTransfer } from \"https://unpkg.com/@ton-pay/api@0.2.1/dist/index.mjs\";\n      import { createTonPay } from \"https://unpkg.com/@ton-pay/ui@0.1.1/dist/ton-pay-vanilla.mjs\";\n    </script>\n    ```\n  </Step>\n\n  <Step\n    title=\"Use the API in the payment handler\"\n  >\n    ```html\n    <script type=\"module\">\n      const tonPay = createTonPay({\n        manifestUrl: \"/tonconnect-manifest.json\"\n      });\n\n      window[\"<CALLBACK_NAME>\"] = async () => {\n        try {\n          const result = await tonPay.pay(async (senderAddr) => {\n            // Create payment with tracking\n            const { message, reference, bodyBase64Hash } =\n              await createTonPayTransfer(\n                {\n                  amount: 3.5,\n                  asset: \"TON\",\n                  recipientAddr: \"<RECIPIENT_ADDR>\",\n                  senderAddr,\n                  commentToSender: \"Order #12345\",\n                },\n                { chain: \"mainnet\" }\n              );\n\n            // Store tracking identifiers\n            console.log(\"Reference:\", reference);\n            console.log(\"Hash:\", bodyBase64Hash);\n\n            return { message, reference, bodyBase64Hash };\n          });\n\n          alert(\"Payment sent! Reference: \" + result.reference);\n        } catch (error) {\n          alert(\"Payment failed: \" + error.message);\n        }\n      };\n    </script>\n    ```\n  </Step>\n</Steps>\n\n<Aside type=\"note\">\n  Store `reference` and `bodyBase64Hash` to track payment status via the [webhooks guide](/ecosystem/ton-pay/webhooks).\n</Aside>\n\n## Embed script parameters\n\n| Parameter      | Type                        | Default           | Description                                                    |\n| -------------- | --------------------------- | ----------------- | -------------------------------------------------------------- |\n| `containerId`  | string                      | `\"ton-pay-btn\"`   | Target element ID where the button renders.                    |\n| `preset`       | `\"default\"` \\| `\"gradient\"` | -                 | Built-in theme preset.                                         |\n| `bgColor`      | string                      | `\"#0098EA\"`       | Background color in hex or CSS gradient. URL-encode the value. |\n| `textColor`    | string                      | `\"#FFFFFF\"`       | Text and icon color.                                           |\n| `variant`      | `\"long\"` \\| `\"short\"`       | `\"long\"`          | Button text variant.                                           |\n| `text`         | string                      | -                 | Custom button text. Overrides `variant`.                       |\n| `loadingText`  | string                      | `\"Processing...\"` | Text shown during loading.                                     |\n| `borderRadius` | number                      | `8`               | Border radius in pixels.                                       |\n| `fontFamily`   | string                      | `\"inherit\"`       | CSS font-family value.                                         |\n| `width`        | number                      | `300`             | Button width in pixels.                                        |\n| `height`       | number                      | `44`              | Button height in pixels.                                       |\n| `showMenu`     | boolean                     | `true`            | Show dropdown menu with wallet actions.                        |\n| `callback`     | string                      | -                 | Global function name called on click.                          |\n\n### Examples\n\n<CodeGroup>\n  ```html Default blue button\n  <script src=\"https://unpkg.com/@ton-pay/ui@0.1.1/dist/ton-pay-embed.js?preset=default&variant=long&borderRadius=8&containerId=btn-1&callback=handlePayment\"></script>\n  ```\n\n  ```html Gradient button\n  <script src=\"https://unpkg.com/@ton-pay/ui@0.1.1/dist/ton-pay-embed.js?preset=gradient&variant=short&borderRadius=12&containerId=btn-2&callback=handlePayment\"></script>\n  ```\n\n  ```html Custom colors\n  <script src=\"https://unpkg.com/@ton-pay/ui@0.1.1/dist/ton-pay-embed.js?bgColor=%23000000&textColor=%23FFFFFF&borderRadius=99&containerId=btn-3&callback=handlePayment\"></script>\n  ```\n\n  ```html Custom size\n  <script src=\"https://unpkg.com/@ton-pay/ui@0.1.1/dist/ton-pay-embed.js?preset=gradient&width=400&height=56&containerId=btn-4&callback=handlePayment\"></script>\n  ```\n</CodeGroup>\n\n<Aside\n  type=\"caution\"\n>\n  URL-encode special characters in parameters. For example, `#` becomes `%23` in color values.\n</Aside>\n\n## TonPayEmbed API\n\nThe embed script exposes a global `TonPayEmbed` object for programmatic control.\n\n### `TonPayEmbed.mount(config)`\n\nUpdate button configuration dynamically.\n\n```js\nTonPayEmbed.mount({\n  preset: \"gradient\",\n  variant: \"short\",\n  borderRadius: 12,\n  width: 350\n});\n```\n\n### `TonPayEmbed.setCallback(functionName)`\n\nChange the callback function.\n\n```js\nTonPayEmbed.setCallback(\"newPaymentHandler\");\n```\n\n### `TonPayEmbed.setAddress(address)`\n\nUpdate the displayed wallet address in the menu.\n\n```js\nTonPayEmbed.setAddress(\"<RECIPIENT_ADDR>\");\n```\n\n### `TonPayEmbed.click()`\n\nTrigger a button click programmatically.\n\n```js\nTonPayEmbed.click();\n```\n\n### Example: dynamic configuration\n\n```html\n<div id=\"<CONTAINER_ID>\"></div>\n<button onclick=\"changeTheme()\">Change Theme</button>\n\n<script src=\"https://unpkg.com/@ton-pay/ui@0.1.1/dist/ton-pay-embed.js?containerId=<CONTAINER_ID>&callback=<CALLBACK_NAME>\"></script>\n\n<script>\n  function changeTheme() {\n    TonPayEmbed.mount({\n      preset: \"gradient\",\n      variant: \"short\",\n      borderRadius: 99\n    });\n  }\n</script>\n```\n\n## TonPay client API\n\n`createTonPay` returns a client for wallet connection and payments.\n\n### Properties\n\n- `address: string | null`\n\n  Current wallet address.\n\n  ```js\n  const tonPay = createTonPay({ manifestUrl: \"/tonconnect-manifest.json\" });\n  console.log(tonPay.address); // null or wallet address\n  ```\n\n### Methods\n\n- `waitForWalletConnection(): Promise<string>`\n\n  Wait for a wallet connection and open the modal if needed.\n\n  ```js\n  try {\n    const address = await tonPay.waitForWalletConnection();\n    console.log(\"Connected:\", address);\n  } catch (error) {\n    console.error(\"Connection failed:\", error);\n  }\n  ```\n\n- `pay(getMessage): Promise<PayResult>`\n\n  Execute a payment transaction.\n\n  ```js\n  const result = await tonPay.pay(async (senderAddr) => {\n    const message = {\n      address: \"<RECIPIENT_ADDR>\",\n      amount: \"1000000\"\n    };\n    return { message };\n  });\n\n  console.log(result.txResult);\n  ```\n\n- `disconnect(): Promise<void>`\n\n  Disconnect the current wallet.\n\n  ```js\n  await tonPay.disconnect();\n  ```\n\n## Framework integration\n\n### WordPress\n\n```html\n<!-- Add to the theme footer or a custom HTML block -->\n<div id=\"<CONTAINER_ID>\"></div>\n<script type=\"importmap\">\n{\n  \"imports\": {\n    \"@tonconnect/ui\": \"https://esm.sh/@tonconnect/ui@2.0.9\"\n  }\n}\n</script>\n<script type=\"module\">\n  import { createTonPay } from \"https://unpkg.com/@ton-pay/ui@0.1.1/dist/ton-pay-vanilla.mjs\";\n  const tonPay = createTonPay({ manifestUrl: \"/tonconnect-manifest.json\" });\n  window[\"<CALLBACK_NAME>\"] = async () => { /* payment handler */ };\n</script>\n<script src=\"https://unpkg.com/@ton-pay/ui@0.1.1/dist/ton-pay-embed.js?containerId=<CONTAINER_ID>&callback=<CALLBACK_NAME>\"></script>\n```\n\n### Plain HTML/CSS/JS\n\nUse the complete example of the embed script in a single HTML file.\n\n### Build tools: Webpack and Vite\n\n```js\nimport { createTonPay } from \"@ton-pay/ui/vanilla\";\n\nconst tonPay = createTonPay({\n  manifestUrl: \"/tonconnect-manifest.json\"\n});\n\n// Use tonPay.pay() in event handlers\n```\n\n## Best practices\n\n- Wrap payment calls in try-catch blocks and display clear error messages.\n- Update the UI during payment processing to prevent repeated clicks.\n- Check amounts, addresses, and input before calling the payment function.\n- Use HTTPS in production. TON Connect requires HTTPS for the manifest URL and callbacks.\n- Save `reference` and `bodyBase64Hash` from `createTonPayTransfer` to track payments via webhooks.\n- Test with testnet first and handle error scenarios before going live.\n\n## Troubleshooting\n\n<AccordionGroup>\n  <Accordion\n    title=\"If the button does not render\"\n  >\n    1. Verify that `containerId` matches the target div ID\n    1. Check the browser console for errors\n    1. Ensure the script loads after the container div\n    1. Verify that the script URL is correct and accessible\n  </Accordion>\n\n  <Accordion\n    title=\"If the callback is not invoked\"\n  >\n    1. Ensure the callback function is defined on the `window` object\n    1. Verify that the function name matches the `callback` parameter exactly\n    1. Define the callback before the embed script runs\n  </Accordion>\n\n  <Accordion\n    title=\"If import map erros occur\"\n  >\n    1. Add the import map before any module scripts\n    1. Verify that the `@tonconnect/ui` version is compatible\n    1. Check that the import map syntax is valid\n  </Accordion>\n\n  <Accordion\n    title=\"If CORS errors occur\"\n  >\n    1. Serve the manifest from the same domain or enable CORS\n    1. Use HTTPS in production\n    1. Verify that CDN resources are accessible\n  </Accordion>\n</AccordionGroup>\n"
  },
  {
    "path": "ecosystem/ton-pay/ui-integration/button-react.mdx",
    "content": "---\ntitle: \"How to add a TON Pay button using React\"\nsidebarTitle: \"Add TON Pay button React\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\nimport { Image } from \"/snippets/image.jsx\";\n\n`TonPayButton` is a ready-to-use React component that handles wallet connection and payment flow with configurable styling for TON payments. The default button appearance is shown below.\n\n<div\n  style={{ display: \"flex\", justifyContent: \"center\" }}\n>\n  <Image\n    src=\"/resources/images/ton-pay/button.png\"\n    alt=\"TON Pay button\"\n    width={300}\n    noZoom={true}\n  />\n</div>\n\n## Install packages\n\n<Steps>\n  <Step\n    title=\"Install necessary libraries\"\n  >\n    ```bash\n    npm install @ton-pay/ui-react @ton-pay/api @tonconnect/ui-react\n    ```\n  </Step>\n\n  <Step\n    title=\"Create a TON Connect manifest\"\n  >\n    Create [`tonconnect-manifest.json`](/ecosystem/ton-connect/manifest) in the app public directory:\n\n    ```json\n    {\n      \"url\": \"<APP_URL>\",\n      \"name\": \"<APP_NAME>\",\n      \"iconUrl\": \"<APP_ICON_URL>\"\n    }\n    ```\n  </Step>\n\n  <Step\n    title=\"Wrap the app with the provider\"\n  >\n    Wrap the root component with `TonConnectUIProvider`.\n\n    ```tsx\n    import { TonConnectUIProvider } from \"@tonconnect/ui-react\";\n\n    function App() {\n      return (\n        <TonConnectUIProvider manifestUrl=\"/tonconnect-manifest.json\">\n          <AppRoutes />\n        </TonConnectUIProvider>\n      );\n    }\n    ```\n  </Step>\n</Steps>\n\n<Aside\n  type=\"note\"\n  title=\"HTTPS required\"\n>\n  To receive webhooks in production, ensure corresponding endpoints use HTTPS. Regular HTTP endpoints would be ignored by TON Pay.\n</Aside>\n\n## Option 1: use useTonPay hook\n\nThe `useTonPay` hook simplifies wallet connection and transaction handling. Use it for a direct integration path.\n\n<Steps>\n  <Step\n    title=\"Import required dependencies\"\n  >\n    ```tsx\n    import { TonPayButton } from \"@ton-pay/ui-react\";\n    import { useTonPay } from \"@ton-pay/ui-react\";\n    import { createTonPayTransfer } from \"@ton-pay/api\";\n    import { useState } from \"react\";\n    ```\n  </Step>\n\n  <Step\n    title=\"Set up the component\"\n  >\n    ```tsx\n    function PaymentComponent() {\n      const { pay } = useTonPay();\n      const [isLoading, setIsLoading] = useState(false);\n    ```\n  </Step>\n\n  <Step\n    title=\"Create the payment handler\"\n  >\n    ```tsx\n      const handlePayment = async () => {\n        setIsLoading(true);\n        try {\n          const { txResult, reference, bodyBase64Hash } = await pay(\n            async (senderAddr: string) => {\n              // Build the payment message\n              const { message, reference, bodyBase64Hash } =\n                await createTonPayTransfer(\n                  {\n                    amount: 3.5,\n                    asset: \"TON\",\n                    recipientAddr: \"<RECIPIENT_ADDRESS>\",\n                    senderAddr,\n                    commentToSender: \"Order #12345\",\n                  },\n                  { chain: \"testnet\" } // change to \"mainnet\" only after full validation\n                );\n              return { message, reference, bodyBase64Hash };\n            }\n          );\n\n          console.log(\"Payment sent:\", txResult);\n          console.log(\"Tracking:\", reference, bodyBase64Hash);\n        } catch (error) {\n          console.error(\"Payment failed:\", error);\n        } finally {\n          setIsLoading(false);\n        }\n      };\n    ```\n\n    <Aside\n      type=\"note\"\n    >\n      The `useTonPay` hook automatically checks wallet connection. If the user is not connected, it opens the TON Connect modal first.\n    </Aside>\n  </Step>\n\n  <Step\n    title=\"Render the button\"\n  >\n    ```tsx\n      return (\n        <TonPayButton\n          handlePay={handlePayment}\n          isLoading={isLoading}\n          loadingText=\"Processing payment...\"\n        />\n      );\n    }\n    ```\n  </Step>\n</Steps>\n\n## Option 2: use TON Connect directly\n\nUse TON Connect hooks directly when full control over the connection flow is required.\n\n<Steps>\n  <Step\n    title=\"Import TON Connect hooks\"\n  >\n    ```tsx\n    import { TonPayButton } from \"@ton-pay/ui-react\";\n    import {\n      useTonAddress,\n      useTonConnectModal,\n      useTonConnectUI,\n    } from \"@tonconnect/ui-react\";\n    import { createTonPayTransfer } from \"@ton-pay/api\";\n    import { useState } from \"react\";\n    ```\n  </Step>\n\n  <Step\n    title=\"Set up hooks and state\"\n  >\n    ```tsx\n    function DirectPaymentComponent() {\n      const address = useTonAddress(true);\n      const modal = useTonConnectModal();\n      const [tonConnectUI] = useTonConnectUI();\n      const [isLoading, setIsLoading] = useState(false);\n    ```\n  </Step>\n\n  <Step\n    title=\"Create the payment handler\"\n  >\n    ```tsx\n      const handlePay = async () => {\n        // Check if wallet is connected\n        if (!address) {\n          modal.open();\n          return;\n        }\n\n        setIsLoading(true);\n        try {\n          // Create the payment message\n          const { message } = await createTonPayTransfer(\n            {\n              amount: 1.2,\n              asset: \"TON\",\n              recipientAddr: \"<RECIPIENT_ADDRESS>\",\n              senderAddr: \"<SENDER_ADDRESS>\",\n              commentToSender: \"Invoice #5012\",\n            },\n            { chain: \"mainnet\" } // can be changed to testnet\n          );\n\n          // Send the transaction\n          await tonConnectUI.sendTransaction({\n            messages: [message],\n            validUntil: Math.floor(Date.now() / 1000) + 5 * 60,\n            from: address,\n          });\n\n          console.log(\"Payment completed!\");\n        } catch (error) {\n          console.error(\"Payment failed:\", error);\n        } finally {\n          setIsLoading(false);\n        }\n      };\n    ```\n  </Step>\n\n  <Step\n    title=\"Render the button\"\n  >\n    ```tsx\n      return <TonPayButton handlePay={handlePay} isLoading={isLoading} />;\n    }\n    ```\n  </Step>\n</Steps>\n\n## TonPayButton props\n\nAll props are optional except `handlePay`.\n\n| Prop                    | Type                        | Default           | Description                                                                                                     |\n| ----------------------- | --------------------------- | ----------------- | --------------------------------------------------------------------------------------------------------------- |\n| `handlePay`             | `() => Promise<void>`       | required          | Payment handler called when the button is selected.                                                             |\n| `isLoading`             | `boolean`                   | `false`           | Shows a loading spinner and disables the button.                                                                |\n| `variant`               | `\"long\"` \\| `\"short\"`       | `\"long\"`          | Button text variant: \"Pay with TON Pay\" (long) or \"TON Pay\" (short).                                            |\n| `preset`                | `\"default\"` \\| `\"gradient\"` | -                 | Predefined theme preset; overrides `bgColor` and `textColor`.                                                   |\n| `onError`               | `(error: unknown) => void`  | -                 | Called when `handlePay` throws. A built-in error popup is also shown unless `showErrorNotification` is `false`. |\n| `showErrorNotification` | `boolean`                   | `true`            | Shows the built-in error notification popup on error.                                                           |\n| `bgColor`               | `string`                    | `\"#0098EA\"`       | Background color (hex) or CSS gradient.                                                                         |\n| `textColor`             | `string`                    | `\"#FFFFFF\"`       | Text and icon color (hex).                                                                                      |\n| `borderRadius`          | `number` \\| `string`        | `8`               | Border radius in pixels or CSS value.                                                                           |\n| `fontFamily`            | `string`                    | `\"inherit\"`       | Font family for button text.                                                                                    |\n| `width`                 | `number` \\| `string`        | `300`             | Button width in pixels or CSS value.                                                                            |\n| `height`                | `number` \\| `string`        | `44`              | Button height in pixels or CSS value.                                                                           |\n| `loadingText`           | `string`                    | `\"Processing...\"` | Text shown during loading state.                                                                                |\n| `showMenu`              | `boolean`                   | `true`            | Shows the dropdown menu with wallet actions.                                                                    |\n| `disabled`              | `boolean`                   | `false`           | Disables the button.                                                                                            |\n| `style`                 | `Record<string, any>`       | -                 | Additional inline styles.                                                                                       |\n| `className`             | `string`                    | -                 | Additional CSS class name.                                                                                      |\n\n## Customization\n\n### Button variants\n\n[Use `useTonPay`](/ecosystem/ton-pay/ui-integration/button-react#option-1:-using-usetonpay-hook-recommended) for a complete example.\n\n<CodeGroup>\n  ```tsx Long variant (default)\n  <TonPayButton\n    variant=\"long\"\n    handlePay={handlePay}\n  />\n  // Displays: \"Pay with [TON icon] Pay\"\n  ```\n\n  ```tsx Short variant\n  <TonPayButton\n    variant=\"short\"\n    handlePay={handlePay}\n  />\n  // Displays: \"[TON icon] Pay\"\n  ```\n</CodeGroup>\n\n### Presets\n\n[Use `useTonPay`](/ecosystem/ton-pay/ui-integration/button-react#option-1:-using-usetonpay-hook-recommended) for a complete example.\n\n<CodeGroup>\n  ```tsx Default preset\n  <TonPayButton\n    preset=\"default\"\n    handlePay={handlePay}\n  />\n  // Blue theme: #0098EA\n  ```\n\n  ```tsx Gradient preset\n  <TonPayButton\n    preset=\"gradient\"\n    handlePay={handlePay}\n  />\n  // Gradient: #2A82EB to #0355CF\n  ```\n</CodeGroup>\n\n### Custom styling\n\n[Use `useTonPay`](/ecosystem/ton-pay/ui-integration/button-react#option-1:-using-usetonpay-hook-recommended) for a complete example.\n\n```tsx\n<TonPayButton\n  bgColor=\"#7C3AED\"\n  textColor=\"#FFFFFF\"\n  borderRadius={12}\n  width={400}\n  height={56}\n  fontFamily=\"'Inter', sans-serif\"\n  handlePay={handlePay}\n/>\n```\n\nCSS gradients can be used in `bgColor`. For example: `\"linear-gradient(135deg, #667eea 0%, #764ba2 100%)\"`.\n\n### Button states\n\n[Use `useTonPay`](/ecosystem/ton-pay/ui-integration/button-react#option-1:-using-usetonpay-hook-recommended) for a complete example.\n\n```tsx\n<TonPayButton\n  handlePay={handlePay}\n  isLoading={isLoading}\n  loadingText=\"Processing payment...\"\n  disabled={cartTotal === 0}\n  showMenu={false}\n/>\n```\n\n## Advanced patterns\n\n### Error handling\n\n```tsx\nimport { TonPayButton, useTonPay } from \"@ton-pay/ui-react\";\nimport { createTonPayTransfer } from \"@ton-pay/api\";\nimport { useState } from \"react\";\n\nfunction PaymentWithErrors() {\n  const { pay } = useTonPay();\n  const [isLoading, setIsLoading] = useState(false);\n  const [error, setError] = useState<string | null>(null);\n\n  const handlePayment = async () => {\n    setIsLoading(true);\n    setError(null);\n\n    try {\n      await pay(async (senderAddr: string) => {\n        const { message, reference, bodyBase64Hash } =\n          await createTonPayTransfer(\n            {\n              amount: 5.0,\n              asset: \"TON\",\n              recipientAddr: \"<RECIPIENT_ADDR>\",\n              senderAddr,\n            },\n            { chain: \"testnet\" }\n          );\n        return { message, reference, bodyBase64Hash };\n      });\n      // Show success message...\n    } catch (err: any) {\n      setError(err.message || \"Payment failed. Please try again.\");\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  return (\n    <div>\n      <TonPayButton handlePay={handlePayment} isLoading={isLoading} />\n      {error && <div style={{ color: \"red\" }}>{error}</div>}\n    </div>\n  );\n}\n```\n\n#### Built-in error notification\n\n`TonPayButton` catches errors thrown from `handlePay` and shows a notification pop-up with the error message.\n\nIf a custom error UI is also rendered, both messages appear. Use either the built-in pop-up or a custom UI, but not both.\n\n#### Add a custom error handler\n\nUse `onError` for logging or custom notifications. Set `showErrorNotification={false}` to disable the built-in pop-up.\n\n```tsx\nimport { TonPayButton, useTonPay } from \"@ton-pay/ui-react\";\nimport { createTonPayTransfer } from \"@ton-pay/api\";\nimport { useState } from \"react\";\n\nfunction PaymentWithCustomHandler() {\n  const { pay } = useTonPay();\n  const [isLoading, setIsLoading] = useState(false);\n\n  const handlePayment = async () => {\n    setIsLoading(true);\n    try {\n      await pay(async (senderAddr: string) => {\n        const { message } = await createTonPayTransfer(\n          {\n            amount: 3,\n            asset: \"TON\",\n            recipientAddr: \"<RECIPIENT_ADDR>\",\n            senderAddr,\n          },\n          { chain: \"testnet\" }\n        );\n        return { message };\n      });\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  return (\n    <TonPayButton\n      handlePay={handlePayment}\n      isLoading={isLoading}\n      onError={(error) => {\n        analytics.track(\"payment_error\", {\n          message: (error as any)?.message ?? String(error),\n        });\n        // The toast/notification can go here\n      }}\n      showErrorNotification={false}\n    />\n  );\n}\n```\n\nReplace the pop-up with a custom UI. Catch errors inside `handlePay` and do not rethrow. When `handlePay` resolves, the button does not show the default pop-up.\n\n```tsx\nimport { TonPayButton, useTonPay } from \"@ton-pay/ui-react\";\nimport { createTonPayTransfer } from \"@ton-pay/api\";\nimport { useState } from \"react\";\n\nfunction PaymentWithOwnUI() {\n  const { pay } = useTonPay();\n  const [isLoading, setIsLoading] = useState(false);\n  const [error, setError] = useState<string | null>(null);\n\n  const handlePayment = async () => {\n    setIsLoading(true);\n    setError(null);\n    try {\n      await pay(async (senderAddr: string) => {\n        const { message } = await createTonPayTransfer(\n          {\n            amount: 2.5,\n            asset: \"TON\",\n            recipientAddr: \"<RECIPIENT_ADDR>\",\n            senderAddr,\n          },\n          { chain: \"testnet\" }\n        );\n        return { message };\n      });\n    } catch (e: any) {\n      // Handle the error here and DO NOT rethrow\n      setError(e?.message ?? \"Payment failed. Please try again.\");\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  return (\n    <div>\n      <TonPayButton handlePay={handlePayment} isLoading={isLoading} />\n      {error && <div style={{ color: \"red\" }}>{error}</div>}\n    </div>\n  );\n}\n```\n\n## Server-side payment creation\n\nCreate the payment message on a backend to store tracking identifiers and validate parameters before sending.\n\n<Steps>\n  <Step\n    title=\"Create a backend endpoint\"\n  >\n    Build an endpoint that returns the message for `TonPayButton`.\n\n    ```ts\n    // /api/create-payment\n    app.post(\"/api/create-payment\", async (req, res) => {\n      const { amount, senderAddr, orderId } = req.body;\n\n      const { message, reference, bodyBase64Hash } = await createTonPayTransfer(\n        {\n          amount,\n          asset: \"TON\",\n          recipientAddr: \"<RECIPIENT_ADDR>\",\n          senderAddr,\n          commentToSender: `Order ${orderId}`,\n        },\n        { chain: \"testnet\" }\n      );\n\n      // Store reference and bodyBase64Hash in the database\n      await db.savePayment({ orderId, reference, bodyBase64Hash });\n\n      res.json({ message });\n    });\n    ```\n  </Step>\n\n  <Step\n    title=\"Call the endpoint from the frontend\"\n  >\n    ```tsx\n    import { TonPayButton, useTonPay } from \"@ton-pay/ui-react\";\n    import { useState } from \"react\";\n\n    function ServerSidePayment() {\n      const { pay } = useTonPay();\n      const [isLoading, setIsLoading] = useState(false);\n\n      const handlePayment = async () => {\n        setIsLoading(true);\n        try {\n          await pay(async (senderAddr: string) => {\n            const response = await fetch(\"/api/create-payment\", {\n              method: \"POST\",\n              headers: { \"Content-Type\": \"application/json\" },\n              body: JSON.stringify({\n                amount: 10.5,\n                senderAddr,\n                orderId: \"<ORDER_ID>\",\n              }),\n            });\n            const data = await response.json();\n            return { message: data.message };\n          });\n        } finally {\n          setIsLoading(false);\n        }\n      };\n\n      return <TonPayButton handlePay={handlePayment} isLoading={isLoading} />;\n    }\n    ```\n  </Step>\n</Steps>\n\n<Aside type=\"tip\">\n  Creating payments server-side allows storing tracking identifiers and validating payment parameters before sending.\n</Aside>\n\n## Test the integration\n\nRun the interactive button showcase to test variants and styling.\n\n```bash\nnpm run test:button-react\n# or\nbun test:button-react\n```\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  Running tests on mainnet can result in irreversible loss of real TON. Always use `chain: \"testnet\"` and testnet wallet addresses during development. Verify the network before switching to mainnet.\n</Aside>\n\n## Best practices\n\n- Wrap payment calls in try-catch blocks and display user-friendly error messages. Network issues and cancellations are common.\n- Set `isLoading={true}` during payment processing to prevent double submissions and provide visual feedback.\n- Verify cart totals, user input, and business rules before calling the payment handler.\n- Use `chain: \"testnet\"` during development. Switch to `\"mainnet\"` only after validation.\n- Save `reference` and `bodyBase64Hash` to track payment status using [webhooks](/ecosystem/ton-pay/webhooks).\n- After successful payment, show a confirmation message, redirect to a success page, or update the UI.\n"
  },
  {
    "path": "ecosystem/ton-pay/webhooks.mdx",
    "content": "---\ntitle: \"Webhooks\"\nsidebarTitle: \"Webhooks\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nTON Pay uses webhooks to notify applications in real-time about transfer events.\n\n## How webhooks work\n\n1. A transfer is completed on-chain and indexed by TON Pay.\n1. TON Pay generates a webhook payload and signs it using [HMAC-SHA256](https://en.wikipedia.org/wiki/HMAC) and the optional API key when it is configured.\n1. TON Pay sends a `POST` request to the webhook URL with the signed payload. The request includes the `X-TonPay-Signature` header for verification.\n1. Verify the signature and process the event payload. Return a `2xx` status code to acknowledge receipt.\n\n<Aside\n  type=\"note\"\n  title=\"Important\"\n>\n  The webhook URL must be publicly accessible and accept `POST` requests from the TON Pay backend.\n</Aside>\n\n## Configure the webhook URL\n\nConfigure the endpoint in TON Pay Merchant Dashboard.\n\n1. Open the [TON Pay Merchant Dashboard](https://tonpay.tech/dashboard) and sign in to the merchant account.\n1. Navigate to the <kbd>Developer</kbd> → <kbd>Webhooks</kbd> sections.\n1. Enter the webhook URL. In production, the endpoint must use HTTPS. For example, `https://thedomain.com/webhooks/tonpay`\n1. Save the configuration and use the test feature to verify delivery.\n\n<Aside\n  type=\"note\"\n  title=\"Built-in test feature\"\n>\n  Use a built-in test feature in the dashboard to send sample webhooks before going live.\n</Aside>\n\n## Webhook payload\n\n### Event types\n\n```ts\nimport {\n  type WebhookPayload,\n  type WebhookEventType,\n  type TransferCompletedWebhookPayload,\n  type TransferRefundedWebhookPayload, // Coming soon\n} from \"@ton-pay/api\";\n\n// Event types: \"transfer.completed\" | \"transfer.refunded\" (Coming Soon)\ntype WebhookEventType = \"transfer.completed\" | \"transfer.refunded\";\n\n// Union type for all webhook payloads\ntype WebhookPayload =\n  | TransferCompletedWebhookPayload\n  | TransferRefundedWebhookPayload; // Coming soon\n```\n\n### `transfer.completed`\n\n```ts\ninterface TransferCompletedWebhookPayload {\n  event: \"transfer.completed\";\n  timestamp: string;\n  data: CompletedTonPayTransferInfo; // See API reference\n}\n```\n\n<Aside\n  type=\"tip\"\n  title=\"Type safety\"\n>\n  Webhook types are exported from [`@ton-pay/api`](/ecosystem/ton-pay/api-reference). Use `WebhookPayload` for type safety in webhook handlers.\n</Aside>\n\n### Example payloads\n\nSuccessful transfer:\n\n```json\n{\n  \"event\": \"transfer.completed\",\n  \"timestamp\": \"2024-01-15T14:30:00.000Z\",\n  \"data\": {\n    \"amount\": \"10.5\",\n    \"rawAmount\": \"10500000000\",\n    \"senderAddr\": \"<SENDER_ADDR>\",\n    \"recipientAddr\": \"<RECIPIENT_ADDR>\",\n    \"asset\": \"TON\",\n    \"assetTicker\": \"TON\",\n    \"status\": \"success\",\n    \"reference\": \"<REFERENCE>\",\n    \"bodyBase64Hash\": \"<BODY_BASE64_HASH>\",\n    \"txHash\": \"<TX_HASH>\",\n    \"traceId\": \"<TRACE_ID>\",\n    \"commentToSender\": \"Thanks for the purchase\",\n    \"commentToRecipient\": \"Payment for order #1234\",\n    \"date\": \"2024-01-15T14:30:00.000Z\"\n  }\n}\n```\n\nFailed transfer:\n\n```json\n{\n  \"event\": \"transfer.completed\",\n  \"timestamp\": \"2024-01-15T14:35:00.000Z\",\n  \"data\": {\n    \"amount\": \"10.5\",\n    \"rawAmount\": \"10500000000\",\n    \"senderAddr\": \"<SENDER_ADDR>\",\n    \"recipientAddr\": \"<RECIPIENT_ADDR>\",\n    \"asset\": \"TON\",\n    \"assetTicker\": \"TON\",\n    \"status\": \"failed\",\n    \"reference\": \"<REFERENCE>\",\n    \"bodyBase64Hash\": \"<BODY_BASE64_HASH>\",\n    \"txHash\": \"<TX_HASH>\",\n    \"traceId\": \"<TRACE_ID>\",\n    \"commentToSender\": \"Transaction failed\",\n    \"commentToRecipient\": \"Payment for order #5678\",\n    \"date\": \"2024-01-15T14:35:00.000Z\",\n    \"errorCode\": 36,\n    \"errorMessage\": \"Not enough TON\"\n  }\n}\n```\n\nPlaceholders:\n\n- `<SENDER_ADDR>` - sender wallet address.\n- `<RECIPIENT_ADDR>` - recipient wallet address.\n- `<REFERENCE>` - transfer reference returned by `createTonPayTransfer`.\n- `<BODY_BASE64_HASH>` - Base64 hash of the transfer body.\n- `<TX_HASH>` - transaction hash.\n- `<TRACE_ID>` - trace identifier.\n\n## Payload fields\n\n<ResponseField\n  name=\"event\"\n  type=\"string\"\n  required\n>\n  Event type. `transfer.completed` indicates that on-chain processing is finished. The transfer may be successful or failed; check `data.status` for the result.\n</ResponseField>\n\n<ResponseField\n  name=\"timestamp\"\n  type=\"string\"\n  required\n>\n  [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) timestamp indicating when the event occurred.\n</ResponseField>\n\n<ResponseField\n  name=\"data\"\n  type=\"object\"\n  required\n>\n  Transfer details such as amount, addresses, and the transaction hash.\n\n  <Expandable\n    title=\"data properties\"\n  >\n    <ResponseField\n      name=\"amount\"\n      type=\"string\"\n      required\n    >\n      Human-readable payment amount with decimals. For example, 10.5.\n    </ResponseField>\n\n    <ResponseField\n      name=\"rawAmount\"\n      type=\"string\"\n      required\n    >\n      Amount in base units; nanotons for TON.\n    </ResponseField>\n\n    <ResponseField\n      name=\"senderAddr\"\n      type=\"string\"\n      required\n    >\n      Sender wallet address on TON blockchain.\n    </ResponseField>\n\n    <ResponseField\n      name=\"recipientAddr\"\n      type=\"string\"\n      required\n    >\n      Recipient wallet address on TON blockchain.\n    </ResponseField>\n\n    <ResponseField\n      name=\"asset\"\n      type=\"string\"\n      required\n    >\n      Asset identifier. Use \"TON\" for TON coin or a jetton master address for tokens.\n    </ResponseField>\n\n    <ResponseField\n      name=\"assetTicker\"\n      type=\"string\"\n    >\n      Human-readable asset ticker. For example, TON or USDT.\n    </ResponseField>\n\n    <ResponseField\n      name=\"status\"\n      type=\"string\"\n      required\n    >\n      Transfer status: `success` or `failed`. Process only `success` status. Log `failed` status for investigation.\n    </ResponseField>\n\n    <ResponseField\n      name=\"reference\"\n      type=\"string\"\n      required\n    >\n      Unique transfer reference. Use this to match the webhook with the internal order or transaction.\n    </ResponseField>\n\n    <ResponseField\n      name=\"bodyBase64Hash\"\n      type=\"string\"\n      required\n    >\n      Base64 hash of the transfer body. Use for advanced verification.\n    </ResponseField>\n\n    <ResponseField\n      name=\"txHash\"\n      type=\"string\"\n      required\n    >\n      Transaction hash on-chain. Use this to verify the transaction if needed.\n    </ResponseField>\n\n    <ResponseField\n      name=\"traceId\"\n      type=\"string\"\n      required\n    >\n      Trace ID for tracking the transaction across systems.\n    </ResponseField>\n\n    <ResponseField\n      name=\"commentToSender\"\n      type=\"string\"\n    >\n      Optional note visible to the sender during signing.\n    </ResponseField>\n\n    <ResponseField\n      name=\"commentToRecipient\"\n      type=\"string\"\n    >\n      Optional note visible to the recipient. Use for order IDs or invoice numbers.\n    </ResponseField>\n\n    <ResponseField\n      name=\"date\"\n      type=\"string\"\n      required\n    >\n      ISO 8601 timestamp of the transfer completion.\n    </ResponseField>\n\n    <ResponseField\n      name=\"errorCode\"\n      type=\"number\"\n    >\n      Error code if the transfer failed.\n    </ResponseField>\n\n    <ResponseField\n      name=\"errorMessage\"\n      type=\"string\"\n    >\n      Error message if the transfer failed.\n    </ResponseField>\n  </Expandable>\n</ResponseField>\n\n## Verify webhook signatures\n\nEvery webhook request includes an `X-TonPay-Signature` header containing an HMAC-SHA256 signature. Verify this signature to ensure the request comes from TON Pay.\n\n<Aside\n  type=\"danger\"\n  title=\"Security requirement\"\n>\n  In production, webhook requests must be verified using the signature. Without verification, requests can be forged.\n</Aside>\n\n```ts\nimport { verifySignature, type WebhookPayload } from \"@ton-pay/api\";\n\napp.post(\"/webhook\", (req, res) => {\n  const signature = req.headers[\"x-tonpay-signature\"];\n\n  if (!verifySignature(req.body, signature, process.env.TONPAY_API_SECRET)) {\n    return res.status(401).json({ error: \"Invalid signature\" });\n  }\n\n  const webhookData: WebhookPayload = req.body;\n\n  // Process the webhook in application-specific logic.\n  res.status(200).json({ received: true });\n});\n```\n\n<Aside\n  type=\"note\"\n  title=\"Important\"\n>\n  The webhook API secret is available in the Merchant Dashboard under <kbd>Developer</kbd> → <kbd>Webhooks</kbd>. Store it securely and use it only on the server.\n</Aside>\n\n## Validate webhook requests\n\nValidate fields against the expected transaction data before marking an order as paid.\n\n<Aside type=\"note\">\n  Return a `2xx` response for validation failures, such as an amount mismatch or an unknown order, to prevent retries. Log these issues for further investigation.\n</Aside>\n\n1. Verify the `X-TonPay-Signature` header and reject invalid requests.\n\n   ```ts\n   if (!verifySignature(payload, signature, apiKey)) { // apiKey is optional and used when configured\n     return res.status(401).json({ error: \"Invalid signature\" });\n   }\n   ```\n\n1. Verify the event type.\n   ```ts\n   if (webhookData.event !== \"transfer.completed\") {\n     return res.status(400).json({ error: \"Unexpected event type\" });\n   }\n   ```\n\n1. Check that the reference matches a transaction created earlier.\n\n   ```ts\n   const order = await db.getOrderByReference(webhookData.data.reference);\n   if (!order) {\n     console.error(\"Order not found:\", webhookData.data.reference);\n     return res.status(200).json({ received: true }); // Acknowledge to prevent retry\n   }\n   ```\n\n1. Verify the amount matches the expected payment amount.\n\n   ```ts\n   if (parseFloat(webhookData.data.amount) !== order.expectedAmount) {\n     console.error(\"Amount mismatch:\", {\n       expected: order.expectedAmount,\n       received: webhookData.data.amount,\n     });\n     return res.status(200).json({ received: true }); // Acknowledge to prevent retry\n   }\n   ```\n\n1. Verify the payment currency or token.\n\n   ```ts\n   if (webhookData.data.asset !== order.expectedAsset) {\n     console.error(\"Asset mismatch:\", {\n       expected: order.expectedAsset,\n       received: webhookData.data.asset,\n     });\n     return res.status(200).json({ received: true }); // Acknowledge to prevent retry\n   }\n   ```\n\n1. Check status and process only successful transfers.\n\n   ```ts\n   if (webhookData.data.status !== \"success\") {\n     await db.markOrderAsFailed(order.id, webhookData.data.txHash);\n     return res.status(200).json({ received: true }); // Acknowledge to prevent retry\n   }\n   ```\n\n1. Prevent duplicate processing using the reference.\n\n   ```ts\n   if (order.status === \"completed\") {\n     return res.status(200).json({ received: true, duplicate: true });\n   }\n   ```\n\n### Complete validation example\n\n```ts expandable\nimport { verifySignature, type WebhookPayload } from \"@ton-pay/api\";\n\napp.post(\"/webhooks/tonpay\", async (req, res) => {\n  try {\n    // 1. Verify signature\n    const signature = req.headers[\"x-tonpay-signature\"] as string;\n\n    if (!verifySignature(req.body, signature, process.env.TONPAY_API_SECRET!)) {\n      console.error(\"Invalid webhook signature\");\n      return res.status(401).json({ error: \"Invalid signature\" });\n    }\n\n    const webhookData: WebhookPayload = req.body;\n\n    // 2. Verify event type\n    if (webhookData.event !== \"transfer.completed\") {\n      return res.status(400).json({ error: \"Unexpected event type\" });\n    }\n\n    // 3. Find the order\n    const order = await db.getOrderByReference(webhookData.data.reference);\n    if (!order) {\n      console.error(\"Order not found:\", webhookData.data.reference);\n      return res.status(200).json({ received: true }); // Acknowledge to prevent retry\n    }\n\n    // 4. Check for duplicate processing\n    if (order.status === \"completed\") {\n      console.log(\"Order already processed:\", order.id);\n      return res.status(200).json({ received: true, duplicate: true });\n    }\n\n    // 5. Verify transfer status\n    if (webhookData.data.status !== \"success\") {\n      await db.updateOrder(order.id, {\n        status: \"failed\",\n        txHash: webhookData.data.txHash,\n        failureReason: \"Transfer failed on blockchain\",\n      });\n      return res.status(200).json({ received: true });\n    }\n\n    // 6. CRITICAL: Verify amount\n    const receivedAmount = parseFloat(webhookData.data.amount);\n    if (receivedAmount !== order.expectedAmount) {\n      console.error(\"Amount mismatch:\", {\n        orderId: order.id,\n        expected: order.expectedAmount,\n        received: receivedAmount,\n      });\n      return res.status(200).json({ received: true }); // Acknowledge to prevent retry\n    }\n\n    // 7. CRITICAL: Verify asset/currency\n    const expectedAsset = order.expectedAsset || \"TON\";\n    if (webhookData.data.asset !== expectedAsset) {\n      console.error(\"Asset mismatch:\", {\n        orderId: order.id,\n        expected: expectedAsset,\n        received: webhookData.data.asset,\n      });\n      return res.status(200).json({ received: true }); // Acknowledge to prevent retry\n    }\n\n    // All validations passed - acknowledge receipt\n    res.status(200).json({ received: true });\n\n    // Process order asynchronously\n    await processOrderCompletion(order.id, {\n      txHash: webhookData.data.txHash,\n      senderAddr: webhookData.data.senderAddr,\n      completedAt: webhookData.timestamp,\n    });\n  } catch (error) {\n    console.error(\"Webhook processing error:\", error);\n    return res.status(500).json({ error: \"Internal server error\" });\n  }\n});\n```\n\n## Retry behavior\n\nTON Pay retries failed webhook deliveries.\n\n<CardGroup cols={2}>\n  <Card\n    title=\"Retry attempts\"\n    icon=\"rotate\"\n  >\n    Up to 3 automatic retries with exponential backoff.\n  </Card>\n\n  <Card\n    title=\"Retry delays\"\n    icon=\"clock\"\n  >\n    1s → 5s → 15s\n  </Card>\n</CardGroup>\n\n### Delivery outcomes\n\n- Success responses: `2xx`. No retry; webhook marked as delivered.\n- All other responses: `4xx`, `5xx`, or network errors. Automatic retry with exponential backoff.\n\n<Aside type=\"note\">\n  Return a `2xx` status code only after validation and any required order updates complete, including cases where validation fails but the event is logged and marked as handled. Returning success before validation finishes can result in missed or duplicated processing.\n</Aside>\n\n## Best practices\n\n- Validate the following fields before marking an order as paid:\n\n  - Signature: authentication;\n  - Reference: the transaction exists in the system;\n  - Amount: the expected payment is matched;\n  - Asset: correct currency or token;\n  - Wallet ID: correct receiving wallet;\n  - Status: the transaction succeeded.\n\n  ```ts\n  // Avoid: trust without verification\n  await markOrderAsPaid(webhook.data.reference);\n\n  // Prefer: validate and then process\n  if (isValidWebhook(webhook, order)) {\n    await markOrderAsPaid(order.id);\n  }\n  ```\n\n- Return `2xx` only after successful validation, then process the webhook to avoid timeouts.\n\n  ```ts\n  app.post('/webhook', async (req, res) => {\n  // Validate signature first\n  if (!verifyWebhookSignature(...)) {\n    return res.status(401).json({ error: 'Invalid signature' });\n  }\n\n  // Quick validations\n  if (!isValidWebhook(req.body)) {\n    return res.status(400).json({ error: 'Invalid webhook data' });\n  }\n\n  // Acknowledge after validation\n  res.status(200).json({ received: true });\n\n  // Process in background\n  processWebhookAsync(req.body).catch(console.error);\n  });\n  ```\n\n- Implement idempotency. Webhooks may be delivered more than once. Use the `reference` field to prevent duplicate processing.\n\n  ```ts\n  async function processWebhook(payload: WebhookPayload) {\n    const order = await db.getOrder(payload.reference);\n\n    // Check if already processed\n    if (order.status === 'completed') {\n        console.log('Order already completed:', payload.reference);\n        return; // Skip processing\n    }\n\n    // Process and update status atomically\n    await db.transaction(async (tx) => {\n        await tx.updateOrder(order.id, { status: 'completed' });\n        await tx.createPaymentRecord(payload);\n    });\n  }\n  ```\n\n- Log all webhook attempts. Log each request for debugging and security auditing.\n\n  ```ts\n  await logger.info(\"Webhook received\", {\n    timestamp: new Date(),\n    signature: req.headers[\"x-tonpay-signature\"],\n    reference: payload.data.reference,\n    event: payload.event,\n    amount: payload.data.amount,\n    asset: payload.data.asset,\n    status: payload.data.status,\n    validationResult: validationResult,\n  });\n  ```\n\n- To receive webhooks in production, ensure corresponding endpoints use HTTPS. Regular HTTP endpoints would be ignored by TON Pay.\n\n- Monitor delivery failures. Set up alerts and review webhook delivery logs in the Merchant Dashboard\n\n- Store transaction hashes. Save `txHash` to support on-chain verification for disputes.\n\n  ```ts\n  await db.updateOrder(order.id, {\n    status: \"completed\",\n    txHash: webhookData.data.txHash,\n    senderAddr: webhookData.data.senderAddr,\n    completedAt: webhookData.timestamp,\n  });\n  ```\n\n## Troubleshooting\n\n<Accordion\n  title=\"If webhooks are not received\"\n>\n  1. Verify the webhook URL configured in the Merchant Dashboard.\n  1. Ensure the endpoint is publicly reachable and not blocked by a firewall.\n  1. Use the dashboard test feature to send a sample webhook.\n  1. Review webhook attempt logs in the Merchant Dashboard.\n  1. Ensure the endpoint returns a `2xx` status code for valid requests.\n  1. Ensure the endpoint responds within 10 seconds to avoid timeouts.\n</Accordion>\n\n<Accordion\n  title=\"If signature verification fails\"\n>\n  1. Use the optional API key from the Merchant Dashboard at <kbd>Developer</kbd> → <kbd>API</kbd> when webhook signing is configured.\n  1. Compute the HMAC over the raw JSON string.\n  1. Do not modify the request body before verification.\n  1. Verify the header name is `x-tonpay-signature` in lowercase.\n  1. Use the `HMAC-SHA256` algorithm.\n  1. Ensure the signature value starts with `sha256=`.\n</Accordion>\n\n<Accordion\n  title=\"If amount or asset mismatch, possible causes include\"\n>\n  1. Wrong order lookup or reference mapping.\n  1. Price changed after order creation.\n  1. Currency mismatch between order and transfer.\n  1. Potential attack or spoofed request.\n</Accordion>\n\n<Accordion\n  title=\"If duplicate webhook processing\"\n>\n  1. Implement idempotency using the `reference` field.\n  1. Use database transactions to prevent race conditions.\n  1. Check order status before processing.\n\n  ```ts\n  if (order.status === \"completed\") {\n    return; // Already processed\n  }\n  ```\n</Accordion>\n\n<Accordion\n  title=\"If timeout errors occur\"\n>\n  1. Respond within 10 seconds.\n  1. Process webhooks asynchronously after quick validation.\n  1. Return `2xx` after validation passes.\n</Accordion>\n\n## Next steps\n\n<CardGroup cols={2}>\n  <Card\n    title=\"Build a transfer\"\n    icon=\"paper-plane\"\n    href=\"/ecosystem/ton-pay/payment-integration/transfer\"\n  >\n    Create a TON Pay transfer message.\n  </Card>\n\n  <Card\n    title=\"Check status and retrieve info\"\n    icon=\"magnifying-glass\"\n    href=\"/ecosystem/ton-pay/payment-integration/status-info\"\n  >\n    Query transfer status and details.\n  </Card>\n</CardGroup>\n"
  },
  {
    "path": "ecosystem/wallet-apps/addresses-workflow.mdx",
    "content": "---\ntitle: \"Addresses workflow\"\n---\n\nTo understand this article, it is necessary to periodically refer to [account status page](/foundations/status).\n\nAt the moment, TON wallets work with [addresses](/foundations/addresses/formats) as follows:\n\nWhen receiving:\n\n1. Wallets display the user's address in a [user-friendly](/foundations/addresses/formats) bounceable or non-bounceable form.\n\nWhen sending:\n\n1. A user sends a message with funds and, possibly, a comment to the destination's wallet address in one of the user-friendly formats through the wallet application.\n1. The wallet app checks the validity of the destination address representation - its length, valid characters, prefix, and checksum. If the address is not valid, then an alert is shown and the sending operation is not performed.\n1. If the address has a testnet flag, and the wallet app works with the mainnet network, then an alert is shown and the sending operation is not performed.\n1. The wallet app reads the bounceable flag from the address.\n1. The wallet app checks the destination address. If it has the `uninitialized` status, the app force-sets the `bounce` field of the sending message to `false` and ignores the bounceable/non-bounceable flag from the address representation.\n1. If the destination is not `uninitialized`, then the wallet app uses the bounceable/non-bounceable flag from the address representation for the `bounce` field of the sending message.\n"
  },
  {
    "path": "ecosystem/wallet-apps/deep-links.mdx",
    "content": "---\ntitle: \"Deep links\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nDeep links allow to seamlessly direct users from a dApp back to a meaningful location within a TON wallet and invoke corresponding actions.\n\nIssue wallet invoices using deep links. See [transaction link formats](#explorers-links) for popular explorers.\n\n## TON Connect invoices\n\n```bash\ntc://<TON_CONNECT_LINK_BODY>\n```\n\nBest for dApps that require multiple transactions within a session or a persistent wallet connection.\n\n**Advantages**\n\n- Permanent communication channel with the wallet.\n- Users only scan a QR code once.\n- Can track transaction confirmation via the returned BoC.\n- Ready-made SDKs and UI kits for various platforms.\n\n**Disadvantages**\n\n- If only one payment is needed, users must connect the wallet and confirm the transaction.\n- More complex integration than a `ton://` link.\n\nExplore [TON Connect](/ecosystem/ton-connect/overview).\n\n## Deep links invoices\n\n<Aside\n  type=\"caution\"\n>\n  The TON link `ton://` is less preferred in the ecosystem, but may be useful for simple and tiny one-time payment flow.\n</Aside>\n\n```bash\nton://<LINK-BODY>\n```\n\n**Advantages**\n\n- Easy integration.\n- No need to connect a wallet.\n\n**Disadvantages**\n\n- Users must scan a new QR code for each payment.\n- Cannot track if the user signed the transaction.\n- No information about the user’s address.\n- Requires workarounds for platforms where links are not clickable (e.g., Telegram Desktop bots).\n\nThe `ton://` scheme is part of the broader TON blockchain standard, enabling interoperability across different TON-based wallets and services.\n\n#### Example workflows\n\n- Quick payments: Integrate payment requests directly from your website, allowing users to complete transactions with a single tap using `ton://` transfer links.\n- In-app transactions: Use deep links to facilitate seamless transfers between users within your application.\n- Link to specific transfers: Provide support or history review by linking directly to specific transactions or transfers.\n\n### TON transfer\n\nOpens the pre-filled Send screen and prompts the user to enter the missing data.\n\n```bash Transfer scheme\nton://transfer/<ADDRESS>?amount=<AMOUNT>&text=<TEXT>\n```\n\n| Parameter   | Description                                                 | Required |\n| ----------- | ----------------------------------------------------------- | -------- |\n| `<ADDRESS>` | The recipient's TON address.                                | required |\n| `<AMOUNT>`  | The amount of TON to send, in nanotons.                     | optional |\n| `<TEXT>`    | A URL-encoded UTF-8 text message to attach to the transfer. | optional |\n\n#### TON transfer to address\n\n```bash scheme\nton://transfer/<ADDRESS>\n```\n\n```bash example\nton://transfer/UQDYzZmfsrGzhObKJUw4gzdeIxEai3jAFbiGKGwxvxHinf4K\n```\n\n#### TON transfer with amount\n\n```bash scheme\nton://transfer/<ADDRESS>?amount=<AMOUNT>\n```\n\n```bash example\nton://transfer/UQDYzZmfsrGzhObKJUw4gzdeIxEai3jAFbiGKGwxvxHinf4K?amount=5000000\n\n```\n\n#### TON transfer with text comment\n\n```bash scheme\nton://transfer/<ADDRESS>?text=<TEXT>\n```\n\n```bash example\nton://transfer/UQDYzZmfsrGzhObKJUw4gzdeIxEai3jAFbiGKGwxvxHinf4K?text=hello\n```\n\n#### TON Transfer with amount and text comment\n\n```bash scheme\nton://transfer/<ADDRESS>?amount=<AMOUNT>&text=<TEXT>\n```\n\n```bash example\nton://transfer/UQDYzZmfsrGzhObKJUw4gzdeIxEai3jAFbiGKGwxvxHinf4K?amount=5000000&text=hello\n```\n\n### Transfer with expiry timestamp\n\nOpens the Send screen with an expiry timestamp for the transaction.\n\n```bash Scheme with timestamp\nton://transfer/<ADDRESS>?amount=<AMOUNT>&text=<TEXT>&exp=<EXPIRY_TIMESTAMP>\n```\n\n| Parameter            | Description                                                 | Required |\n| -------------------- | ----------------------------------------------------------- | -------- |\n| `<ADDRESS>`          | The recipient's TON address.                                | required |\n| `<AMOUNT>`           | The amount of TON to send, in nanotons.                     | optional |\n| `<TEXT>`             | A URL-encoded UTF-8 text message to attach to the transfer. | optional |\n| `<EXPIRY_TIMESTAMP>` | Expiry timestamp in seconds since the Unix epoch.           | optional |\n\nThe `exp` parameter, like other parameters, must be included when constructing the message to ensure the blockchain rejects transactions with an expired exp.\n\n#### TON transfer with expiry timestamp\n\n```bash scheme tranfser with expiry\nton://transfer/<ADDRESS>?amount=<AMOUNT>&text=<TEXT>&exp=<EXPIRY_TIMESTAMP>\n```\n\n```bash example transfer with expiry\nton://transfer/EQD2NmD_lH5f5u1Kj3KfGyTvhZSX0Eg6qp2a5IQUKXxOG21n?amount=100000&text=test&exp=2147483647\n```\n\n### Jetton transfer\n\nOpens the Send screen with a jetton transfer. [Jetton](/standard/tokens/jettons/overview) is a standard for TON assets, like USDT, USDC and e.t.c.\n\n```bash Scheme\nton://transfer/<ADDRESS>?jetton=<JETTON_ADDRESS>&amount=<AMOUNT>&text=<TEXT>\n```\n\n| Parameter            | Description                                                 | Required |\n| -------------------- | ----------------------------------------------------------- | -------- |\n| `<ADDRESS>`          | The recipient's TON wallet address.                         | required |\n| `<JETTON_ADDRESS>`   | The jetton master address.                                  | required |\n| `<AMOUNT>`           | The amount of jettons to send.                              | optional |\n| `<TEXT>`             | A URL-encoded UTF-8 text message to attach to the transfer. | optional |\n| `<EXPIRY_TIMESTAMP>` | Expiry timestamp in seconds since the Unix epoch.           | optional |\n\n<Aside type=\"tip\">\n  One whole Jetton for `<AMOUNT>` is defined by\n\n  - [`decimals`](/standard/tokens/metadata#decimals) the number of fractional digits\n  - `unit` that represents the smallest indivisible amount of the token (similar to satoshi in Bitcoin).\n\n  <Accordion\n    title=\"Read more...\"\n  >\n    $$\n    \\text{One whole Jetton} = unit \\times 10^{decimal}\n    $$\n\n    For example, a USDT Jetton on TON defines decimals = 6.\n    This means:\n\n    $$\n    1\\ \\text{USDT} = 1{,}000{,}000\\ \\text{smallest units}\n    $$\n\n    Or, in general form:\n\n    $$\n    \\text{One whole USDT} = unit \\times 10^{6}\n    $$\n\n    Typically Jetton on TON defines with decimals = 9, for example, DUST jetton.\n    This means:\n\n    $$\n    1\\ \\text{DUST} = 1{,}000{,}000{,}000\\ \\text{smallest units}\n    $$\n\n    Or, in general form:\n\n    $$\n    \\text{One whole DUST} = unit \\times 10^{9}\n    $$\n  </Accordion>\n</Aside>\n\n#### Transfer default jetton\n\nTypically, jetton decimals in amount are equal 9 and evaluation same as for Toncoin.\n\n```bash scheme\nton://transfer/<ADDRESS>?jetton=<JETTON_ADDRESS>&amount=<AMOUNT>&text=<TEXT>\n```\n\n```bash example transfer 0.005 DUST\nton://transfer/UQDYzZmfsrGzhObKJUw4gzdeIxEai3jAFbiGKGwxvxHinf4K?jetton=EQBlqsm144Dq6SjbPI4jjZvA1hqTIP3CvHovbIfW_t-SCALE&amount=5000000&text=hello\n```\n\n#### Transfer USDT\n\nWhile Toncoin requires nine decimal places and 1 Toncoin equals 1 billion ($10^9$) nanoToncoin, USDT only uses six decimal places. This means that 1 USDT unit stands for 1 million ($10^6$) microUSDT units. The `AMOUNT` below requires the microUSDT format.\n\n```bash scheme\nton://transfer/<ADDRESS>?jetton=<JETTON_ADDRESS>&amount=<AMOUNT>&text=<TEXT>\n```\n\n```bash example transfer 0.005 USDT\nton://transfer/UQDYzZmfsrGzhObKJUw4gzdeIxEai3jAFbiGKGwxvxHinf4K?jetton=EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs&amount=5000&text=hello\n```\n\n### Transfer with binary data\n\nOpens the emulation screen or screen with alert about blind signing transactions with amount and destination.\n\n```bash scheme\nton://transfer/<ADDRESS>?amount=<AMOUNT>&bin=<BINARY_DATA>\n```\n\n| Parameter       | Description                                                                    | Required |\n| --------------- | ------------------------------------------------------------------------------ | -------- |\n| `<ADDRESS>`     | The recipient's TON address.                                                   | required |\n| `<AMOUNT>`      | The amount of TON to send, in nanotons.                                        | optional |\n| `<BINARY_DATA>` | A URL-encoded base64 BoC which will be attached as a body to internal message. | optional |\n\n```bash example transfer with binary data\nton://transfer/UQDYzZmfsrGzhObKJUw4gzdeIxEai3jAFbiGKGwxvxHinf4K?amount=5000000&bin=te6cckECBQEAARUAAUWIAMEY4jHsfgXgPZLLJhtH/oPEOBKZZb6Y4/RJaJnbXc4GDAEBnBSf8D7P51eitphXHiTNAS6WXVDOgcxIxFWf7JICcG9ooFRNCDzTZbHg0mlW6782P8huKd5wzYK3huSVDMGTrQgpqaMXaMF9SAAAACsAAwIBaGIAV+9GxkYnezSj7VSw9vtlmc5RJ5lsyyItoKd5rFDpJZUgL68IAAAAAAAAAAAAAAAAAAEDAaFfzD0Ug3czLfk9/4aAArAmxHNbYrurO/IYyD89+mJZ/XDMnkMemHy/nTsrzYDwAYIxxGPY/AvAeyWWTDaP/QeIcCUyy30xx+iS0TO2u5wMIDgEACIAAAAAUmVmI05PTmQxZ0pCUK4fW14=\n```\n\n## Wallet-specific invoices\n\nUse wallet‑specific links to create simple jetton and Toncoin transfers. The syntax is usually similar to `ton://transfer` links, but always check each wallet’s documentation.\n\nExample: transferring 1 USDT to `EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs`:\n\n```bash Tonkeeper mobile link\nhttps://app.tonkeeper.com/transfer/saint.ton?amount=1000000&jetton=EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs\n```\n\n```bash Tonkeeper web link\nhttps://app.tonkeeper.com/transfer/saint.ton?amount=1000000&jetton=EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs\n```\n\n```bash MyTonWallet\nhttps://my.tt/transfer/UQDYzZmfsrGzhObKJUw4gzdeIxEai3jAFbiGKGwxvxHinf4K?amount=1000000&jetton=EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs\n```\n\nFind more wallet-specific features in the documentation:\n\n- Tonkeeper - [`docs.tonconsole.com`](https://docs.tonconsole.com/tonkeeper/deep-linking)\n- MyTonWallet - [`help.mytonwallet.io`](https://help.mytonwallet.io/intro/key-features/deeplinks-in-mytonwallet)\n\n## Explorers links\n\nTo generate a transaction link, the service must obtain the account address, logical time (lt), and transaction hash by calling the [`getTransactions`](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get) method. Using these values, [Tonviewer](https://tonviewer.com), [Tonscan](https://tonscan.org), and [Toncoin Explorer](https://explorer.toncoin.org/) render the transaction page according to the following formats respectively:\n\n- [Tonviewer links](#tonviewer)\n- [Tonscan links](#tonscan)\n- [Toncoin Explorer links](#toncoin-explorer)\n\n### Tonviewer\n\n#### Mainnet\n\n```bash Tonviewer Mainnet link\nhttps://tonviewer.com/transaction/<hash as hex>\n```\n\n```bash Tonviewer Mainnet link example\nhttps://tonviewer.com/transaction/aee8d185a0c8f73c787bf1872ee9659ac53ce11a90b16b384856a7821eff8c29\n```\n\n#### Testnet\n\n```bash Tonviewer Testnet link\nhttps://testnet.tonviewer.com/transaction/<hash as hex>\n```\n\n```bash Tonviewer Testnet short link example\nhttps://testnet.tonviewer.com/transaction/61ef8fac43edf408fcc041aa8afaec14ac2c4f68faafe6eb18c50a921697d2f6\n```\n\n### Tonscan\n\n#### Mainnet\n\n```bash Tonscan Mainnet link\nhttps://tonscan.org/tx/<lt as int>:<hash as base64url>:<account address>\n```\n\n```bash Tonscan Mainnet link example\nhttps://tonscan.org/tx/63333243000002:rujRhaDI9zx4e_GHLullmsU84RqQsWs4SFangh7_jCk:Ef8zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM0vF\n```\n\n#### Testnet\n\n```bash Tonscan Testnet link\nhttps://testnet.tonscan.org/tx/<lt as int>:<hash as base64url>:<account address>\n```\n\n```bash Tonviewer Testnet link example\nhttps://testnet.tonscan.org/tx/40988257000002:Ye-PrEPt9Aj8wEGqivrsFKwsT2j6r-brGMUKkhaX0vY:kf8zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM_BP\n```\n\n### Toncoin explorer\n\n#### Mainnet\n\n```bash Toncoin Mainnet link\nhttps://explorer.toncoin.org/transaction?account=<account address>&lt=<lt as int>&hash=<transaction uppercase hex>\n```\n\n```bash Toncoin Mainnet link example\nhttps://explorer.toncoin.org/transaction?account=Ef8zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM0vF&lt=63333243000002&hash=AEE8D185A0C8F73C787BF1872EE9659AC53CE11A90B16B384856A7821EFF8C29\n```\n\n#### Testnet\n\n```bash Toncoin Testnet link\nhttps://test-explorer.toncoin.org/transaction?account=<account address>&lt=<lt as int>&hash=<transaction uppercase hex>\n```\n\n```bash Toncoin Testnet link example\nhttps://test-explorer.toncoin.org/transaction?account=Ef8zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM0vF&lt=40988257000002&hash=61EF8FAC43EDF408FCC041AA8AFAEC14AC2C4F68FAAFE6EB18C50A921697D2F6\n```\n"
  },
  {
    "path": "ecosystem/wallet-apps/get-coins.mdx",
    "content": "---\ntitle: \"How to get coins on testnet\"\nsidebarTitle: \"Get coins on testnet\"\n---\n\nimport { Image } from '/snippets/image.jsx';\nimport { Aside } from '/snippets/aside.jsx';\n\nTestnet coins are used for development and testing on the TON testnet. To obtain testnet Toncoin, a testnet wallet is required.\n\nDepending on the required amount of Toncoin, choose one of the following options:\n\n- For regular requests of 2 TON per hour, use Telegram [Testgiver TON bot](#use-testgiver-ton-bot).\n- For larger allocations of up to 5,000 TON, submit a [request form](#use-request-form).\n\n## Use Testgiver TON Bot\n\n1. Download [Telegram](https://telegram.org/) and create an account.\n\n1. Open [`@testgiver_ton_bot`](https://t.me/testgiver_ton_bot) in a browser and click <kbd>Open Telegram</kbd>.\n\n   <Image\n     src=\"/resources/images/fund-wallet/open-telegram-light.png\"\n     darkSrc=\"/resources/images/fund-wallet/open-telegram-dark.png\"\n     width={608}\n     height={342}\n     alt=\"Open Telegram prompt\"\n   />\n\n1. Once the bot opens, click <kbd>Start</kbd> to initiate the session.\n\n   <Image\n     src=\"/resources/images/fund-wallet/start-bot-light.png\"\n     darkSrc=\"/resources/images/fund-wallet/start-bot-dark.png\"\n     width={608}\n     height={342}\n     alt=\"Start bot screen\"\n   />\n\n1. After the `/start` command is sent, the bot displays a welcome message. Click <kbd>Get 2 TON in testnet</kbd> to request test coins.\n\n   <Image\n     src=\"/resources/images/fund-wallet/bot-welcome-light.png\"\n     darkSrc=\"/resources/images/fund-wallet/bot-welcome-dark.png\"\n     alt=\"Bot welcome screen\"\n   />\n\n1. A captcha prompt appears. Open the image to view it in full size and enter the displayed characters.\n\n   <Image\n     src=\"/resources/images/fund-wallet/captcha-light.png\"\n     darkSrc=\"/resources/images/fund-wallet/captcha-dark.png\"\n     alt=\"Captcha screen\"\n   />\n\n1. Once the captcha is complete, enter the testnet wallet address.\n\n   <Image\n     src=\"/resources/images/fund-wallet/enter-address-light.png\"\n     darkSrc=\"/resources/images/fund-wallet/enter-address-dark.png\"\n     alt=\"Enter wallet address\"\n   />\n\n   <Aside\n     type=\"caution\"\n   >\n     Verify that the pasted address belongs to the **testnet**. Mainnet and testnet addresses are distinct. See [Internal address formats](/foundations/addresses/formats#flag-definitions) for details.\n   </Aside>\n\n1. After submitting the address, a message confirms that the request is queued. Then, the bot processes it and sends 2 Toncoin in testnet.\n\n   <Image\n     src=\"/resources/images/fund-wallet/request-confirmed-light.png\"\n     darkSrc=\"/resources/images/fund-wallet/request-confirmed-dark.png\"\n     alt=\"Request confirmed\"\n   />\n\n1. No additional confirmation is sent when the request is processed.\n   To confirm receipt of the testnet Toncoin, see [Verify the transfer](#verify-the-transfer).\n\n1. To request again, open the menu in the lower-left corner, select `/get`, and repeat the steps.\n\n   <Image\n     src=\"/resources/images/fund-wallet/menu-light.png\"\n     darkSrc=\"/resources/images/fund-wallet/menu-dark.png\"\n     alt=\"Bot menu\"\n   />\n\n## Use request form\n\nRequest up to 5,000 testnet TON by completing the [token request form](https://builders.ton.org/opportunities/testnet).\nThe TON Foundation reviews the submission and transfers the tokens directly to the specified testnet wallet address.\n\n## Verify the transfer\n\nAfter requesting tokens, use the Tonviewer Testnet explorer to verify that the transfer occurred.\n\n1. Open [Tonviewer Testnet](https://testnet.tonviewer.com/), enter the wallet address in the search bar, and click <kbd>Find</kbd>.\n\n   <Image\n     src=\"/resources/images/fund-wallet/tonviewer-light.png\"\n     darkSrc=\"/resources/images/fund-wallet/tonviewer-dark.png\"\n     alt=\"Tonviewer search\"\n   />\n\n1. The explorer shows the current balance and transaction history, including the testnet Toncoin received from the bot. The account state is `uninit`, indicating that the account is not deployed.\n\n   <Image\n     src=\"/resources/images/fund-wallet/account-uninit-light.png\"\n     darkSrc=\"/resources/images/fund-wallet/account-uninit-dark.png\"\n     alt=\"Wallet balance showing uninit state\"\n   />\n\n1. To [deploy the account](/ecosystem/wallet-apps/web#deploy-the-code) send any transaction from the wallet.\n"
  },
  {
    "path": "ecosystem/wallet-apps/tonkeeper.mdx",
    "content": "---\ntitle: \"Tonkeeper\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\nimport { Image } from '/snippets/image.jsx';\n\n[Tonkeeper](https://tonkeeper.com/) is a self‑custodial mobile wallet available on [iOS](https://apps.apple.com/us/app/tonkeeper-ton-wallet/id1587742107) and [Android](https://play.google.com/store/apps/details?id=com.ton_keeper).\nIt supports regular [wallets](/standard/wallets/how-it-works), [Jettons](/standard/tokens/jettons/overview), [NFTs](/standard/tokens/nft/overview), and [TON Connect](/ecosystem/ton-connect). Its github repository can be found [here](https://github.com/tonkeeper).\n\n<div\n  style={{ display: \"flex\", justifyContent: \"center\" }}\n>\n  <Image\n    src=\"/resources/images/wallets/tonkeeper/main-int-light.png\"\n    darkSrc=\"/resources/images/wallets/tonkeeper/main-int-dark.png\"\n    width={228}\n    height={342}\n    alt=\"Tonkeeper main interface\"\n  />\n</div>\n\n- 🟡 **Account balance** displays the total amount of Toncoin and other tokens held on account.\n- 🔴 **Account address** is shown as a base64-encoded string. It can be shared to receive TON, jettons, or NFTs.\n- 🟢 **Send/Receive/Scan buttons** are used to transfer TON or jettons to another account, receive TON or jettons to the wallet, and scan QR codes to confirm transactions, respectively.\n\n## Create a wallet\n\nA wallet is required to do any transactions on a public global network. It is the primary way to interact with the blockchain. This step-by-step guide explains how to use Tonkeeper app to create a testnet wallet account.\n\nTestnet is used instead of mainnet, because it is more suitable for development and experimentation, and test coins can be obtained for free on testnet. The procedure works the same way on mainnet, except funds will have to be procured in a different way.\n\nOverall procedure is:\n\n- Generate a mnemonic (a key). It uniquely determines wallet's address, but the wallet doesn't exist on blockchain yet, i.e. is in [`nonexist`](/foundations/status#status-variety) status.\n- Send some funds to the wallet's account. Now it will be in [`uninit`](/foundations/status#status-variety) status, i.e. already with some balance on it, but without any code yet.\n- Deploy wallet's code to this address. Some of these funds will be used to pay for the deploy process. Now the wallet is in [`active`](/foundations/status#status-variety) status, and can be used for any purpose.\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  Addresses of both mainnet and testnet accounts can be derived from the same mnemonic, i.e. the same key might be used for both wallets. Beware these accounts exist only in their corresponding networks.\n\n  It's possible to forget switching to testnet, and accidentally spend real funds on mainnet.\n\n  It's possible to accidentally transfer funds to a testnet wallet address on mainnet. These funds will be impossible to recover.\n\n  Verify which network is used before any funds are sent.\n</Aside>\n\n### Generate a key\n\n1. Install Tonkeeper on [iOS](https://apps.apple.com/us/app/tonkeeper-ton-wallet/id1587742107) or [Android](https://play.google.com/store/apps/details?id=com.ton_keeper).\n\n1. Click <kbd>Create New Wallet</kbd>\n\n   <div\n     style={{ display: \"flex\", justifyContent: \"center\" }}\n   >\n     <Image\n       src=\"/resources/images/wallets/tonkeeper/create-wallet-light.png\"\n       darkSrc=\"/resources/images/wallets/tonkeeper/create-wallet-dark.png\"\n       width={228}\n       height={342}\n       alt=\"Create a wallet\"\n     />\n   </div>\n\n1. Create a passcode and re-enter it. Passcode is used to encrypt the mnemonic.\n\n   <div\n     style={{ display: \"flex\", justifyContent: \"center\", gap: \"16px\" }}\n   >\n     <Image\n       src=\"/resources/images/wallets/tonkeeper/passcode-light.png\"\n       darkSrc=\"/resources/images/wallets/tonkeeper/passcode-dark.png\"\n       width={228}\n       height={342}\n       alt=\"Create a passcode\"\n     />\n\n     <Image\n       src=\"/resources/images/wallets/tonkeeper/reenter-light.png\"\n       darkSrc=\"/resources/images/wallets/tonkeeper/reenter-dark.png\"\n       width={228}\n       height={342}\n       alt=\"Confirm the passcode\"\n     />\n   </div>\n\n1. Click <kbd>Back up your recovery phrase</kbd> and <kbd>Back Up Manually</kbd>.\n\n   <div\n     style={{ display: \"flex\", justifyContent: \"center\", gap: \"16px\" }}\n   >\n     <Image\n       src=\"/resources/images/wallets/tonkeeper/backup-light.png\"\n       darkSrc=\"/resources/images/wallets/tonkeeper/backup-dark.png\"\n       width={228}\n       height={300}\n       alt=\"Back up\"\n     />\n\n     <Image\n       src=\"/resources/images/wallets/tonkeeper/backup-manually-light.png\"\n       darkSrc=\"/resources/images/wallets/tonkeeper/backup-manually-dark.png\"\n       width={228}\n       height={342}\n       alt=\"Confirm the passcode\"\n     />\n   </div>\n\n1. Save 24 words of the [mnemonic](/standard/wallets/mnemonics).\n\n   <Aside\n     type=\"danger\"\n     title=\"Funds at risk\"\n   >\n     Mnemonic is the text representation of wallet's secret key. Losing it is the same as losing access to the wallet.<br />\n     Anyone who has access to the mnemonic can take control of the wallet and move funds. If compromise is suspected, create a new wallet and transfer all funds immediately. Prefer not to store recovery words digitally; write them down and keep them offline.\n   </Aside>\n\n   <div\n     style={{ display: \"flex\", justifyContent: \"center\" }}\n   >\n     <Image\n       src=\"/resources/images/wallets/tonkeeper/recovery-light.png\"\n       darkSrc=\"/resources/images/wallets/tonkeeper/recovery-dark.png\"\n       width={228}\n       height={342}\n       alt=\"Recovery phrase\"\n     />\n   </div>\n\n1. Pass the check that the mnemonic was saved.\n\n   <div\n     style={{ display: \"flex\", justifyContent: \"center\" }}\n   >\n     <Image\n       src=\"/resources/images/wallets/tonkeeper/backup-check-light.png\"\n       darkSrc=\"/resources/images/wallets/tonkeeper/backup-check-dark.png\"\n       width={228}\n       height={342}\n       alt=\"Recovery phrase\"\n     />\n   </div>\n\n1. The main interface of the app should now appear.\n\n### Switch to testnet\n\n1. Click <kbd>wallet</kbd> to open the <kbd>Add Wallet</kbd> pop-up.\n\n   <div\n     style={{ display: \"flex\", justifyContent: \"center\" }}\n   >\n     <Image\n       src=\"/resources/images/wallets/tonkeeper/add-testnet-wallet-light.png\"\n       darkSrc=\"/resources/images/wallets/tonkeeper/add-testnet-wallet-dark.png\"\n       width={228}\n       height={342}\n       alt=\"Add testnet\"\n     />\n   </div>\n\n1. In the \"Add Wallet\" window, scroll down to the \"For developers\" section. Click the \"Testnet Account\" card.\n\n   <div\n     style={{ display: \"flex\", justifyContent: \"center\" }}\n   >\n     <Image\n       src=\"/resources/images/wallets/tonkeeper/for-devs-light.png\"\n       darkSrc=\"/resources/images/wallets/tonkeeper/for-devs-dark.png\"\n       width={228}\n       height={342}\n       alt=\"Testnet account\"\n     />\n   </div>\n\n1. Enter the recovery phrase that was provided when the wallet was created on Mainnet, then click <kbd>Confirm</kbd>.\n\n   <div\n     style={{ display: \"flex\", justifyContent: \"center\" }}\n   >\n     <Image\n       src=\"/resources/images/wallets/tonkeeper/recovery-test-light.png\"\n       darkSrc=\"/resources/images/wallets/tonkeeper/recovery-test-dark.png\"\n       width={228}\n       height={342}\n       alt=\"Recovery phrase for testnet\"\n     />\n   </div>\n\n1. The main interface of the app should now appear, indicating that the testnet is used. Also address of the testnet wallet in the [user-friendly format](/foundations/addresses/formats#user-friendly-format) starts with `k` or `0`.\n\n   <div\n     style={{ display: \"flex\", justifyContent: \"center\" }}\n   >\n     <Image\n       src=\"/resources/images/wallets/tonkeeper/main-int-test-light.png\"\n       darkSrc=\"/resources/images/wallets/tonkeeper/main-int-test-dark.png\"\n       width={228}\n       height={342}\n       alt=\"Main interface with testnet note\"\n     />\n   </div>\n\n### Add funds into the wallet\n\nTo get free coins on testnet, follow [the guide](/ecosystem/wallet-apps/get-coins).\n\n#### Quick version\n\n1. Message [`@testgiver_ton_bot`](https://t.me/testgiver_ton_bot) in [Telegram](https://telegram.org/).\n1. Press the <kbd>Start</kbd> or send `/start` message.\n1. Pass the captcha test.\n1. Enter and send the testnet wallet address displayed by wallet.\n1. Soon after the \"Request added to the queue\" response, 2 TON will be sent to the wallet.\n1. There won't be any other message that the transfer happened. [Use an explorer](#check-the-account-state) to check the request status.\n1. The account should be in the `uninit` status now.\n\n<Image\n  src=\"/resources/images/wallets/wallet-ton-org/address_uninit_light.png\"\n  darkSrc=\"/resources/images/wallets/wallet-ton-org/address_uninit_dark.png\"\n  alt=\"Account status: uninit\"\n/>\n\n### Deploy the code\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  On-chain transfers are irreversible — verify the recipient and amount before confirming. Use testnet for practice; use mainnet only for real transfers.\n</Aside>\n\nTo deploy the code, send any transaction from the wallet. The recipient can be any address, including the wallet itself.\n\n1. Click <kbd>Send</kbd> on the main interface, enter wallet address in \"Address or name\", and the \"Amount\" of TON. Click <kbd>Continue</kbd>.\n\n   <div\n     style={{ display: \"flex\", justifyContent: \"center\" }}\n   >\n     <Image\n       src=\"/resources/images/wallets/tonkeeper/send-light.png\"\n       darkSrc=\"/resources/images/wallets/tonkeeper/send-dark.png\"\n       width={228}\n       height={342}\n       alt=\"Send TON\"\n     />\n   </div>\n\n1. Verify the transaction details and swipe if correct. Otherwise, tap <kbd>`<`</kbd> in the top-left corner to edit.\n\n   <div\n     style={{ display: \"flex\", justifyContent: \"center\" }}\n   >\n     <Image\n       src=\"/resources/images/wallets/tonkeeper/confirm-light.png\"\n       darkSrc=\"/resources/images/wallets/tonkeeper/confirm-dark.png\"\n       width={228}\n       height={342}\n       alt=\"Verify transaction\"\n     />\n   </div>\n\n1. After confirmation, enter the passcode. Then, the \"History\" page displays the sent transaction.\n\n1. [Use an explorer](#check-the-account-state) to check wallet's status. It should be `active` now.\n\n## Check the account state\n\nUse a [blockchain explorer](/ecosystem/explorers/overview) to inspect the account. For **Testnet**, use [Tonviewer Testnet](https://testnet.tonviewer.com/).\n\n1. Paste the wallet address into the search bar.<br /><Image src=\"/resources/images/wallets/wallet-ton-org/tonviewer_light.png\" darkSrc=\"/resources/images/wallets/wallet-ton-org/tonviewer_dark.png\" alt=\"Insert address in Tonviewer search\" />\n\n1. The account details will appear. In a newly created wallet, the status is `nonexist`, indicating the wallet is not deployed.<br /><Image src=\"/resources/images/wallets/wallet-ton-org/address_nonexist_light.png\" darkSrc=\"/resources/images/wallets/wallet-ton-org/address_nonexist_dark.png\" alt=\"Account status: nonexist\" />\n\n## Verify wallet's version\n\nBy default, Tonkeeper creates wallets with the [Wallet v5](/standard/wallets/v5) code deployed on them. To switch [wallet contract version](/standard/wallets/comparison) to [v4](/standard/wallets/v4):\n\n1. On the main menu, tap the gear icon <kbd><Icon icon=\"gear\" size={16} /></kbd> in the upper-right corner.\n\n1. In \"Settings\", select <kbd>Wallet v4R2</kbd> and enter the passcode.\n\n   <div\n     style={{ display: \"flex\", justifyContent: \"center\" }}\n   >\n     <Image\n       src=\"/resources/images/wallets/tonkeeper/v4r2-light.png\"\n       darkSrc=\"/resources/images/wallets/tonkeeper/v4r2-dark.png\"\n       width={228}\n       height={342}\n       alt=\"V4R2\"\n     />\n   </div>\n\n1. The wallet v4r2 is auto-generated and the app returns to the main menu.\n\n   - If v5 is highlighted, v4 has no visual indicator.\n   - To check, tap the wallet name — **wallet v4r2** — v5 is highlighted, while v4 is not.\n\n<div\n  style={{ display: \"flex\", justifyContent: \"center\" }}\n>\n  <Image\n    src=\"/resources/images/wallets/tonkeeper/wallet-v4r2-light.png\"\n    darkSrc=\"/resources/images/wallets/tonkeeper/wallet-v4r2-dark.png\"\n    width={228}\n    height={342}\n    alt=\"V4R2\"\n  />\n</div>\n"
  },
  {
    "path": "ecosystem/wallet-apps/web.mdx",
    "content": "---\ntitle: \"wallet.ton.org\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\nimport { Image } from '/snippets/image.jsx';\n\n[wallet.ton.org](https://wallet.ton.org) is a self-custodial wallet web app that doesn't require installation. It supports regular [wallets](/standard/wallets/how-it-works), [Jettons](/standard/tokens/jettons/overview), and [NFTs](/standard/tokens/nft/overview). Its source code can be found [here](https://github.com/ton-blockchain/ton-wallet).\n\n<Image\n  src=\"/resources/images/wallets/wallet-ton-org/ui_light.png\"\n  darkSrc=\"/resources/images/wallets/wallet-ton-org/ui_dark.png\"\n  alt=\"Wallet interface\"\n/>\n\n- 🟡 **Account balance** displays the total amount of Toncoin and other tokens held on account.\n- 🔴 **Account address** is shown both as a QR code and as a base64-encoded string. You can share this address to receive TON, jettons, or NFTs.\n- 🟢 **Send button** opens the transfer form, allowing you to send TON or jettons to another account address.\n\n## Create a wallet\n\nA wallet is required to do any transactions on a public global network. It is the primary way to interact with the blockchain. This step-by-step guide explains how to use [wallet.ton.org](https://wallet.ton.org) app to create a testnet wallet account.\n\nTestnet is used instead of mainnet, because it is more suitable for development and experimentation, and test coins can be obtained for free on testnet. The procedure works the same way on mainnet, except funds will have to be procured in a different way.\n\nOverall procedure is:\n\n- Generate a mnemonic (a key). It uniquely determines wallet's address, but the wallet doesn't exist on blockchain yet, i.e. is in [`nonexist`](/foundations/status#status-variety) status.\n- Send some funds to the wallet's account. Now it will be in [`uninit`](/foundations/status#status-variety) status, i.e. already with some balance on it, but without any code yet.\n- Deploy wallet's code to this address. Some of these funds will be used to pay for the deploy process. Now the wallet is in [`active`](/foundations/status#status-variety) status, and can be used for any purpose.\n\n<Aside\n  type=\"caution\"\n  title=\"Funds at risk\"\n>\n  Addresses of both mainnet and testnet accounts can be derived from the same mnemonic, i.e. the same key might be used for both wallets. Beware these accounts exist only in their corresponding networks.\n\n  It's possible to forget switching to testnet, and accidentally spend real funds on mainnet.\n\n  It's possible to accidentally transfer funds to a testnet wallet address on mainnet. These funds will be impossible to recover.\n\n  Verify which network is used before any funds are sent.\n</Aside>\n\n<Aside\n  type=\"caution\"\n  title=\"Bug!\"\n>\n  There is a bug in wallet.ton.org. Mainnet [subwallet ID](/standard/wallets/how-it-works#subwallet-id) is used to generate the address of testnet account.\n\n  If an address from wallet.ton.org doesn't match an address computed with `@ton/ton` or some other library, this might be the reason.\n</Aside>\n\n### Generate a key\n\n1. Open [wallet.ton.org](https://wallet.ton.org/).\n1. Click \"Create Wallet\".<br /><Image src=\"/resources/images/wallets/wallet-ton-org/welcome_page_light.png\" darkSrc=\"/resources/images/wallets/wallet-ton-org/welcome_page_dark.png\" alt=\"Web wallet welcome page\" />\n1. Choose \"Use Password\".<br /><Image src=\"/resources/images/wallets/wallet-ton-org/password_light.png\" darkSrc=\"/resources/images/wallets/wallet-ton-org/password_dark.png\" alt=\"Password option\" />\n1. Set and confirm password. Password will be used to encrypt the mnemonic that is stored in browser's local storage.<br /><Image src=\"/resources/images/wallets/wallet-ton-org/creating_password_light.png\" darkSrc=\"/resources/images/wallets/wallet-ton-org/creating_password_dark.png\" alt=\"Password setup\" />\n1. Save 24 words of the [mnemonic](/standard/wallets/mnemonics).<br />{<Aside type=\"danger\" title=\"Funds at risk\">\n     Mnemonic is the text representation of wallet's secret key. Losing it is the same as losing access to the wallet.<br/>\n     Anyone who has access to the mnemonic can take control of the wallet and move funds. If you suspect it already happened, create a new wallet and transfer all funds immediately. Prefer not to store recovery words digitally; write them down and keep them offline.\n     </Aside>}{<Image\n     src=\"/resources/images/wallets/wallet-ton-org/secret_words_light.png\"\n     darkSrc=\"/resources/images/wallets/wallet-ton-org/secret_words_dark.png\"\n     alt=\"Recovery words\"\n     />}\n1. Pass the check that the mnemonic was actually saved.<br /><Image src=\"/resources/images/wallets/wallet-ton-org/verify_light.png\" darkSrc=\"/resources/images/wallets/wallet-ton-org/verify_dark.png\" alt=\"Verify secret words\" />\n1. Now the app should show its main interface.\n\n### Switch to testnet\n\n1. Click the \"Settings\" icon.<br /><Image src=\"/resources/images/wallets/wallet-ton-org/settings_light.png\" darkSrc=\"/resources/images/wallets/wallet-ton-org/settings_dark.png\" alt=\"Settings button\" />\n1. In the settings window, double-click the wallet version number to open developer options.<br /><Image src=\"/resources/images/wallets/wallet-ton-org/version_light.png\" darkSrc=\"/resources/images/wallets/wallet-ton-org/version_dark.png\" alt=\"Click on version\" />\n1. In the \"Developer options\" panel, locate the \"Networks\" section and select \"Testnet\".<br /><Image src=\"/resources/images/wallets/wallet-ton-org/testnet_light.png\" darkSrc=\"/resources/images/wallets/wallet-ton-org/testnet_dark.png\" alt=\"Choose Testnet\" />\n1. The interface should indicate that testnet is used. Also address of the testnet wallet in the [user-friendly format](/foundations/addresses/formats#user-friendly-format) starts with `k` or `0`.<br />{<Image\n     src=\"/resources/images/wallets/wallet-ton-org/testnet_version_light.png\"\n     darkSrc=\"/resources/images/wallets/wallet-ton-org/testnet_version_dark.png\"\n     alt=\"Choose Testnet\"\n     />}\n\n### Add funds into the wallet\n\nThere is a [separate article](/ecosystem/wallet-apps/get-coins) on this.\n\n1. Message [`@testgiver_ton_bot`](https://t.me/testgiver_ton_bot) in [Telegram](https://telegram.org/).\n1. Press the Start button or send `/start` message.\n1. Pass the captcha test.\n1. Enter and send the testnet wallet address displayed by wallet.ton.org.\n1. Soon after the \"Request added to the queue\" response, 2 TON will be sent to the wallet.\n1. There won't be any other message that the transfer happened. [Use an explorer](#check-the-account-state) to check the request status.\n1. The account should be in the `uninit` status now.\n\n<Image\n  src=\"/resources/images/wallets/wallet-ton-org/address_uninit_light.png\"\n  darkSrc=\"/resources/images/wallets/wallet-ton-org/address_uninit_dark.png\"\n  alt=\"Account status: uninit\"\n/>\n\n### Deploy the code\n\n<Aside\n  type=\"caution\"\n  title=\"Funds at risk\"\n>\n  On-chain transfers are irreversible — verify the recipient and amount before confirming. Use testnet for practice; only use mainnet when you intend to make a real transfer.\n</Aside>\n\nTo deploy the code, send any transaction from the wallet. The recipient can be any address, including the wallet itself.\n\n1. Click \"Send\", enter wallet address in \"Recipient Address\", and the \"Amount\" of TON. Click \"Send TON\".<br /><Image src=\"/resources/images/wallets/wallet-ton-org/send_coins_light.png\" darkSrc=\"/resources/images/wallets/wallet-ton-org/send_coins_dark.png\" alt=\"Sending coins\" />\n1. In the confirmation popup, verify the transaction details and click \"Confirm\" if correct; otherwise, \"Edit\".<br /><Image src=\"/resources/images/wallets/wallet-ton-org/confirm_light.png\" darkSrc=\"/resources/images/wallets/wallet-ton-org/confirm_dark.png\" alt=\"Confirm transaction\" />\n1. After confirmation, the wallet will display a notification: \"Coins have been sent!\"<br /><Image src=\"/resources/images/wallets/wallet-ton-org/notification_light.png\" darkSrc=\"/resources/images/wallets/wallet-ton-org/notification_dark.png\" alt=\"Notification\" />\n1. [Use an explorer](#check-the-account-state) to check wallet's status. It should be `active` now.<br /><Image src=\"/resources/images/wallets/wallet-ton-org/active_light.png\" darkSrc=\"/resources/images/wallets/wallet-ton-org/active_dark.png\" alt=\"Account status: active\" />\n\n## Check the account state\n\nUse a [blockchain explorer](/ecosystem/explorers/overview) to inspect the account. For **Testnet**, use [Tonviewer Testnet](https://testnet.tonviewer.com/).\n\n1. Paste the wallet address into the search bar.<br /><Image src=\"/resources/images/wallets/wallet-ton-org/tonviewer_light.png\" darkSrc=\"/resources/images/wallets/wallet-ton-org/tonviewer_dark.png\" alt=\"Insert address in Tonviewer search\" />\n\n1. The account details will appear. In a newly created wallet, the status is `nonexist`, indicating the wallet is not deployed.<br /><Image src=\"/resources/images/wallets/wallet-ton-org/address_nonexist_light.png\" darkSrc=\"/resources/images/wallets/wallet-ton-org/address_nonexist_dark.png\" alt=\"Account status: nonexist\" />\n\n## Verify wallet's version\n\nBy default, wallet.ton.org creates wallets with the [Wallet v5](/standard/wallets/v5) code deployed on them. To check which [wallet contract version](/standard/wallets/comparison) is used:\n\n1. Click the \"Settings\" icon.<br /><Image src=\"/resources/images/wallets/wallet-ton-org/settings_light.png\" darkSrc=\"/resources/images/wallets/wallet-ton-org/settings_dark.png\" alt=\"Settings button\" />\n1. In the \"Wallet Versions\", you can see which contract the wallet uses.<br /><Image src=\"/resources/images/wallets/wallet-ton-org/wallet_version_light.png\" darkSrc=\"/resources/images/wallets/wallet-ton-org/wallet_version_dark.png\" alt=\"Settings button\" />\n1. Click the field to view the current version, for example, W5.<br /><Image src=\"/resources/images/wallets/wallet-ton-org/contract_type_light.png\" darkSrc=\"/resources/images/wallets/wallet-ton-org/contract_type_dark.png\" alt=\"Settings button\" />\n"
  },
  {
    "path": "ecosystem/walletkit/android/data.mdx",
    "content": "---\ntitle: \"How to retrieve wallet information, jettons, and NFTs with WalletKit on the Android platform\"\nsidebarTitle: \"Receiving information\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside type=\"tip\">\n  All methods require an existing wallet instance. [Create or retrieve](/ecosystem/walletkit/android/wallets) a wallet before accessing data.\n</Aside>\n\nRetrieve wallet information, Jettons, and NFTs using WalletKit.\n\n## Wallet information\n\n### Balance\n\n```kotlin\n// Returns balance in nanoToncoin\nval balance = wallet.getBalance()\n```\n\n### Address\n\n```kotlin\nval address = wallet.address\n```\n\n## Jettons\n\n### Get all Jettons\n\n```kotlin\nval jettons = wallet.getJettons(limit = 10, offset = 0)\n```\n\n### Get specific Jetton balance\n\n```kotlin\n// Address of a Jetton minter contract\n// E.g., EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs for USDT\nval jettonAddress = \"<JETTON_ADDRESS>\"\n\n// Returns balance in nanoToncoin with decimals count according to Jetton specification\nval balance = wallet.getJettonBalance(jettonAddress)\n```\n\n### Get Jetton wallet address\n\n```kotlin\n// Address of a Jetton minter contract\n// E.g., EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs for USDT\nval jettonAddress = \"<JETTON_ADDRESS>\"\nval walletAddress = wallet.getJettonWalletAddress(jettonAddress)\n```\n\n## NFTs\n\n### Get all NFTs\n\n```kotlin\nval nfts = wallet.getNFTItems(limit = 10, offset = 0)\n```\n\n### Get specific NFT\n\n```kotlin\n// Address of an NFT item contract\n// E.g., EQDkT3BSIU3CTwnZG9ZIdyWYmcnuaAEwGr_dsS1RFYqBTanY\nval nftAddress = \"<NFT_ADDRESS>\"\nval nft = wallet.getNFT(nftAddress)\n```\n\n## Next steps\n\n<Columns cols={2}>\n  <Card\n    title=\"Transactions\"\n    href=\"./transactions\"\n  >\n    Transfer Toncoin, Jettons and NFTs\n  </Card>\n\n  <Card\n    title=\"Manage wallets\"\n    href=\"./wallets\"\n  >\n    Create and manage TON wallets\n  </Card>\n</Columns>\n"
  },
  {
    "path": "ecosystem/walletkit/android/events.mdx",
    "content": "---\ntitle: \"How to connect to dApp and handle wallet events on the Android platform\"\nsidebarTitle: \"Handle events\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside type=\"tip\">\n  Initialize WalletKit before adding an events handler. See the [initialization guide](/ecosystem/walletkit/android/init) for details.\n</Aside>\n\n## Connection\n\nBefore receiving and handling wallet events, set up an events handler and establish a connection with a dApp.\n\n### Setting up events handler\n\nCreate your own implementation of an events handler and add it to the WalletKit instance:\n\n```kotlin\nimport io.ton.walletkit.ITONWalletKit\nimport io.ton.walletkit.listener.TONBridgeEventsHandler\nimport io.ton.walletkit.event.TONWalletKitEvent\n\nclass YourCustomWalletEventsHandler : TONBridgeEventsHandler {\n\n    override fun handle(event: TONWalletKitEvent) {\n        // Process the event or throw an error\n    }\n}\n\nval eventsHandler = YourCustomWalletEventsHandler()\nwalletKit.addEventsHandler(eventsHandler)\n```\n\nIf a handler is not needed anymore or needs to be replaced by some other handler, remove it:\n\n```kotlin\nwalletKit.removeEventsHandler(eventsHandler)\n```\n\n### Establishing connection with dApp\n\nTo establish a connection with a dApp, one needs a connection request URL from any source: copy/paste, QR code, deep link, etc. Send it to the WalletKit to initiate a connection request.\n\n```kotlin\nwallet.connect(/* connection url */)\n```\n\nOnce the connection request is fired, the corresponding event will be sent to your event handler. The connection event contains an object you can use to display request information to your app's users and to approve (or reject) the request to complete connection establishment.\n\n```kotlin\nclass YourCustomWalletEventsHandler : TONBridgeEventsHandler {\n\n    override fun handle(event: TONWalletKitEvent) {\n        when (event) {\n            is TONWalletKitEvent.ConnectRequest -> {\n                // Send request object to appropriate screen\n                // to display request information to app user\n            }\n            else -> {}\n        }\n    }\n}\n\n// Call an appropriate method corresponding to the user's response\n\n// To approve\nrequest.approve(walletAddress = /* TON wallet address */)\n\n// To reject\nrequest.reject(reason = /* rejection reason */)\n```\n\nAfter approval, the connection will be established, and the wallet service will be able to receive and handle other events associated with the corresponding TON wallet.\n\n## Handling events\n\nAll event handling is made through a custom event handler.\n\nReceived events carry a lot of useful information that can be displayed to the user to allow them to approve or reject the request based on their action.\n\nThe only exception is a disconnection request. Even though it contains information you can show to a user, there is no need to approve or reject it on their end.\n\n### Transaction event handling\n\n```kotlin\nclass YourCustomWalletEventsHandler : TONBridgeEventsHandler {\n\n    override fun handle(event: TONWalletKitEvent) {\n        when (event) {\n            is TONWalletKitEvent.TransactionRequest -> {\n                // Send request object to appropriate screen\n                // to display request information to app user\n            }\n            else -> {}\n        }\n    }\n}\n\n// Call an appropriate method corresponding to the user's response\n\n// To approve\nrequest.approve()\n\n// To reject\nrequest.reject(reason = /* rejection reason */)\n```\n\n### Sign data event handling\n\n```kotlin\nclass YourCustomWalletEventsHandler : TONBridgeEventsHandler {\n\n    override fun handle(event: TONWalletKitEvent) {\n        when (event) {\n            is TONWalletKitEvent.SignDataRequest -> {\n                // Send request object to appropriate screen\n                // to display request information to app user\n            }\n            else -> {}\n        }\n    }\n}\n\n// Call an appropriate method corresponding to the user's response\n\n// To approve\nrequest.approve()\n\n// To reject\nrequest.reject(reason = /* rejection reason */)\n```\n\n### Disconnection event handling\n\n```kotlin\nclass YourCustomWalletEventsHandler : TONBridgeEventsHandler {\n\n    override fun handle(event: TONWalletKitEvent) {\n        when (event) {\n            is TONWalletKitEvent.Disconnect -> {\n                // Send info object to appropriate screen\n                // to display request information to app user\n            }\n            else -> {}\n        }\n    }\n}\n```\n\nAlternatively, explore the complete demo wallet with WalletKit integration:\n\n<Card\n  title=\"Demo wallet, GitHub\"\n  icon=\"github\"\n  horizontal\n  href=\"https://github.com/ton-connect/kit-android/tree/main/AndroidDemo\"\n/>\n"
  },
  {
    "path": "ecosystem/walletkit/android/init.mdx",
    "content": "---\ntitle: \"How to initialize the TON Connect's WalletKit on the Android platform\"\nsidebarTitle: \"Init the kit\"\n---\n\n## Creating configuration\n\nThe basic kit initialization consists of creating a corresponding object by passing it a minimal set of necessary arguments. Pick a TON network to operate on, a wallet manifest, and feature configurations.\n\nHere is an example of a minimal configuration:\n\n```kotlin\nimport io.ton.walletkit.ITONWalletKit\nimport io.ton.walletkit.config.TONWalletKitConfiguration\nimport io.ton.walletkit.config.SignDataType\nimport io.ton.walletkit.model.TONNetwork\n\n// URL of the wallet's implementation of the HTTP bridge:\n// https://github.com/ton-connect/docs/blob/main/bridge.md#http-bridge\n//\n// Can be different, e.g., https://bridge.tonapi.io/bridge\nval bridgeURL = \"https://connect.ton.org/bridge\"\n\nval features = listOf(\n    // Wallet can send transactions.\n    TONWalletKitConfiguration.SendTransactionFeature(\n        // Max number of messages that can be sent in a single transaction.\n        // Depends on the TON wallet used, because different kinds can handle\n        // different number of messages.\n        maxMessages = 1,\n\n        // Are messages sending extra-currencies supported?\n        extraCurrencySupported = false\n    ),\n    TONWalletKitConfiguration.SignDataFeature(\n        types = listOf(\n            // Types of data to sign.\n            SignDataType.TEXT, SignDataType.BINARY, SignDataType.CELL\n        )\n    )\n)\n\nval configuration = TONWalletKitConfiguration(\n    network = TONNetwork.MAINNET, /* or TONNetwork.TESTNET */\n    walletManifest = TONWalletKitConfiguration.Manifest(\n        name = \"Name of your wallet service\",\n        appName = \"your_wallet_service_id\", /* e.g. best_ton_wallet_service */\n        imageUrl = \"https://<YOUR_WALLET_SERVICE_URL>/image.png\",\n        aboutUrl = \"https://<YOUR_WALLET_SERVICE_URL>/about\",\n        universalLink = \"https://<YOUR_WALLET_SERVICE_URL>/universal-link\",\n        bridgeUrl = bridgeURL\n    ),\n    bridge = TONWalletKitConfiguration.Bridge(\n        bridgeUrl = bridgeURL\n    ),\n    features = features\n)\n```\n\n### Storage configuration\n\nBy default, WalletKit uses persistent storage. To set a different behavior, use the `storage` parameter when [creating a new configuration](#creating-configuration):\n\n```kotlin\nval configuration = TONWalletKitConfiguration(\n    // ...other fields...\n    storage = TONWalletKitConfiguration.Storage(\n        persistent = true // or false for memory-only storage\n    )\n)\n```\n\n## Creating WalletKit instance\n\nOnce you have a configuration, create an instance of the kit:\n\n```kotlin\nimport io.ton.walletkit.ITONWalletKit\n\n// Instance\nval walletKit = ITONWalletKit.initialize(\n    context = context,\n    config = configuration\n)\n```\n"
  },
  {
    "path": "ecosystem/walletkit/android/installation.mdx",
    "content": "---\ntitle: \"How to install the TON Connect's WalletKit on the Android platform\"\nsidebarTitle: \"Install the kit\"\n---\n\n## Requirements\n\n- Android SDK 26+\n- Java 17+\n- Gradle 7.0+\n- Up-to-date Android System WebView (tested with 138.0.7204.179+)\n\n## Adding WalletKit to project\n\n1. Add the dependency to the app's `build.gradle.kts` file:\n\n   ```kotlin\n   dependencies {\n       // See https://central.sonatype.com/artifact/org.ton/walletkit-android/versions\n       implementation(\"org.ton:walletkit-android:+\")\n   }\n   ```\n\n1. Ensure Maven Central is included in the repository list:\n\n   ```kotlin\n   repositories {\n       google()\n       mavenCentral()\n   }\n   ```\n\n## Permissions\n\nAdd the required permission to the `AndroidManifest.xml`:\n\n```xml\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n</manifest>\n```\n\nAlternatively, explore the complete demo wallet with WalletKit integration:\n\n<Card\n  title=\"Demo wallet, GitHub\"\n  icon=\"github\"\n  horizontal\n  href=\"https://github.com/ton-connect/kit-android/tree/main/AndroidDemo\"\n/>\n"
  },
  {
    "path": "ecosystem/walletkit/android/transactions.mdx",
    "content": "---\ntitle: \"How to transfer Toncoin, Jettons and NFTs with WalletKit on the Android platform\"\nsidebarTitle: \"Transactions\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside type=\"tip\">\n  All methods require an existing wallet instance. [Create or retrieve](/ecosystem/walletkit/android/wallets) a wallet before accessing data.\n</Aside>\n\nCreate transactions to send Toncoin, Jettons, and NFTs, or generate previews for users.\n\n## Creating a transaction\n\nBefore sending any transaction to the blockchain, initialize it for the appropriate asset: Toncoin, Jetton, or NFT.\n\n### Toncoin\n\n```kotlin\nval message = TONTransferParams(\n    // TON wallet address\n    toAddress = \"<TON_WALLET_ADDRESS>\",\n\n    // 1 Toncoin in nanoToncoin format\n    amount = \"1000000000\"\n)\nval transaction = wallet.createTransferTonTransaction(message)\n```\n\n### Jettons\n\n```kotlin\nval parameters = TONJettonTransferParams(\n    // TON wallet address\n    toAddress = \"<TON_WALLET_ADDRESS>\",\n\n    // Address of a Jetton minter contract\n    // E.g., EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs for USDT\n    jettonAddress = \"<JETTON_ADDRESS>\",\n\n    // 1 token in Jetton units\n    amount = \"1000000\"\n)\nval transaction = wallet.createTransferJettonTransaction(parameters)\n```\n\n### NFTs\n\n```kotlin\nval parameters = TONNFTTransferParamsHuman(\n    // TON wallet address\n    toAddress = \"<TON_WALLET_ADDRESS>\",\n\n    // Address of an NFT item contract\n    // E.g., EQDkT3BSIU3CTwnZG9ZIdyWYmcnuaAEwGr_dsS1RFYqBTanY \n    nftAddress = \"<NFT_ADDRESS>\",\n)\nval transaction = wallet.createTransferNFTTransaction(parameters)\n```\n\n## Transaction Preview\n\nOnce a transaction object is created, present a preview to the user before sending it.\n\n```kotlin\nval preview = wallet.getTransactionPreview(transaction)\n```\n\n## Sending a transaction\n\n```kotlin\nwallet.sendTransaction(transaction)\n```\n\n## Next steps\n\n<Columns cols={2}>\n  <Card\n    title=\"Receiving information\"\n    href=\"./data\"\n  >\n    Get wallet information, Jettons, and NFTs\n  </Card>\n\n  <Card\n    title=\"Manage wallets\"\n    href=\"./wallets\"\n  >\n    Create and manage TON wallets\n  </Card>\n</Columns>\n"
  },
  {
    "path": "ecosystem/walletkit/android/wallets.mdx",
    "content": "---\ntitle: \"How to manage TON wallets with WalletKit on the Android platform\"\nsidebarTitle: \"Manage TON wallets\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside type=\"tip\">\n  Initialize the WalletKit before managing wallets. See the [initialization guide](/ecosystem/walletkit/android/init) for details.\n</Aside>\n\nThe SDK provides a comprehensive API for creating, retrieving, and managing wallets. All wallet operations follow a three-step pattern.\n\n## Creation pattern\n\nThe SDK uses a three-step pattern for creating wallets, providing fine-grained control over key management and wallet configuration:\n\n1. Create a signer: generate or import cryptographic keys\n1. Create an adapter: configure wallet version and network settings\n1. Add the wallet: register the wallet with the SDK\n\n## Creating wallets from mnemonic\n\nImport an existing wallet from a mnemonic:\n\n```kotlin\nval mnemonic = listOf(\"word1\", \"word2\", /* ... 24 words ... */)\nval signer = walletKit.createSignerFromMnemonic(mnemonic)\nval adapter = walletKit.createV5R1Adapter(\n    signer = signer,\n    network = TONNetwork.MAINNET\n)\nval wallet = walletKit.addWallet(adapter.adapterId)\n```\n\n<Aside\n  type=\"danger\"\n>\n  Always store mnemonic phrases securely using platform-specific encrypted storage. Never store them in plain text or as part of the code.\n</Aside>\n\n## Creating wallets from secret key\n\nFor externally managed keys:\n\n```kotlin\nval secretKey = /* 32-byte secret key as ByteArray */\nval signer = walletKit.createSignerFromSecretKey(secretKey)\nval adapter = walletKit.createV5R1Adapter(\n    signer = signer,\n    network = TONNetwork.MAINNET\n)\nval wallet = walletKit.addWallet(adapter.adapterId)\n```\n\n## Wallet versions\n\nThe SDK supports multiple wallet contract versions: V5R1 and V4R2.\n\n### V5R1 (Recommended)\n\nThe latest wallet version with improved features and gas optimization:\n\n```kotlin\nval adapter = walletKit.createV5R1Adapter(\n    signer = signer,\n    network = TONNetwork.MAINNET\n)\n```\n\n### V4R2 (Compatible)\n\nWidely supported legacy version:\n\n```kotlin\nval adapter = walletKit.createV4R2Adapter(\n    signer = signer,\n    network = TONNetwork.MAINNET\n)\n```\n\n## Retrieving wallets\n\nGet all wallets managed by the SDK:\n\n```kotlin\nval wallets = walletKit.getWallets()\n```\n\nGet a specific wallet by an address:\n\n```kotlin\nval wallet = walletKit.getWallet(\"<TON_WALLET_ADDRESS>\")\n```\n\n## Removing wallets\n\nRemove a single wallet:\n\n```kotlin\nwalletKit.removeWallet(\"<TON_WALLET_ADDRESS>\")\n```\n\n## Next steps\n\n<Columns cols={2}>\n  <Card\n    title=\"Handle events\"\n    href=\"./events\"\n  >\n    Learn how to handle dApp connections and other events\n  </Card>\n\n  <Card\n    title=\"Retrieve wallet data\"\n    href=\"./data\"\n  >\n    Get balances, Jettons, and NFTs\n  </Card>\n</Columns>\n"
  },
  {
    "path": "ecosystem/walletkit/android/webview.mdx",
    "content": "---\ntitle: \"How to inject TON's WalletKit into WebView on Android platform\"\nsidebarTitle: \"WebView injection\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside type=\"tip\">\n  Initialize the WalletKit before injecting it into WebView. See the [initialization guide](/ecosystem/walletkit/android/init) for details.\n</Aside>\n\nInjecting WalletKit into WebView allows integrating the wallet service with a dApp running in a native WebView and handling its events.\n\nTo do so, enable JavaScript in the WebView and inject `TonConnect`.\n\n```kotlin\nimport android.webkit.WebView\nimport io.ton.walletkit.ITONWalletKit\nimport io.ton.walletkit.extensions.injectTonConnect\n\nval webView = WebView(context)\nwebView.settings.javaScriptEnabled = true\n\nwebView.injectTonConnect(walletKit)\nwebView.loadUrl(/* dApp URL */)\n```\n\nAfter the injection is complete, handle dApp events from a [custom events handler](/ecosystem/walletkit/android/events).\n"
  },
  {
    "path": "ecosystem/walletkit/browser-extension.mdx",
    "content": "---\ntitle: Custodian integration for in-wallet browsers and browser extensions\nsidebarTitle: Browser extensions and in-wallet browsers\ndocumentation: >-\n  TON Connect integration for custodians in browser extensions and in-wallet browsers\n---\n\nThis document provides instructions for integrating [TON Connect](/ecosystem/ton-connect/overview) into wallets and other custodian services in browser extensions and in-wallet browsers.\n\nTON Connect is the standard wallet connection protocol for The Open Network (TON) blockchain, similar to WalletConnect on Ethereum. It enables secure communication between wallets and decentralized applications, allowing users to authorize transactions while maintaining control of their private keys.\n\n<Columns cols={2}>\n  <Card\n    title=\"More about TON Connect\"\n    arrow=\"true\"\n    href=\"/ecosystem/ton-connect/overview\"\n  >\n    overview of the protocol and its role in the TON ecosystem\n  </Card>\n\n  <Card\n    title=\"Wallet manifest\"\n    arrow=\"true\"\n    href=\"/ecosystem/ton-connect/manifest#wallet-manifest\"\n  >\n    what is the manifest and how to prepare it\n  </Card>\n\n  <Card\n    title=\"Bridge\"\n    href=\"#ton-connect-bridge\"\n  >\n    what is the JavaScript bridge and how to use it\n  </Card>\n\n  <Card\n    title=\"Protocol\"\n    href=\"#ton-connect-protocol\"\n  >\n    what is the protocol and how to implement it\n  </Card>\n\n  <Card\n    title=\"Signing\"\n    href=\"#ton-connect-signing\"\n  >\n    signing processes and reference implementations\n  </Card>\n\n  <Card\n    title=\"Support\"\n    href=\"#support-and-assistance\"\n  >\n    how to get help and schedule technical consultations\n  </Card>\n\n  <Card\n    title=\"FAQ\"\n    href=\"#faq\"\n  >\n    frequently asked questions about TON Connect implementation\n  </Card>\n\n  <Card\n    title=\"See also\"\n    href=\"#see-also\"\n  >\n    additional links and references\n  </Card>\n</Columns>\n\n## TON Connect bridge\n\nA TON Connect bridge acts as a communication layer between decentralized applications (dApps) and wallets.\n\nThe wallet extension should expose the bridge using the `window.[custodian].tonconnect` property.\n\nThis bridge must implement a defined interface, allowing dApps to call its methods and receive appropriate responses from the wallet.\n\n```ts\ninterface TonConnectBridge {\n    deviceInfo: DeviceInfo; // see Requests/Responses spec\n    walletInfo?: WalletInfo;\n    protocolVersion: number; // max supported Ton Connect version (e.g. 2)\n    isWalletBrowser: boolean; // if the page is opened into wallet's browser\n    connect(protocolVersion: number, message: ConnectRequest): Promise<ConnectEvent>;\n    restoreConnection(): Promise<ConnectEvent>;\n    send(message: AppRequest): Promise<WalletResponse>;\n    listen(callback: (event: WalletEvent) => void): () => void;\n}\n```\n\nTo read more about the bridge protocol, please refer to the [TON Connect Bridge documentation](https://github.com/ton-blockchain/ton-connect/blob/main/bridge.md).\n\n## TON Connect protocol\n\nTON Connect enables communication between wallets and dApps. For custodian wallets, the integration has these core components:\n\n1. Managing wallet connections\n1. Listening for messages from connected dApps\n1. Disconnecting from dApps\n\n### Setting up the protocol\n\nWe recommend using the `@tonconnect/protocol` package to handle the TON Connect protocol. But you can also implement the protocol manually.\n\n```shell\nnpm install @tonconnect/protocol\n```\n\nRefer to the [`@tonconnect/protocol` documentation](https://github.com/ton-connect/sdk/tree/main/packages/protocol) for more details.\n\n### Interacting with the dApp\n\nTo interact with the dApp wallet, implement the `TonConnectBridge` interface and inject it into the `window.[custodian].tonconnect` property. Below is the sample implementation of the protocol:\n\n```ts expandable\nimport {\n    AppRequest,\n    CHAIN,\n    CONNECT_EVENT_ERROR_CODES,\n    ConnectEvent,\n    ConnectEventSuccess,\n    ConnectManifest,\n    ConnectRequest,\n    DeviceInfo,\n    RpcMethod,\n    SendTransactionRpcRequest,\n    SendTransactionRpcResponseError,\n    SendTransactionRpcResponseSuccess,\n    TonAddressItem,\n    TonProofItem,\n    WalletEvent,\n    WalletResponse,\n} from '@tonconnect/protocol';\n\nexport type TonConnectCallback = (event: WalletEvent | DisconnectEvent) => void;\n\n// https://github.com/ton-connect/sdk/blob/main/packages/sdk/src/provider/injected/models/injected-wallet-api.ts\nexport interface TonConnectBridge {\n    deviceInfo: DeviceInfo; // see Requests/Responses spec\n    walletInfo?: WalletInfo;\n    protocolVersion: number; // max supported Ton Connect version (e.g. 2)\n    isWalletBrowser: boolean; // if the page is opened into the wallet's browser\n    connect(\n        protocolVersion: number,\n        message: ConnectRequest,\n    ): Promise<ConnectEvent>;\n\n    restoreConnection(): Promise<ConnectEvent>;\n\n    send<T extends RpcMethod>(message: AppRequest<T>): Promise<WalletResponse<T>>;\n\n    listen(callback: TonConnectCallback): () => void;\n}\n\nexport interface DisconnectEvent {\n    event: 'disconnect';\n    id: number | string;\n    payload: Record<string, never>;\n}\n\nexport interface WalletInfo {\n    name: string;\n    image: string; // <png image url>\n    tondns?: string;\n    about_url: string;\n}\n\n// Instance of this class should be injected into the window.[custodian].tonconnect property.\nexport class JsBridge implements TonConnectBridge {\n    deviceInfo: DeviceInfo = {\n        platform: 'browser',\n        appName: '[custodian]',     // Must match your manifest app_name\n        appVersion: '1.0.0',        // Your wallet version\n        maxProtocolVersion: 2,      // TON Connect protocol version, currently 2\n        features: [\n            'SendTransaction',        // Keep 'SendTransaction' as string for backward compatibility\n            {                         // And pass the object of 'SendTransaction' feature\n                name: 'SendTransaction',\n                maxMessages: 4,\n                extraCurrencySupported: false\n            }\n        ]\n    };\n\n    isWalletBrowser: boolean = true;\n    protocolVersion: number = 2;\n    walletInfo: WalletInfo = {\n        name: 'walletName',\n        about_url: 'about.com',\n        image: 'image.png',\n    };\n\n    // Refer to https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md#initiating-connection documentation for more details.\n    async connect(protocolVersion: number, request: ConnectRequest): Promise<ConnectEvent> {\n        if (protocolVersion > this.protocolVersion) {\n            throw new Error('Invalid TON Connect URL');\n        }\n        // Check if the ton_addr is requested in the connection request, if not, throw an error\n        const tonAddrItemRequest: TonAddressItem | null = request.items.find(p => p.name === 'ton_addr') ?? null;\n        if (!tonAddrItemRequest) {\n            throw new Error(\"`ton_addr` item is required in the connection request\");\n        }\n        // Check if the ton_proof is requested in the connection request, optional\n        const tonProofItemRequest: TonProofItem | null = request.items.find(p => p.name === 'ton_proof') ?? null;\n\n        // Load app manifest\n        const manifestUrl: string = request.manifestUrl; // app manifest url\n        const manifest: ConnectManifest = await fetch(manifestUrl).then(res => res.json());\n        if (!manifest) {\n            throw new Error(\"Failed to load app manifest\");\n        }\n\n        // 2. Show the connection approval dialog to the user\n        const userApproved = await confirm(`Allow ${request.manifestUrl} to connect to your wallet?`);\n        if (!userApproved) {\n            // User rejected the connection\n            throw new Error('User rejected connection'); //\n        }\n\n        // 3. Get the user's wallet data from the custodian API\n        const walletAddress = '0:9C60B85...57805AC'; // Replace with actual address from custodian API\n        const walletPublicKey = 'ADA60BC...1B56B86'; // Replace with actual wallet's public key from custodian API\n        const walletStateInit = 'te6cckEBBAEA...PsAlxCarA=='; // Replace with actual wallet's `StateInit` from custodian API\n\n        // 4. Create the connect event\n        return {\n            event: 'connect',\n            id: 0, // The id field is 0 for connect events\n            payload: {\n                items: [\n                    {\n                        name: 'ton_addr',\n                        address: walletAddress,\n                        network: CHAIN.MAINNET,\n                        publicKey: walletPublicKey,\n                        walletStateInit: walletStateInit\n                    }\n                    // If ton_proof was requested in the connection request, include it here:\n                    // Note: how to get the proof is described in a separate section\n                    // {\n                    //   name: 'ton_proof',\n                    //   proof: {\n                    //     // Signed proof data\n                    //   }\n                    // }\n                ],\n                device: this.deviceInfo\n            }\n        };\n    }\n\n    private listeners: TonConnectCallback[] = [];\n\n    listen(callback: TonConnectCallback): () => void {\n        this.listeners.push(callback);\n        return () => {\n            this.listeners = this.listeners.filter(listener => listener !== callback);\n        }\n    }\n\n    // Function to disconnect from a dApp\n    // Refer to the https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md#wallet-events documentation for more details.\n    async disconnectFromDApp() {\n        // Create a disconnect event\n        // The id field should be incremented for each sent message\n        const disconnectEvent = {\n            event: 'disconnect',\n            id: nextEventId++,\n            payload: {\n                reason: 'user_disconnected'\n            }\n        } as const;\n\n        this.listeners.map(listener => listener(disconnectEvent));\n    }\n\n\n    async restoreConnection(): Promise<ConnectEvent> {\n        // 1. Get the user's wallet data from custodian API\n        const walletAddress = '0:9C60B85...57805AC'; // Replace with actual address from custodian API\n        const walletPublicKey = 'ADA60BC...1B56B86'; // Replace with actual wallet's public key from custodian API\n        const walletStateInit = 'te6cckEBBAEA...PsAlxCarA=='; // Replace with actual wallet's `StateInit` from custodian API\n\n        // 2. Create the connect event\n        return {\n            event: 'connect',\n            id: 0, // The id field is 0 for connect events\n            payload: {\n                items: [\n                    {\n                        name: 'ton_addr',\n                        address: walletAddress,\n                        network: CHAIN.MAINNET,\n                        publicKey: walletPublicKey,\n                        walletStateInit: walletStateInit\n                    }\n                    // If ton_proof was requested in the connection request, include it here:\n                    // Note: how to get the proof is described in a separate section\n                    // {\n                    //   name: 'ton_proof',\n                    //   proof: {\n                    //     // Signed proof data\n                    //   }\n                    // }\n                ],\n                device: this.deviceInfo\n            }\n        };\n    }\n\n    // Handle messages from dApps\n    // Refer to the https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md#sign-and-send-transaction documentation for more details.\n    // Parameters:\n    // - request: The request from the dApp\n    send<T extends RpcMethod>(request: AppRequest<T>): Promise<WalletResponse<T>> {\n        console.log(`Received message:`, request);\n\n        // Check the message type\n        if (request.method === 'sendTransaction') {\n            // Handle transaction request\n            await handleTransactionRequest(request);\n        } else if (request.method === 'disconnect') {\n            // Handle disconnect request\n            await handleDisconnectRequest(request);\n        } else {\n            console.warn(`Unknown message method: ${request.method}`);\n        }\n    }\n}\n\n// Handle transaction request\n// Parameters:\n// - request: The transaction request object from the dApp\nasync function handleTransactionRequest(request: SendTransactionRpcRequest) {\n    // Extract transaction details\n    const {id, params} = request;\n    let [{network, from, valid_until, messages}] = JSON.parse(params[0]);\n\n    // The wallet should check all the parameters of the request; if any of the checks fail, it should send an error response back to the dApp\n\n    // Check if the selected network is valid\n    if (network !== CHAIN.MAINNET) {\n        return {\n            id: request.id,\n            error: {code: 1, message: 'Invalid network ID'},\n        } satisfies SendTransactionRpcResponseError;\n    }\n\n    // Check if the selected wallet address is valid\n    if (!Address.parse(from).equals(Address.parse(sessionData.walletAddress))) {\n        return {\n            id: request.id,\n            error: {\n                code: 1,\n                message: 'Invalid wallet address'\n            },\n        } satisfies SendTransactionRpcResponseError;\n    }\n\n    // Set limit for valid_until\n    const limit = 60 * 5; // 5 minutes\n    const now = Math.round(Date.now() / 1000);\n    valid_until = Math.min(valid_until ?? Number.MAX_SAFE_INTEGER, now + limit);\n\n    // Check if the transaction is still valid\n    if (valid_until < now) {\n        return {\n            id: request.id,\n            error: {\n                code: 1,\n                message: 'Transaction expired'\n            },\n        } satisfies SendTransactionRpcResponseError;\n    }\n\n    // Check if the messages are valid\n    for (const message of messages) {\n        if (!message.to || !Address.isFriendly(message.to)) {\n            return {\n                id: request.id,\n                error: {\n                    code: 1,\n                    message: 'Address is not friendly'\n                },\n            } satisfies SendTransactionRpcResponseError;\n        }\n\n        // Check if the value is a string of digits\n        if (!(typeof message.value === 'string' && /^[0-9]+$/.test(message.value))) {\n            return {\n                id: request.id,\n                error: {\n                    code: 1,\n                    message: 'Value is not a string of digits'\n                },\n            } satisfies SendTransactionRpcResponseError;\n        }\n\n        // Check if the payload is a valid BoC\n        if (message.payload) {\n            try {\n                const payload = Cell.fromBoc(message.payload)[0];\n            } catch (e) {\n                return {\n                    id: request.id,\n                    error: {\n                        code: 1,\n                        message: 'Payload is not valid BoC'\n                    },\n                } satisfies SendTransactionRpcResponseError;\n            }\n        }\n\n        // Check if the stateInit is valid BoC\n        if (message.stateInit) {\n            try {\n                const stateInit = Cell.fromBoc(message.stateInit)[0];\n            } catch (e) {\n                return {\n                    id: request.id,\n                    error: {\n                        code: 1,\n                        message: 'StateInit is not valid BoC'\n                    },\n                } satisfies SendTransactionRpcResponseError;\n            }\n        }\n    }\n\n    if (messages.length === 0) {\n        return {\n            id: request.id,\n            error: {\n                code: 1,\n                message: 'No messages'\n            },\n        } satisfies SendTransactionRpcResponseError;\n    }\n\n    // Show transaction approval UI to the user\n    const userApproved = await confirm(`Approve transaction from ${dAppName}?`);\n\n    // User rejected the transaction - send error response\n    if (!userApproved) {\n        return {\n            id: request.id,\n            error: {\n                code: 300,\n                message: 'Transaction rejected by user'\n            },\n        } satisfies SendTransactionRpcResponseError;\n    }\n\n    if (messages.length > 4) {\n        return {\n            id: request.id,\n            error: {\n                code: 1,\n                message: 'Too many messages'\n            },\n        } satisfies SendTransactionRpcResponseError;\n    }\n\n    // User approved the transaction - sign it using the custodian API, send signed BoC to the blockchain, and send a success response\n    try {\n        // Sign the transaction (implementation would depend on custodian API)\n        const signedBoc = await signTransactionWithMpcApi(sessionData.walletAddress, messages);\n\n        // Send the signed transaction to the blockchain and wait for the result\n        const isSuccess = await sendTransactionToBlockchain(signedBoc);\n        if (!isSuccess) {\n            throw new Error('Transaction send failed');\n        }\n\n        return {\n            id: request.id,\n            result: signedBoc,\n        } satisfies SendTransactionRpcResponseSuccess;\n    } catch (error) {\n        return {\n            id: request.id,\n            error: {\n                code: 100,\n                message: 'Transaction signing failed'\n            },\n        } satisfies SendTransactionRpcResponseError;\n    }\n}\n```\n\n## TON Connect signing\n\nThe signing process is a critical component when integrating TON Connect with custodians. Two key cryptographic operations are required: **Transaction Signing** and **TON Proof Signing**.\n\n### Transaction signing\n\nFor transaction signing implementation, you can refer to the [`@ton/ton` library](https://github.com/ton-org/ton) where wallet integrations are implemented. Please note that this serves as a reference implementation to understand how to achieve transaction signing:\n\n- [`@ton/crypto` on GitHub](https://github.com/ton-org/ton-crypto)\n- [`@ton/core` on GitHub](https://github.com/ton-org/ton-core)\n- [`@ton/ton` on GitHub](https://github.com/ton-org/ton)\n\nThis library provides examples and utilities for TON blockchain operations, but custodians will need to adapt these patterns to work with their specific signing infrastructure and APIs.\n\n### TON Proof implementation\n\nFor implementing the necessary functionality, two key resources are available:\n\n1. [TON Proof specification](https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md#address-proof-signature-ton_proof)\n\n- This document provides the complete specification for address proof signatures\n- Describes the required format and cryptographic requirements\n\n2. [TON Proof verification example](https://github.com/ton-connect/demo-dapp-with-react-ui/blob/248379d2545f663931151ec9f49e465b748cfc68/src/server/services/ton-proof-service.ts#L25-L116)\n\n- This example demonstrates verification of `ton_proof` (not signing)\n- Useful for understanding the proof structure and validation logic\n\n### Reference implementations\n\nFor practical examples of TON Connect signing implementations, you can review these wallet integrations:\n\n- [Tonkeeper](https://github.com/tonkeeper/wallet)\n- [TonDevWallet](https://github.com/TonDevWallet/TonDevWallet)\n\nThese implementations demonstrate how different wallets handle TON Connect signing operations and can serve as reference points for custodian implementations.\n\n## Support and assistance\n\nFor questions or clarifications during your integration process:\n\n- Add comments directly in this document for specific technical clarifications\n- Engage with the TON Foundation team through our technical chat channels\n- Contact the TON Foundation business development team to provide access to the technical team for consultations\n\nTo schedule a consultation call with our technical team:\n\n- Request a meeting through our technical chat channels\n- Contact the TON Foundation business development team to arrange technical discussions\n\nThe TON Foundation is fully committed to supporting custodians throughout this integration process. This support includes:\n\n- Providing technical documentation and specifications\n- Sharing reference implementations and code examples\n- Offering consulting and troubleshooting assistance\n- Helping with testing and verification\n\nThe TON Foundation is committed to supporting custodians throughout their TON Connect integration journey. Our team is available to address technical implementation questions, provide guidance on best practices, and facilitate business discussions to ensure successful integration outcomes.\n\n## FAQ\n\n### What are the correct network chain IDs for TON Connect?\n\nThe TON blockchain uses specific network chain identifiers in the TON Connect protocol:\n\n- **Mainnet:** `CHAIN.MAINNET` (`-239`)\n- **Testnet:** `CHAIN.TESTNET` (`-3`)\n\nThese values are defined in the TON Connect protocol specification as the `CHAIN` enum. When handling TON Connect requests, you'll encounter these network identifiers in transaction requests, address items, and connection payloads to specify which TON network the operation should target.\n\n## See also\n\n- TON Connect specification:\n  - [Bridge API](https://github.com/ton-blockchain/ton-connect/blob/main/bridge.md)\n  - [Requests and Responses](https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md)\n  - [Session](https://github.com/ton-blockchain/ton-connect/blob/main/session.md)\n  - [TON Wallet Guidelines](https://github.com/ton-blockchain/ton-connect/blob/main/wallet-guidelines.md)\n  - [Workflows](https://github.com/ton-blockchain/ton-connect/blob/main/workflows.md)\n- Reference implementations:\n  - [`@tonconnect/protocol`](https://github.com/ton-connect/sdk/tree/main/packages/protocol)\n  - [TON Connect Bridge][bridge-repo]\n- Integration examples:\n  - [Tonkeeper](https://github.com/tonkeeper/wallet)\n  - [TonDevWallet](https://github.com/TonDevWallet/TonDevWallet)\n\n[bridge-repo]: https://github.com/ton-connect/bridge\n"
  },
  {
    "path": "ecosystem/walletkit/ios/data.mdx",
    "content": "---\ntitle: \"How to retrieve wallet information, jettons, and NFTs with WalletKit on the iOS platform\"\nsidebarTitle: \"Receiving information\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside type=\"tip\">\n  All methods require an existing wallet instance. [Create or retrieve](/ecosystem/walletkit/ios/wallets) a wallet before accessing data.\n</Aside>\n\nRetrieve wallet information, Jettons, and NFTs using WalletKit.\n\n## Wallet information\n\n### Balance\n\n```swift\n// Returns balance in nanoToncoin\nlet balance = try await wallet.balance()\n```\n\n### Address\n\n```swift\nlet address = wallet.address\n```\n\n## Jettons\n\n### Get all Jettons\n\n```swift\nlet jettons = try\n    await wallet.jettons(limit: TONLimitRequest(limit: 10, offset: 0))\n```\n\n### Get specific Jetton balance\n\n```swift\n// Address of a Jetton minter contract\n// E.g., EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs for USDT\nlet jettonAddress = \"<JETTON_ADDRESS>\"\n\n// Returns balance in nano with decimals count according to Jetton specification\nlet balance = try await wallet.jettonBalance(jettonAddress: jettonAddress)\n```\n\n### Get Jetton wallet address\n\n```swift\n// Address of a Jetton minter contract\n// E.g., EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs for USDT\nlet jettonAddress = \"<JETTON_ADDRESS>\"\nlet walletAddress = try\n    await wallet.jettonWalletAddress(jettonAddress: jettonAddress)\n```\n\n## NFTs\n\n### Get all NFTs\n\n```swift\nlet nfts = try await wallet.nfts(limit: TONLimitRequest(limit: 10, offset: 0))\n```\n\n### Get specific NFT\n\n```swift\n// Address of an NFT\n// E.g., EQDkT3BSIU3CTwnZG9ZIdyWYmcnuaAEwGr_dsS1RFYqBTanY\nlet nftAddress = \"<NFT_ADDRESS>\"\nlet nft = wallet.nft(address: nftAddress)\n```\n\n## Next steps\n\n<Columns cols={2}>\n  <Card\n    title=\"Transactions\"\n    href=\"./transactions\"\n  >\n    Transfer Toncoin, Jettons and NFTs\n  </Card>\n\n  <Card\n    title=\"Manage wallets\"\n    href=\"./wallets\"\n  >\n    Create and manage TON wallets\n  </Card>\n</Columns>\n"
  },
  {
    "path": "ecosystem/walletkit/ios/events.mdx",
    "content": "---\ntitle: \"How to connect to dApp and handle wallet events on the iOS platform\"\nsidebarTitle: \"Handle events\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside type=\"tip\">\n  Initialize WalletKit before adding an events handler. See the [initialization guide](/ecosystem/walletkit/ios/init) for details.\n</Aside>\n\n## Connection\n\nBefore receiving and handling wallet events, set up an events handler and establish a connection with a dApp.\n\n### Setting up events handler\n\nCreate your own implementation of an events handler and add it to the WalletKit instance:\n\n```swift\nimport TONWalletKit\n\nclass YourCustomWalletEventsHandler: TONBridgeEventsHandler {\n\n    func handle(event: TONWalletKitEvent) throws {\n        // Process the event or throw an error\n    }\n}\n\nlet eventsHandler = YourCustomWalletEventsHandler()\ntry await walletKit.add(eventsHandler: eventsHandler)\n```\n\nIf a handler is not needed anymore or needs to be replaced by some other handler, remove it:\n\n```swift\ntry await walletKit.remove(eventsHandler: eventsHandler)\n```\n\n### Establishing connection with dApp\n\nTo establish a connection with a dApp, one needs a connection request URL from any source: copy/paste, QR code, deep link, etc. Send it to the WalletKit to initiate a connection request.\n\n```swift\ntry await walletKit.connect(url: /* connection url */)\n```\n\nOnce the connection request is fired, the corresponding event will be sent to your event handler. The connection event contains an object you can use to display request information to your app's users and to approve (or reject) the request to complete connection establishment.\n\n```swift\nclass YourCustomWalletEventsHandler: TONBridgeEventsHandler {\n\n    func handle(event: TONWalletKitEvent) throws {\n        switch event {\n        case .connectRequest(let request):\n            // Send request object to appropriate screen\n            // to display request information to app user\n            break\n        default: ()\n        }\n    }\n}\n\n// Call an appropriate method corresponding to the user's response\n\n// To approve\ntry await request.approve(walletAddress: /* TON wallet address */)\n\n// To reject\ntry await request.reject(reason: /* rejection reason */)\n```\n\nAfter approval, the connection will be established, and the wallet service will be able to receive and handle other events associated with the corresponding TON wallet.\n\n## Handling events\n\nAll event handling is made through a custom event handler.\n\nReceived events carry a lot of useful information that can be displayed to the user to allow them to approve or reject the request based on their action.\n\nThe only exception is a disconnection request. Even though it contains information you can show to a user, there is no need to approve or reject it on their end.\n\n### Transaction event handling\n\n```swift\nclass YourCustomWalletEventsHandler: TONBridgeEventsHandler {\n\n    func handle(event: TONWalletKitEvent) throws {\n        switch event {\n        case .transactionRequest(let request):\n            // Send request object to appropriate screen\n            // to display request information to app user\n            break\n        default: ()\n        }\n    }\n}\n\n// Call an appropriate method corresponding to the user's response\n\n// To approve\ntry await request.approve()\n\n// To reject\ntry await request.reject(reason: /* rejection reason */)\n```\n\n### Sign data event handling\n\n```swift\nclass YourCustomWalletEventsHandler: TONBridgeEventsHandler {\n\n    func handle(event: TONWalletKitEvent) throws {\n        switch event {\n        case .signDataRequest(let request):\n            // Send request object to appropriate screen\n            // to display request information to app user\n            break\n        default: ()\n        }\n    }\n}\n\n// Call an appropriate method corresponding to the user's response\n\n// To approve\ntry await request.approve()\n\n// To reject\ntry await request.reject(reason: /* rejection reason */)\n```\n\n### Disconnection event handling\n\n```swift\nclass YourCustomWalletEventsHandler: TONBridgeEventsHandler {\n\n    func handle(event: TONWalletKitEvent) throws {\n        switch event {\n        case .disconnect(let info):\n            // Send info object to appropriate screen\n            // to display request information to app user\n            break\n        default: ()\n        }\n    }\n}\n```\n\nAlternatively, explore the complete demo wallet with WalletKit integration:\n\n<Card\n  title=\"Demo wallet, GitHub\"\n  icon=\"github\"\n  horizontal\n  href=\"https://github.com/ton-connect/kit-ios/tree/main/Demo\"\n/>\n"
  },
  {
    "path": "ecosystem/walletkit/ios/init.mdx",
    "content": "---\ntitle: \"How to initialize the TON Connect's WalletKit on the iOS platform\"\nsidebarTitle: \"Init the kit\"\n---\n\n## Creating configuration\n\nThe basic kit initialization consists of creating a corresponding object by passing it a minimal set of necessary arguments. Pick a TON network to operate on, a wallet manifest, and feature configurations.\n\nHere is an example of a minimal configuration:\n\n```swift\nimport TONWalletKit\n\n// URL of the wallet's implementation of the HTTP bridge:\n// https://github.com/ton-connect/docs/blob/main/bridge.md#http-bridge\n//\n// Can be different, e.g., https://bridge.tonapi.io/bridge\nlet bridgeURL = \"https://connect.ton.org/bridge\"\n\nlet features: [TONWalletKitConfiguration.Feature] = [\n    // Wallet can send transactions.\n    TONWalletKitConfiguration.SendTransactionFeature(\n        // Max number of messages that can be sent in a single transaction.\n        // Depends on the TON wallet used, because different kinds can handle\n        // different number of messages.\n        maxMessages: 1,\n\n        // Are messages sending extra-currencies supported?\n        extraCurrencySupported: false\n    ),\n    TONWalletKitConfiguration.SignDataFeature(types: [\n        // Types of data to sign.\n        .text, .binary, .cell\n    ]),\n]\n\nlet configuration = TONWalletKitConfiguration(\n    network: .mainnet, /* or .testnet */\n    walletManifest: TONWalletKitConfiguration.Manifest(\n        name: \"Name of your wallet service\",\n        appName: \"your_wallet_service_id\", /* e.g. best_ton_wallet_service */\n        imageUrl: \"https://<YOUR_WALLET_SERVICE_URL>/image.png\",\n        aboutUrl: \"https://<YOUR_WALLET_SERVICE_URL>/about\",\n        universalLink: \"https://<YOUR_WALLET_SERVICE_URL>/universal-link\",\n        bridgeUrl: bridgeURL\n    ),\n    features: features\n)\n```\n\n## Creating WalletKit instance\n\nOnce you have a configuration, create an instance of the kit:\n\n```swift\nimport TONWalletKit\n\n// Instructs how to store intermediate events and other data from the WalletKit.\nlet storage: TONWalletKitStorageType = .memory // .keychain or .custom(/* custom storage */)\n\n// Instance\nlet walletKit = try await TONWalletKit.initialize(\n      configuration: configuration,\n      storage: storage\n)\n```\n\n### Creating custom storage\n\nOne can implement a custom storage and provide it during initialization:\n\n```swift\nimport TONWalletKit\n\nclass YourCustomStorage: TONWalletKitStorage {\n    func save(key: String, value: String) throws { ... }\n    func get(key: String) throws -> String? { ... }\n    func remove(key: String) throws { ... }\n    func clear() throws { ... }\n}\n\nlet walletKit = try await TONWalletKit.initialize(\n      configuration: configuration,\n      storage: .custom(YourCustomStorage())\n)\n```\n"
  },
  {
    "path": "ecosystem/walletkit/ios/installation.mdx",
    "content": "---\ntitle: \"How to install the TON Connect's WalletKit on the iOS platform\"\nsidebarTitle: \"Install the kit\"\n---\n\n## Requirements\n\n- iOS 13.0+\n- Swift 5.9+\n\n## Adding WalletKit to XCode project\n\n1. Open the project in XCode\n1. Go to `File` → `Add Package Dependencies`\n1. Search for WalletKit package by URL: [`https://github.com/ton-connect/kit-ios.git`](https://github.com/ton-connect/kit-ios.git)\n1. Tap the <kbd>Add Package</kbd> button\n\n## Adding WalletKit to Swift package\n\n1. Open the package's `Package.swift` manifest file\n\n1. Add a dependency:\n\n   ```swift\n   dependencies: [\n       .package(url: \"https://github.com/ton-connect/kit-ios.git\", .upToNextMajor(from: \"0.0.2\"))\n   ]\n   ```\n\n1. Add a product to the target:\n\n   ```swift\n   .product(name: \"TONWalletKit\", package: \"TONWalletKit\")\n   ```\n\nAlternatively, explore the complete demo wallet with WalletKit integration:\n\n<Card\n  title=\"Demo wallet, GitHub\"\n  icon=\"github\"\n  horizontal\n  href=\"https://github.com/ton-connect/kit-ios/tree/main/Demo\"\n/>\n"
  },
  {
    "path": "ecosystem/walletkit/ios/transactions.mdx",
    "content": "---\ntitle: \"How to transfer Toncoin, Jettons and NFTs with WalletKit on the iOS platform\"\nsidebarTitle: \"Transactions\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside type=\"tip\">\n  All methods require an existing wallet instance. [Create or retrieve](/ecosystem/walletkit/ios/wallets) a wallet before accessing data.\n</Aside>\n\nCreate transactions to send Toncoin, Jettons, and NFTs, or generate previews for users.\n\n## Creating a transaction\n\nBefore sending any transaction to the blockchain, initialize it for the appropriate asset: Toncoin, Jetton, or NFT.\n\n### Toncoin\n\n```swift\n// Transaction for 1 Toncoin\nlet amountFormatter = TONTokenAmountFormatter()\n\n// Provide the user's input here\nguard let amount = amountFormatter.amount(from: \"1\") else {\n    return\n}\nlet message = TONTransferMessage(\n    // TON wallet address\n    toAddress: address,\n    amount: amount,\n)\nlet transaction = try await wallet.transferTONTransaction(message: message)\n```\n\n### Jettons\n\n```swift\n// Transaction for 1 Jetton of some kind (e.g., USDT)\nlet amountFormatter = TONTokenAmountFormatter()\namountFormatter.nanoUnitDecimalsNumber = 6\n\n// Provide the user's input here\nguard let amount = amountFormatter.amount(from: \"1\") else {\n    return\n}\nlet parameters = TONJettonTransferParams(\n    // TON wallet address\n    toAddress: address,\n    // Address of a Jetton minter contract\n    jettonAddress: jettonAddress,\n    amount: amount,\n)\nlet transaction = try await wallet.transferJettonTransaction(parameters: parameters)\n```\n\n### NFTs\n\n```swift\nlet parameters = TONNFTTransferParamsHuman(\n    // TON wallet address\n    toAddress: address,\n    // Address of an NFT item contract\n    nftAddress: nft.address,\n)\nlet transaction = try await wallet.transferNFTTransaction(parameters: parameters)\n```\n\n## Transaction Preview\n\nOnce a transaction object is created, present a preview to the user before sending it.\n\n```swift\nlet preview = try await wallet.preview(transaction: transaction)\n```\n\n## Sending a transaction\n\n```swift\ntry await wallet.send(transaction: transaction)\n```\n\n## Next steps\n\n<Columns cols={2}>\n  <Card\n    title=\"Receiving information\"\n    href=\"./data\"\n  >\n    Get wallet information, Jettons, and NFTs\n  </Card>\n\n  <Card\n    title=\"Manage wallets\"\n    href=\"./wallets\"\n  >\n    Create and manage TON wallets\n  </Card>\n</Columns>\n"
  },
  {
    "path": "ecosystem/walletkit/ios/wallets.mdx",
    "content": "---\ntitle: \"How to manage TON wallets with WalletKit on the iOS platform\"\nsidebarTitle: \"Manage TON wallets\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside type=\"tip\">\n  Initialize the WalletKit before managing wallets. See the [initialization guide](/ecosystem/walletkit/ios/init) for details.\n</Aside>\n\nThe SDK provides a comprehensive API for creating, retrieving, and managing wallets. All wallet operations follow a three-step pattern.\n\n## Creation pattern\n\nThe SDK uses a three-step pattern for creating wallets, providing fine-grained control over key management and wallet configuration:\n\n1. Create a signer: generate or import cryptographic keys\n1. Create an adapter: configure wallet version and network settings\n1. Add the wallet: register the wallet with the SDK\n\n## Creating wallets from mnemonic\n\nImport an existing wallet from a mnemonic:\n\n```swift\nlet mnemonic = TONMnemonic(value: [\"word1\", \"word2\", /* ... 24 words ... */])\nlet signer = try await walletKit.signer(mnemonic: mnemonic)\nlet adapter = try await walletKit.walletV5R1Adapter(\n    signer: signer,\n    parameters: .init(network: .mainnet)\n)\nlet wallet = try await walletKit.add(walletAdapter: adapter)\n```\n\n<Aside\n  type=\"danger\"\n>\n  Always store mnemonic phrases securely using platform-specific encrypted storage. Never store them in plain text or as part of the code.\n</Aside>\n\n## Creating wallets from secret key\n\nFor externally managed keys:\n\n```swift\nlet privateKey = /* 32-byte private key as Data */\nlet signer = try await walletKit.signer(privateKey: privateKey)\nlet adapter = try await walletKit.walletV5R1Adapter(\n    signer: signer,\n    parameters: .init(network: .mainnet)\n)\nlet wallet = try await walletKit.add(walletAdapter: adapter)\n```\n\n## Wallet versions\n\nThe SDK supports multiple wallet contract versions: V5R1 and V4R2.\n\n### V5R1 (Recommended)\n\nThe latest wallet version with improved features and gas optimization:\n\n```swift\nlet adapter = try await walletKit.walletV5R1Adapter(\n    signer: signer,\n    parameters: .init(network: .mainnet)\n)\n```\n\n### V4R2 (Compatible)\n\nWidely supported legacy version:\n\n```swift\nlet adapter = try await walletKit.walletV4R2Adapter(\n    signer: signer,\n    parameters: .init(network: .mainnet)\n)\n```\n\n## Retrieving wallets\n\nGet all wallets managed by the SDK:\n\n```swift\nlet wallets = try await walletKit.wallets()\n```\n\nGet a specific wallet by an address:\n\n```swift\nlet wallet = try walletKit.wallet(address: \"<TON_WALLET_ADDRESS>\")\n```\n\n## Removing wallets\n\nRemove a single wallet:\n\n```swift\ntry await walletKit.remove(walletAddress: \"<TON_WALLET_ADDRESS>\")\n```\n\n## Next steps\n\n<Columns cols={2}>\n  <Card\n    title=\"Handle events\"\n    href=\"./events\"\n  >\n    Learn how to handle dApp connections and other events\n  </Card>\n\n  <Card\n    title=\"Retrieve wallet data\"\n    href=\"./data\"\n  >\n    Get balances, Jettons, and NFTs\n  </Card>\n</Columns>\n"
  },
  {
    "path": "ecosystem/walletkit/ios/webview.mdx",
    "content": "---\ntitle: \"How to inject TON's WalletKit into WebView on iOS platform\"\nsidebarTitle: \"WebView injection\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside type=\"tip\">\n  Initialize the WalletKit before injecting it into WebView. See the [initialization guide](/ecosystem/walletkit/ios/init) for details.\n</Aside>\n\nInjecting WalletKit into WebView allows integrating the wallet service with a dApp running in a native WebView and handling its events.\n\nTo do so, obtain the dApp injection bridge key — it is the name under which the dApp injects itself in the `window` object.\n\n```swift\nimport TONWalletKit\nimport WebKit\n\nlet webView = WKWebView()\ntry webView.inject(walletKit: walletKit, key: /* dApp bridge key */)\nwebView.load(URLRequest(url: /* dApp URL */))\n```\n\nAfter the injection is complete, handle dApp events from a [custom events handler](/ecosystem/walletkit/android/events).\n"
  },
  {
    "path": "ecosystem/walletkit/native-web.mdx",
    "content": "---\ntitle: Custodian integration for native and web wallets\nsidebarTitle: Native and web wallets\ndocumentation: >-\n  TON Connect integration for custodians on iOS, Android, macOS, Windows, Linux, and Web platforms.\n---\n\nThis document provides instructions for integrating [TON Connect](/ecosystem/ton-connect/overview) into wallets and other custodian services for iOS, Android, macOS, Windows, Linux, and Web platforms.\n\nTON Connect is the standard wallet connection protocol for The Open Network (TON) blockchain, similar to WalletConnect on Ethereum. It enables secure communication between wallets and decentralized applications, allowing users to authorize transactions while maintaining control of their private keys.\n\n<Columns cols={2}>\n  <Card\n    title=\"More about TON Connect\"\n    arrow=\"true\"\n    href=\"/ecosystem/ton-connect/overview\"\n  >\n    overview of the protocol and its role in the TON ecosystem\n  </Card>\n\n  <Card\n    title=\"Wallet manifest\"\n    arrow=\"true\"\n    href=\"/ecosystem/ton-connect/manifest#wallet-manifest\"\n  >\n    what is the manifest and how to prepare it\n  </Card>\n\n  <Card\n    title=\"Bridge\"\n    href=\"#ton-connect-bridge\"\n  >\n    what is the bridge service and how to set it up\n  </Card>\n\n  <Card\n    title=\"Protocol\"\n    href=\"#ton-connect-protocol\"\n  >\n    what is the protocol and how to implement it\n  </Card>\n\n  <Card\n    title=\"Signing\"\n    href=\"#ton-connect-signing\"\n  >\n    signing processes and reference implementations\n  </Card>\n\n  <Card\n    title=\"Support\"\n    href=\"#support-and-assistance\"\n  >\n    how to get help and schedule technical consultations\n  </Card>\n\n  <Card\n    title=\"FAQ\"\n    href=\"#faq\"\n  >\n    frequently asked questions about TON Connect implementation\n  </Card>\n\n  <Card\n    title=\"See also\"\n    href=\"#see-also\"\n  >\n    additional links and references\n  </Card>\n</Columns>\n\n## TON Connect bridge\n\nThe TON Connect bridge serves as a transport mechanism for delivering messages between applications (dApps) and wallets. It enables end-to-end encrypted communication where neither party needs to be online simultaneously.\n\n### Setup options\n\n#### Option 1: On-premise solution\n\nCustodians can run the TON Connect Bridge themselves. This approach provides full control over the infrastructure and data.\n\nFor this option, you can deploy the [official TON Connect Bridge implementation][bridge-repo].\n\nYou will need to:\n\n1. Set up a dedicated bridge instance following the repository documentation\n1. Create a DNS entry pointing to your bridge\n1. Configure your infrastructure (load balancers, SSL certificates, etc.)\n1. Maintain the bridge and provide updates\n\n#### Option 2: SaaS solution\n\nTON Foundation can provide a Software-as-a-Service (SaaS) solution for custodians who prefer not to maintain on-premise infrastructure.\n\nTo request access to the SaaS solution, contact the TON Foundation business development team. This managed service includes:\n\n1. Hosted bridge infrastructure\n1. Maintenance and updates\n1. Technical support\n1. Service level agreements\n\n### Bridge endpoints and protocol\n\nThe TON Connect Bridge protocol uses these main endpoints:\n\n- **SSE Events Channel** — For receiving messages:\n\n  ```\n  GET /events?client_id=<to_hex_str(A1)>,<to_hex_str(A2)>,<to_hex_str(A3)>&last_event_id=<lastEventId>\n  Accept: text/event-stream\n  ```\n\n- **Message Sending** — For sending messages:\n\n  ```\n  POST /message?client_id=<sender_id>&to=<recipient_id>&ttl=300\n  body: <base64_encoded_message>\n  ```\n\nThere, `client_id` and `sender_id` are the public keys of the wallet's session in hex.\n\nTo read more about the bridge protocol, please refer to the [TON Connect Bridge documentation](https://github.com/ton-blockchain/ton-connect/blob/main/bridge.md).\n\n## TON Connect protocol\n\nTON Connect enables communication between wallets and dApps. For custodian wallets, the integration has these core components:\n\n1. Establishing secure sessions with dApps\n1. Handling universal links in the browser\n1. Managing wallet connections\n1. Listening for messages from connected dApps\n1. Disconnecting from dApps\n\n### Setting up the protocol\n\nWe recommend using the `@tonconnect/protocol` package to handle the TON Connect protocol. But you can also implement the protocol manually.\n\n```shell\nnpm install @tonconnect/protocol\n```\n\nRefer to the [`@tonconnect/protocol` documentation](https://github.com/ton-connect/sdk/tree/main/packages/protocol) for more details.\n\n### Session management and encryption\n\nThe foundation of TON Connect is secure communication using the SessionCrypto class:\n\n```ts expandable\nimport { SessionCrypto, KeyPair, AppRequest, Base64 } from '@tonconnect/protocol';\n\n// Receive dApp public key from the connection link 'id' parameter\n// This value is decoded from hex to Uint8Array\nconst dAppPublicKey: Uint8Array = hexToByteArray(dAppClientId);\n\n// Create a new session - this generates a keypair for the session internally\nconst sessionCrypto: SessionCrypto = new SessionCrypto();\n\n// Encrypt a message to send to the dApp\n// Parameters:\n// - message: The string message to encrypt\n// - dAppPublicKey: The dApp's public key as Uint8Array\nconst message: string = JSON.stringify({\n  event: 'connect',\n  payload: { /* connection details */ }\n});\nconst encryptedMessage: string = sessionCrypto.encrypt(\n  message,\n  dAppPublicKey\n);\n\n// Decrypt a message from the dApp\n// Parameters:\n// - encrypted: The encrypted message string from the dApp\n// - dAppPublicKey: The dApp's public key as Uint8Array\nconst encrypted: string = 'encrypted_message_from_dapp';\nconst decryptedMessage: string = sessionCrypto.decrypt(\n  Base64.decode(encrypted).toUint8Array(),\n  dAppPublicKey\n);\nconst parsedMessage: AppRequest = JSON.parse(decryptedMessage);\n\n// Get session keys for storage\n// Returns an object with `publicKey` and `secretKey` as hex strings\nconst keyPair: KeyPair = sessionCrypto.stringifyKeypair();\n\n// Store these securely in your persistent storage\nconst storedData = {\n  secretKey: keyPair.secretKey,\n  publicKey: keyPair.publicKey,\n  dAppClientId: dAppClientId\n};\n\n// Later - restore the session using stored keys\n// Parameters:\n// - secretKey: Hex string of the secret key\n// - publicKey: Hex string of the public key\nconst restoredSessionCrypto: SessionCrypto = new SessionCrypto({\n  secretKey: storedData.secretKey,\n  publicKey: storedData.publicKey\n});\n```\n\nRefer to the [SessionCrypto implementation](https://github.com/ton-connect/sdk/blob/main/packages/protocol/src/crypto/session-crypto.ts) and [Session documentation](https://github.com/ton-blockchain/ton-connect/blob/main/session.md) for more details.\n\n### Bridge communication\n\nTON Connect uses a bridge service as a relay for messages between dApps and wallets:\n\n```ts expandable\n// Bridge URL for your wallet\nconst bridgeUrl = 'https://bridge.[custodian].com/bridge';\n\n// Sending messages to the bridge\n// Parameters:\n// - fromClientId: Your wallet's client ID (public key of the wallet's session in hex)\n// - toClientId: The dApp's client ID (public key of the dApp's session in hex)\n// - encryptedMessage: The encrypted message to send\n// - ttl: Time to live in seconds (optional, default is 300 seconds)\nasync function sendToBridge(fromClientId: string, toClientId: string, encryptedMessage: string) {\n  await fetch(`${bridgeUrl}/message`, {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify({\n      client_id: fromClientId,\n      to: toClientId,\n      message: encryptedMessage,\n      ttl: 300\n    })\n  });\n}\n\n// Listening for messages from the bridge\n// Parameters:\n// - clientId: Your wallet's client ID (public key of the wallet's session in hex)\n// - lastEventId: The last event ID received from the bridge (optional, but should be used if you want to resume listening for messages from the same point)\nfunction listenFromBridge(clientId: string, lastEventId?: string) {\n  const url = lastEventId\n    ? `${bridgeUrl}/events?client_id=${clientId}&last_event_id=${lastEventId}`\n    : `${bridgeUrl}/events?client_id=${clientId}`;\n\n  return new EventSource(url);\n}\n```\n\nRefer to the [bridge API documentation](https://github.com/ton-blockchain/ton-connect/blob/main/bridge.md) for more details.\n\n### Handling TON Connect links for new connections\n\nWhen a user opens a connection link in your browser wallet, this flow begins:\n\n```ts expandable\n// This code runs when a URL like this is opened:\n// https://wallet.[custodian].com/ton-connect?v=2&id=<client_id>&r=<connect_request>&ret=<return_strategy>\n// Parameters in the URL:\n// - v: Protocol version (2)\n// - id: The dApp's client ID (hex-encoded public key of the dApp's session)\n// - r: URL-encoded connect request object\n// - ret: Return strategy for the dApp (may be ignored for custodian)\n\nimport { ConnectRequest, ConnectEventSuccess, SessionCrypto, KeyPair, ConnectManifest, TonAddressItem, TonProofItem, CHAIN, Base64 } from '@tonconnect/protocol';\n\nwindow.addEventListener('load', async () => {\n  if (window.location.pathname === '/ton-connect') {\n    try {\n      // 1. Parse the connection parameters from the URL\n      const parsedUrl: URL = new URL(window.location.href);\n      const searchParams: URLSearchParams = parsedUrl.searchParams;\n\n      const version: string | null = searchParams.get('v');\n      const dAppClientId: string | null = searchParams.get('id');\n      const requestEncoded: string | null = searchParams.get('r');\n\n      if (!version || !dAppClientId || !requestEncoded) {\n        console.error('Invalid TON Connect URL: missing required parameters');\n        return;\n      }\n\n      // Decode and parse the request\n      const request: ConnectRequest = JSON.parse(decodeURIComponent(requestEncoded));\n\n      // Check if the ton_addr is requested in the connection request, if not, throw an error\n      const tonAddrItemRequest: TonAddressItem | null = request.items.find(p => p.name === 'ton_addr') ?? null;\n      if (!tonAddrItemRequest) {\n        console.error(\"`ton_addr` item is required in the connection request\");\n        return;\n      }\n      // Check if the ton_proof is requested in the connection request, optional\n      const tonProofItemRequest: TonProofItem | null = request.items.find(p => p.name === 'ton_proof') ?? null;\n\n      // Load app manifest\n      const manifestUrl: string = request.manifestUrl; // app manifest url\n      const manifest: ConnectManifest = await fetch(manifestUrl).then(res => res.json());\n      if (!manifest) {\n        console.error(\"Failed to load app manifest\");\n        return;\n      }\n\n      // 2. Show connection approval dialog to the user\n      const userApproved = await confirm(`Allow ${request.manifestUrl} to connect to your wallet?`);\n      if (!userApproved) {\n        return; // User rejected the connection\n      }\n\n      // 3. Create a new session for this connection, this generates a keypair for the session internally\n      const sessionCrypto = new SessionCrypto();\n\n      // 4. Get the user's wallet data from custodian API\n      const walletAddress = '0:9C60B85...57805AC'; // Replace with actual address from custodian API\n      const walletPublicKey = 'ADA60BC...1B56B86'; // Replace with actual wallet's public key from custodian API\n      const walletStateInit = 'te6cckEBBAEA...PsAlxCarA=='; // Replace with actual wallet's `StateInit` from custodian API\n\n      // 5. Create the connect event\n      const connectEvent: ConnectEventSuccess = {\n        event: 'connect',\n        id: 0, // The id field is 0 for connect events\n        payload: {\n          items: [\n            {\n              name: 'ton_addr',\n              address: walletAddress,\n              network: CHAIN.MAINNET,\n              publicKey: walletPublicKey,\n              walletStateInit: walletStateInit\n            }\n            // If ton_proof was requested in the connection request, include it here:\n            // Note: how to get the proof is described in separate section\n            // {\n            //   name: 'ton_proof',\n            //   proof: {\n            //     // Signed proof data\n            //   }\n            // }\n          ],\n          device: {\n            platform: 'web',\n            appName: '[custodian]',     // Must match your manifest app_name\n            appVersion: '1.0.0',        // Your wallet version\n            maxProtocolVersion: 2,      // TON Connect protocol version, currently 2\n            features: [\n              'SendTransaction',        // Keep 'SendTransaction' as string for backward compatibility\n              {                         // And pass the object of 'SendTransaction' feature\n                name: 'SendTransaction',\n                maxMessages: 4,\n                extraCurrencySupported: false\n              }\n            ]\n          }\n        }\n      };\n\n      // 6. Encrypt the connect event with the dApp's public key\n      const encryptedConnectEvent: string = sessionCrypto.encrypt(\n        JSON.stringify(connectEvent),\n        hexToByteArray(dAppClientId)\n      );\n\n      // 7. Store the session data for future interactions\n      const keyPair = sessionCrypto.stringifyKeypair();\n      const sessionData = {\n        secretKey: keyPair.secretKey,        // Wallet session secret key (hex)\n        publicKey: keyPair.publicKey,        // Wallet session public key (hex)\n        dAppClientId: dAppClientId,          // dApp session public key (hex) / same as the id parameter in the URL\n        dAppName: manifest.app_name,         // dApp name from manifest\n        dAppUrl: manifest.url,               // dApp URL from manifest\n        walletAddress: walletAddress,        // User's wallet address\n        network: CHAIN.MAINNET,              // Network from manifest\n        lastEventId: undefined,              // Last received event ID from bridge\n        nextEventId: 1,                      // Next ID for events sent from wallet\n      };\n\n      // Generate a session ID and store the session\n      const sessionId = sessionData.publicKey;\n      localStorage.setItem(`tonconnect_session_${sessionId}`, JSON.stringify(sessionData));\n\n      // 8. Send the connect event to the dApp through the bridge\n      const walletClientId = sessionCrypto.publicKey;\n      await sendToBridge(walletClientId, dAppClientId, encryptedConnectEvent);\n\n      // 9. Set up a listener for future messages from this dApp\n      setupDAppMessageListener(sessionId, sessionData);\n\n    } catch (e) {\n      console.error('Failed to handle TON Connect link:', e);\n    }\n  }\n});\n```\n\nRefer to [Universal link](https://github.com/ton-blockchain/ton-connect/blob/main/bridge.md#universal-link) and [`ConnectRequest`](https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md#initiating-connection) documentation for more details.\n\n### Listening for messages from connected dApps\n\nAfter establishing connections, you need to listen for messages from connected dApps:\n\n```ts expandable\n// This function sets up listeners for all active sessions\n// Note: this is a simplified example, in a real wallet there can be multiple sessions per one connection\nfunction setupAllSessionListeners() {\n  // Get all active sessions\n  for (let i = 0; i < localStorage.length; i++) {\n    const key = localStorage.key(i);\n    if (key && key.startsWith('tonconnect_session_')) {\n      const sessionId = key.replace('tonconnect_session_', '');\n      const sessionData = JSON.parse(localStorage.getItem(key));\n\n      setupDAppMessageListener(sessionId, sessionData);\n    }\n  }\n}\n\n// Set up a listener for messages from a specific dApp\n// Parameters:\n// - sessionId: The session ID (wallet's session public key)\n// - sessionData: The session data object containing keys and dApp info\nfunction setupDAppMessageListener(sessionId: string, sessionData) {\n  // Create a session crypto instance from the stored keys\n  const sessionCrypto = new SessionCrypto({\n    secretKey: sessionData.secretKey,\n    publicKey: sessionData.publicKey\n  });\n\n  // Your wallet's client ID is its public key in hex\n  const walletClientId: string = sessionCrypto.publicKey;\n\n  // Start listening for messages, using the last event ID if available\n  const eventSource = listenFromBridge(walletClientId, sessionData.lastEventId);\n\n  eventSource.onmessage = async (event: { lastEventId: string, data: { message: string, from: string } }) => {\n    try {\n      // Update the last event ID for this session\n      sessionData.lastEventId = event.lastEventId;\n      localStorage.setItem(`tonconnect_session_${sessionId}`, JSON.stringify(sessionData));\n\n      // Process the message if it's from the dApp we're connected to\n      if (appRequest.from === sessionData.dAppClientId) {\n        // Decrypt the message using the dApp's public key\n        const decrypted: string = sessionCrypto.decrypt(\n          Base64.decode(appRequest.message).toUint8Array(),\n          hexToByteArray(sessionData.dAppClientId)\n        );\n\n        // Parse and handle the message\n        const request: AppRequest = JSON.parse(decrypted);\n\n        // Handle different types of requests (e.g., transaction requests, disconnect request, etc.)\n        await handleDAppMessage(sessionId, sessionData, request);\n      }\n    } catch (e) {\n      console.error('Failed to process message:', e);\n    }\n  };\n}\n\n// Handle messages from dApps\n// Parameters:\n// - sessionId: The session ID (wallet's session public key)\n// - sessionData: The session data object\n// - request: The decrypted request from the dApp\nasync function handleDAppMessage(sessionId: string, sessionData, request: AppRequest) {\n  console.log(`Received message from ${sessionData.dAppName}:`, request);\n\n  // Check the message type\n  if (request.method === 'sendTransaction') {\n    // Handle transaction request\n    await handleTransactionRequest(sessionId, sessionData, request);\n  } else if (request.method === 'disconnect') {\n    // Handle disconnect request\n    await handleDisconnectRequest(sessionId, sessionData, request);\n  } else {\n    console.warn(`Unknown message method: ${request.method}`);\n  }\n}\n\n// Handle transaction request\n// Parameters:\n// - sessionId: The session ID (wallet's session public key)\n// - sessionData: The session data object\n// - request: The transaction request object from the dApp\nasync function handleTransactionRequest(sessionId: string, sessionData, request: SendTransactionRequest) {\n  // Extract transaction details\n  const { id, params } = request;\n  const [{ network, from, valid_until, messages }] = params;\n\n  // The wallet should check all the parameters of the request; if any of the checks fail, it should send an error response back to the dApp\n\n  // Check if the selected network is valid\n  if (network !== sessionData.network) {\n    return await sendTransactionResponseError(sessionId, sessionData, id, {\n      code: 1,\n      message: 'Invalid network'\n    });\n  }\n\n  // Check if the selected wallet address is valid\n  if (!Address.parse(from).equals(Address.parse(sessionData.walletAddress))) {\n    return await sendTransactionResponseError(sessionId, sessionData, id, {\n      code: 1,\n      message: 'Invalid wallet address'\n    });\n  }\n\n  // Set limit for valid_until\n  const limit = 60 * 5; // 5 minutes\n  const now = Math.round(Date.now() / 1000);\n  valid_until = Math.min(valid_until ?? Number.MAX_SAFE_INTEGER, now + limit);\n\n  // Check if the transaction is still valid\n  if (valid_until < now) {\n    return await sendTransactionResponseError(sessionId, sessionData, id, {\n      code: 1,\n      message: 'Transaction expired'\n    });\n  }\n\n  // Check if the messages are valid\n  for (const message of messages) {\n    if (!message.to || !Address.isFriendly(message.to)) {\n      return await sendTransactionResponseError(sessionId, sessionData, id, {\n        code: 1,\n        message: 'Address is not friendly'\n      });\n    }\n\n    // Check if the value is a string of digits\n    if (!(typeof message.value === 'string' && /^[0-9]+$/.test(message.value))) {\n      return await sendTransactionResponseError(sessionId, sessionData, id, {\n        code: 1,\n        message: 'Value is not a string of digits'\n      });\n    }\n\n    // Check if the payload is valid BoC\n    if (message.payload) {\n      try {\n        const payload = Cell.fromBoc(message.payload)[0];\n      } catch (e) {\n        return await sendTransactionResponseError(sessionId, sessionData, id, {\n          code: 1,\n          message: 'Payload is not valid BoC'\n        });\n      }\n    }\n\n    // Check if the stateInit is valid BoC\n    if (message.stateInit) {\n      try {\n        const stateInit = Cell.fromBoc(message.stateInit)[0];\n      } catch (e) {\n        return await sendTransactionResponseError(sessionId, sessionData, id, {\n          code: 1,\n          message: 'StateInit is not valid BoC'\n        });\n      }\n    }\n  }\n\n  // Show transaction approval UI to the user\n  const userApproved = await confirm(`Approve transaction from ${dAppName}?`);\n\n  // User rejected the transaction - send error response\n  if (!userApproved) {\n    return await sendTransactionResponseError(sessionId, sessionData, id, {\n      code: 300,\n      message: 'Transaction rejected by user'\n    });\n  }\n  if (messages.length === 0) {\n    return await sendTransactionResponseError(sessionId, sessionData, id, {\n      code: 1,\n      message: 'No messages'\n    });\n  }\n  if (messages.length > 4) {\n    return await sendTransactionResponseError(sessionId, sessionData, id, {\n      code: 1,\n      message: 'Too many messages'\n    });\n  }\n\n  // User approved the transaction - sign it using the custodian API, send the signed BoC to the blockchain, and send a success response\n  try {\n    // Sign the transaction (implementation would depend on custodian API)\n    const signedBoc = await signTransactionWithMpcApi(sessionData.walletAddress, messages);\n\n    // Send the signed transaction to the blockchain and wait for the result\n    const isSuccess = await sendTransactionToBlockchain(signedBoc);\n    if (!isSuccess) {\n        throw new Error('Transaction send failed');\n    }\n\n    // Create success response\n    await sendTransactionResponseSuccess(sessionId, sessionData, id, signedBoc);\n  } catch (error) {\n    // Handle signing error\n    await sendTransactionResponseError(sessionId, sessionData, id, {\n        code: 100,\n        message: 'Transaction signing failed'\n    });\n  }\n}\n\n// Send error response for a transaction request\n// Parameters:\n// - sessionId: The session ID (wallet's session public key)\n// - sessionData: The session data object\n// - requestId: The original request ID from the dApp\n// - error: Error object with code and message\nasync function sendTransactionResponseError(sessionId, sessionData, requestId, error) {\n  const transactionResponse: SendTransactionResponseError = {\n    id: requestId,\n    error: error\n  };\n  await sendTransactionResponse(sessionId, sessionData, requestId, transactionResponse);\n}\n\n// Send a success response for a transaction request\n// Parameters:\n// - sessionId: The session ID (wallet's session public key)\n// - sessionData: The session data object\n// - requestId: The original request ID from the dApp\n// - signedBoc: The signed transaction BoC\nasync function sendTransactionResponseSuccess(sessionId, sessionData, requestId, signedBoc) {\n  const transactionResponse: SendTransactionResponseSuccess = {\n    id: requestId,\n    result: signedBoc\n  };\n  await sendTransactionResponse(sessionId, sessionData, requestId, transactionResponse);\n}\n\n// Send response for a transaction request\n// Parameters:\n// - sessionId: The session ID (wallet's session public key)\n// - sessionData: The session data object\n// - requestId: The original request ID from the dApp\n// - response: The response object to send\nasync function sendTransactionResponse(sessionId, sessionData, requestId, response) {\n  // Create a session crypto from the stored keys\n  const sessionCrypto = new SessionCrypto({\n    secretKey: sessionData.secretKey,\n    publicKey: sessionData.publicKey\n  });\n\n  // Include response ID - this should match the request ID\n  response.id = requestId;\n\n  // Encrypt the response\n  const encryptedResponse = sessionCrypto.encrypt(\n    JSON.stringify(response),\n    hexToByteArray(sessionData.dAppClientId)\n  );\n\n  // Send through the bridge\n  await sendToBridge(\n    sessionCrypto.publicKey,\n    sessionData.dAppClientId,\n    encryptedResponse\n  );\n}\n```\n\nRefer to the [SendTransactionRequest](https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md#sign-and-send-transaction) documentation for more details.\n\n### Disconnecting from dApps\n\nAllow users to disconnect from dApps when needed. This action is initiated by the user on the custodian's side:\n\n```ts expandable\n// Function to disconnect from a dApp\n// Parameters:\n// - sessionId: The session ID (wallet's session public key) to disconnect\nasync function disconnectFromDApp(sessionId) {\n  const sessionDataString = localStorage.getItem(`tonconnect_session_${sessionId}`);\n  if (!sessionDataString) return;\n\n  const sessionData = JSON.parse(sessionDataString);\n\n  // Create a session crypto from the stored keys\n  const sessionCrypto = new SessionCrypto({\n    secretKey: sessionData.secretKey,\n    publicKey: sessionData.publicKey\n  });\n\n  // Create a disconnect event\n  // The id field should be incremented for each sent message\n  const disconnectEvent = {\n    event: 'disconnect',\n    id: sessionData.nextEventId++,\n    payload: {\n      reason: 'user_disconnected'\n    }\n  };\n\n  // Encrypt and send to the dApp\n  const encryptedDisconnectEvent = sessionCrypto.encrypt(\n    JSON.stringify(disconnectEvent),\n    hexToByteArray(sessionData.dAppClientId)\n  );\n\n  // Your wallet's client ID is its public key\n  const walletClientId = sessionCrypto.publicKey;\n\n  // Send the disconnect event\n  await sendToBridge(walletClientId, sessionData.dAppClientId, encryptedDisconnectEvent);\n\n  // Close the EventSource\n  const eventSource = document.querySelector(`#event-source-${sessionId}`);\n  if (eventSource) {\n    eventSource.close();\n  }\n\n  // Delete the session\n  localStorage.removeItem(`tonconnect_session_${sessionId}`);\n}\n```\n\nRefer to the [DisconnectEvent](https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md#wallet-events) documentation for more details.\n\n## TON Connect signing\n\nThe signing process is a critical component when integrating TON Connect with custodians. Two key cryptographic operations are required: [**Transaction signing**](#transaction-signing) and [**TON Proof signing**](#ton-proof-implementation).\n\n### Transaction signing\n\nFor transaction signing implementation, you can refer to the [`@ton/ton` library](https://github.com/ton-org/ton) where wallet integrations are implemented. Please note that this serves as a reference implementation to understand how to achieve transaction signing:\n\n- [`@ton/crypto`](https://github.com/ton-org/ton-crypto)\n- [`@ton/core`](https://github.com/ton-org/ton-core)\n- [`@ton/ton`](https://github.com/ton-org/ton)\n\nThis library provides examples and utilities for TON blockchain operations, but custodians will need to adapt these patterns to work with their specific signing infrastructure and APIs.\n\n### TON Proof implementation\n\nFor implementing the necessary functionality, two key resources are available:\n\n1. [TON Proof specification](https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md#address-proof-signature-ton_proof)\n\n- This document provides the complete specification for address proof signatures\n- Describes the required format and cryptographic requirements\n\n2. [TON Proof verification example](https://github.com/ton-connect/demo-dapp-with-react-ui/blob/248379d2545f663931151ec9f49e465b748cfc68/src/server/services/ton-proof-service.ts#L25-L116)\n\n- This example demonstrates verification of `ton_proof` (not signing)\n- Useful for understanding the proof structure and validation logic\n\n### Reference implementations\n\nFor practical examples of TON Connect signing implementations, you can review these wallet integrations:\n\n- [Tonkeeper](https://github.com/tonkeeper/wallet)\n- [TonDevWallet](https://github.com/TonDevWallet/TonDevWallet)\n\nThese implementations demonstrate how different wallets handle TON Connect signing operations and can serve as reference points for custodian implementations.\n\n## Support and assistance\n\nFor questions or clarifications during your integration process:\n\n- Add comments directly in this document for specific technical clarifications\n- Engage with the TON Foundation team through our technical chat channels\n- Contact the TON Foundation business development team to provide access to the technical team for consultations\n\nTo schedule a consultation call with our technical team:\n\n- Request a meeting through our technical chat channels\n- Contact the TON Foundation business development team to arrange technical discussions\n\nThe TON Foundation is fully committed to supporting custodians throughout this integration process. This support includes:\n\n- Providing technical documentation and specifications\n- Sharing reference implementations and code examples\n- Offering consulting and troubleshooting assistance\n- Helping with testing and verification\n\nThe TON Foundation is committed to supporting custodians throughout their TON Connect integration journey. Our team is available to address technical implementation questions, provide guidance on best practices, and facilitate business discussions to ensure successful integration outcomes.\n\n## FAQ\n\n### What are the correct network chain IDs for TON Connect?\n\nThe TON blockchain uses specific network chain identifiers in the TON Connect protocol:\n\n- **Mainnet:** `CHAIN.MAINNET` (`-239`)\n- **Testnet:** `CHAIN.TESTNET` (`-3`)\n\nThese values are defined in the TON Connect protocol specification as the `CHAIN` enum. When handling TON Connect requests, you'll encounter these network identifiers in transaction requests, address items, and connection payloads to specify which TON network the operation should target.\n\n## See also\n\n- TON Connect specification:\n  - [Bridge API](https://github.com/ton-blockchain/ton-connect/blob/main/bridge.md)\n  - [Requests and Responses](https://github.com/ton-blockchain/ton-connect/blob/main/requests-responses.md)\n  - [Session](https://github.com/ton-blockchain/ton-connect/blob/main/session.md)\n  - [TON Wallet Guidelines](https://github.com/ton-blockchain/ton-connect/blob/main/wallet-guidelines.md)\n  - [Workflows](https://github.com/ton-blockchain/ton-connect/blob/main/workflows.md)\n- Reference implementations:\n  - [`@tonconnect/protocol`](https://github.com/ton-connect/sdk/tree/main/packages/protocol)\n  - [TON Connect Bridge][bridge-repo]\n- Integration examples:\n  - [Tonkeeper](https://github.com/tonkeeper/wallet)\n  - [TonDevWallet](https://github.com/TonDevWallet/TonDevWallet)\n\n[bridge-repo]: https://github.com/ton-connect/bridge\n"
  },
  {
    "path": "ecosystem/walletkit/overview.mdx",
    "content": "---\ntitle: \"WalletKit: SDK for custodial and non-custodial wallet services\"\nsidebarTitle: \"Overview\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nTON Connect's **WalletKit** is an open-source SDK that helps integrate your custodial or non-custodial wallet with TON in a secure and streamlined fashion.\n\nIt is designed for institutions, non-custodians, and custodians that need full control over key management, signing, and access without compromising UX or compliance.\n\n## Features\n\n- TON Connect protocol: Handles connect, disconnect, transaction and data sign requests\n- Wallet management: Support for multiple TON wallets at once, with persistent storage and optional use of custom signers\n- Action previews: Transaction emulation with money flow analysis\n- Asset support: Toncoin (TON), Jettons (including USDTs), NFTs with metadata\n- Platform availability: Use on the Web, on mobile (Android and iOS), and in browser extensions\n\n## Use cases\n\nWalletKit supports both small wallet services and large cross-chain systems.\n\n## Quick start\n\nFirst, follow this step-by-step guide: [How to integrate a wallet with TON](/ecosystem/ton-connect/wallet).\n\nThen, follow relevant usage recipes:\n\n<Tabs>\n  <Tab\n    title=\"Web\"\n    icon=\"globe\"\n  >\n    <Columns\n      cols={3}\n    >\n      <Card\n        title=\"Initialize the kit\"\n        href=\"/ecosystem/walletkit/web/init\"\n      />\n\n      <Card\n        title=\"Manage TON wallets\"\n        href=\"/ecosystem/walletkit/web/wallets\"\n      />\n\n      <Card\n        title=\"Handle connections\"\n        href=\"/ecosystem/walletkit/web/connections\"\n      />\n\n      <Card\n        title=\"Handle other events\"\n        href=\"/ecosystem/walletkit/web/events\"\n      />\n\n      <Card\n        title=\"Work with Toncoin\"\n        href=\"/ecosystem/walletkit/web/toncoin\"\n      />\n\n      <Card\n        title=\"Work with Jettons\"\n        href=\"/ecosystem/walletkit/web/jettons\"\n      />\n\n      <Card\n        title=\"Work with NFTs\"\n        href=\"/ecosystem/walletkit/web/nfts\"\n      />\n    </Columns>\n  </Tab>\n</Tabs>\n\n## See also\n\nRead more about the TON Connect itself: [TON Connect overview](/ecosystem/ton-connect/overview).\n\nSkim the reference pages with more in-depth information:\n\n- [TON Connect manifests](/ecosystem/ton-connect/manifest)\n- [`@tonconnect/protocol`, external API reference](https://ton-connect.github.io/sdk/modules/_tonconnect_protocol.html)\n"
  },
  {
    "path": "ecosystem/walletkit/qa-guide.mdx",
    "content": "---\ntitle: Integration QA guide\n---\n\nThis document provides a complete guide for custodians integrating TON Connect - from understanding what to build to verifying your implementation works correctly.\n\n<Columns cols={2}>\n  <Card\n    title=\"Understanding user experience standards\"\n    href=\"#understanding-user-experience-standards\"\n  >\n    Learn what good integration looks like\n  </Card>\n\n  <Card\n    title=\"Demo environment and testing platform\"\n    href=\"#demo-environment-and-testing-platform\"\n  >\n    using TON Foundation's testing infrastructure\n  </Card>\n\n  <Card\n    title=\"Testing your implementation\"\n    href=\"#testing-your-implementation\"\n  >\n    verify your basic integration works\n  </Card>\n\n  <Card\n    title=\"Go-live procedure\"\n    href=\"#go-live-procedure\"\n  >\n    what's needed for production integrations\n  </Card>\n\n  <Card\n    title=\"Support\"\n    href=\"#support\"\n  >\n    get help\n  </Card>\n\n  <Card\n    title=\"FAQ\"\n    href=\"#faq\"\n  >\n    frequently asked questions\n  </Card>\n</Columns>\n\n## Understanding user experience standards\n\nBefore building your integration, experience TON Connect as a user to understand what good integration looks like and what your users will expect.\n\n### Try these wallets first\n\nUse [Tonkeeper](https://tonkeeper.com/) or [MyTonWallet](https://mytonwallet.io/) to experience TON Connect. Both support mobile, desktop, and browser extensions.\n\n[Wallet in Telegram](https://t.me/wallet) demonstrates the UX for wallets implemented as Telegram Mini Apps.\n\n### Basic flow experience\n\nOpen the [React Demo dApp](https://tonconnect-sdk-demo-dapp.vercel.app/) and connect one of these wallets. Notice how the connection works — desktop to mobile uses QR codes, mobile browser to wallet clicks directly, browser extensions connect instantly, and in-wallet browsers connect with one click.\n\nAfter connecting, try sending a basic transaction and test signing features like \"Sign Text\".\n\nPay attention to how transaction details are displayed, how approval works, and how errors are handled. This is the standard your users will expect from your wallet.\n\n## Demo environment and testing platform\n\nTON Foundation provides demo dApps and a comprehensive testing platform with all necessary test scenarios. You don't need to create your own test cases — everything is already prepared.\n\n### Demo dApps\n\nWe have a [dApp for TON Connect testing](https://tonconnect-sdk-demo-dapp.vercel.app/), which is used in most test cases. In our testing platform, it is called **GENERAL**.\n\nAdditionally, there are several demo dApps used for testing specific scenarios. In our testing platform, it is called **CUSTOM**. Keep in mind that each test case has a Description field indicating which dApp to use: **GENERAL** or **CUSTOM**.\n\n### Testing platform\n\nOur testing platform, Allure TestOps, contains manual test scenarios you execute yourself. Navigate to test suites matching your wallet's platforms and run each test case manually.\n\nObserve all test scenarios [via this link](https://tontech.testops.cloud/project/1/test-cases?treeId=2) with these credentials:\n\n- Login: `guest`\n- Password: `Test123!`\n\n| #  | Test suite                         | Coverage                                                  |\n| :- | :--------------------------------- | :-------------------------------------------------------- |\n| 1  | Common Checks                      | PR formatting, manifest validation, platform installation |\n| 2  | Connection and Transaction Sending | Core functionality across platforms and dApps             |\n| 3  | Disconnection Testing              | Session termination scenarios                             |\n| 4  | Transaction Data Validation        | Wallet-side security checks                               |\n| 5  | Max Messages                       | Batch transaction handling                                |\n| 6  | App Domain Validation              | Security testing for TON Proof wallets                    |\n| 7  | Extra Currency Support             | Advanced currency features                                |\n| 8  | Merkle Proof/Update                | Advanced cryptographic operations                         |\n| 9  | Sign data                          | Custom payload signing                                    |\n\nEach test case shows:\n\n- **Description:** Which dApp to use **GENERAL** or **CUSTOM** along with its URL.\n- **Preconditions:** What setup is needed before starting.\n- **Scenario:** Manual actions to perform.\n- **Expected results:** What should happen if your integration works correctly.\n\nFor transaction tests, use the provided JSON configurations in the demo dApp's editable transaction interface. Execute all test cases in sequence and fix any issues found in your integration.\n\n## Testing your implementation\n\nAfter building your integration, verify that it works with a basic connection test.\n\n### Basic connection test\n\n1. Open the [React Demo dApp](https://tonconnect-sdk-demo-dapp.vercel.app/)\n1. Click \"Connect Wallet\" to see the connection modal\n1. Choose connection method:\n   - Scan universal QR code: Use your mobile wallet to scan the QR code (works with any TON Connect wallet)\n   - Find your wallet in the testing wallets list and click it for direct connection\n1. Complete the connection based on your wallet type (extension, mobile app, or web wallet)\n1. Try sending a simple transaction to confirm full functionality\n\nIf this works, your basic integration is successful, and you can start using our testing platform suites. If your wallet doesn't appear in the list or the connection fails, revisit the technical implementation guides.\n\n## Go-live procedure\n\n### Wallet submission\n\nSubmit a pull request to the [wallet-list repository](https://github.com/ton-connect/wallets-list) with your wallet manifest, which was tested with the testing platform.\n\n### Audit process\n\nOnce your team has opened a pull request to add the wallet to the official [wallets-list repository on GitHub](https://github.com/ton-connect/wallets-list), please advise your BizDev liaison so an audit slot can be scheduled. A typical review cycle lasts **three to five business days**. During this period, TON Foundation engineers verify the TON Connect integration, assessing connection flows, transaction signing, security controls, error handling, and overall user experience across every supported platform.\n\nAt the end of each iteration, you will receive a written report that summarizes the test results. After you supply an updated build and a brief changelog, the engineering team performs a re-test under the same three-to-five-day service level.\n\n### Release\n\nWhen the audit is approved, the pull request moves to the maintainers’ queue for a final repository review. This check — focused on completeness of metadata and technical compliance — normally takes **one business day**. Once the pull request is merged, your wallet becomes discoverable to TON ecosystem dApps. Please keep the manifest endpoint continuously available and update the repository entry whenever you release significant changes to the wallet.\n\n## Support\n\nTON Foundation’s engineering team is available throughout the entire integration lifecycle – from design review to pre-production validation – to surface issues early and help you reach production smoothly.\n\nWhen you request support, please include the following information so we can diagnose and resolve issues quickly:\n\n- **Wallet platform and version:** e.g., macOS 15.3.2, Chrome 137.0.7151.69, wallet version 1.2.3\n- **Issue summary:** Brief description of the problem or the attached URL to the corresponding Allure scenario, if available, along with any questions related to it.\n- **Reproduction steps:** Clear, step-by-step instructions (or sample requests/transactions) that consistently trigger the issue.\n\nProviding this information up front enables faster triage, targeted guidance, and efficient re-testing once fixes are applied.\n\n## FAQ\n\n### How long does the process take?\n\nWith collaborative development and continuous testing support, we expect 1-2 weeks for wallet listing. (General self-submitted wallets typically take 4-8 weeks.)\n\n### What platforms should we support?\n\nAny platforms that fit your business needs — mobile, desktop, browser extensions, or web.\n\n### Is TON Proof required?\n\nYes — TON Proof is a required feature for wallet integration.\n\n### What if we fail test scenarios?\n\nWork with TON Foundation during the audit to determine if issues are critical or acceptable.\n\n### Can we update during the audit?\n\nYes, notify the audit team of significant changes.\n"
  },
  {
    "path": "ecosystem/walletkit/web/connections.mdx",
    "content": "---\ntitle: \"How to handle connections with WalletKit on the Web platform\"\nsidebarTitle: \"Handle connections\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside>\n  [Initialize the WalletKit](/ecosystem/walletkit/web/init) and [set up at least one TON wallet](/ecosystem/walletkit/web/wallets) before using examples on this page.\n</Aside>\n\nTo use a wallet service for initiating blockchain transactions and signing data, dApps need to set up a connection over the bridge first. Connection is established via `connect` requests and terminated via `disconnect` requests.\n\n## Connection flow\n\nStandard flow looks as follows:\n\n1. User clicks a \"Connect wallet\" button in the dApp, selecting the desired wallet service\n1. WalletKit processes the connection URL and triggers the `onConnectRequest()` method\n1. There, WalletKit instructs the wallet service to show a connection request preview, waiting for the user's approval\n1. User approves or rejects a connection\n\n<Aside>\n  The flow can started by scanning a QR code from a dApp in the wallet service, or by pressing a deep link in the wallet service. In both cases, WalletKit will process the URL via the `handleTonConnectUrl()` method, then fire a `connect` event for the `onConnectRequest()` method to handle.\n</Aside>\n\nIf the connection was approved, the dApp could proceed to send various transaction or data sign requests. If it was rejected, the dApp can repeat the flow.\n\nIf a user decides to disconnect a wallet at any point, the `disconnect` request will be issued and the `onDisconnect()` method of the WalletKit will handle it.\n\n## Handlers\n\nTo work with connection-specific requests, the WalletKit offers three methods which expect processing functions as callbacks:\n\n- The `onConnectRequest()` method processes connection requests\n- The `onDisconnect()` method processes disconnection requests\n- The `onRequestError()` method allows to [handle errors](/ecosystem/walletkit/web/events#handle-request-errors) arising in any of the requests\n\n### Handle `onConnectRequest`\n\nWhen a user wants to connect a TON wallet from the dApp, the dApp fires the `connect` request over the bridge. The wallet service then handles it with the `onConnectRequest` method of the WalletKit.\n\nOn the dApp side, this flow is often initiated by pressing the \"Connect a wallet\" button, followed by selecting the user's wallet service. Additionally, a dApp can produce a [QR code or a deep link](#qr-codes-and-deep-links), which initiate the connection flow from within the wallet service.\n\n```ts title=\"TypeScript\"\nkit.onConnectRequest(async (event) => {\n  try {\n    const wallets = kit.getWallets();\n    if (wallets.length === 0) {\n      // Make sure to present a message to the user.\n      console.log('No wallets available');\n      await kit.rejectConnectRequest(event, 'No wallets available');\n      return;\n    }\n    const dappName = event.preview.dAppInfo?.name || 'Unknown dApp';\n    const dappUrl = event.preview.dAppInfo?.url || event.preview.dAppInfo?.manifestUrl || 'Unknown URL';\n    // Show the connection confirmation UI to the user of the wallet service\n    if (confirm(`Connect to ${dappName} from ${dappUrl}?`)) {\n      // Set `walletId` on the request before approving\n      event.walletId = wallets[0].getWalletId();\n      await kit.approveConnectRequest(event);\n      console.log('Connected to:', dappName);\n    } else {\n      await kit.rejectConnectRequest(event, 'User rejected');\n      console.log('Connection rejected by a user');\n    }\n  } catch (error) {\n    console.error('Connection handler error:', error);\n    await kit.rejectConnectRequest(event, 'Fatal error in the connection handler');\n  }\n});\n```\n\n#### Wallet selection\n\nWhen there are several TON wallets added, ask the user to select one before approving the connection request.\n\n```ts title=\"TypeScript\"\nkit.onConnectRequest(async (event) => {\n  try {\n    const wallets = kit.getWallets();\n    if (wallets.length === 0) {\n      // Make sure to present a message to the user.\n      console.log('No wallets available');\n      await kit.rejectConnectRequest(event, 'No wallets available');\n      return;\n    }\n    // Selecting the 1st TON wallet by default\n    let selectedWallet = { ok: true, wallet: wallets[0] };\n    // Yet, asking the user to pick one if there are many\n    if (wallets.length > 1) {\n      // Here, uiSelectWallet() is assumed to be implemented elsewhere:\n      // it takes the list of wallets and provides the user with a choice\n      // to pick one from the list, then returns with the picked option\n      // or a rejection if there was none.\n      selectedWallet = await uiSelectWallet(wallets);\n    }\n    if (!selectedWallet.ok) {\n      // Make sure to present a message to the user.\n      console.log('No wallet selected');\n      await kit.rejectConnectRequest(event, 'No wallet selected');\n      return;\n    }\n    const dappName = event.preview.dAppInfo?.name || 'Unknown dApp';\n    const dappUrl = event.preview.dAppInfo?.url || event.preview.dAppInfo?.manifestUrl || 'Unknown URL';\n    // Show the connection confirmation UI to the user of the wallet service\n    if (confirm(`Connect to ${dappName} from ${dappUrl}?`)) {\n      // Set `walletId` on the request before approving\n      event.walletId = selectedWallet.wallet.getWalletId();\n      await kit.approveConnectRequest(event);\n      console.log('Connected to:', dappName);\n    } else {\n      await kit.rejectConnectRequest(event, 'User rejected');\n      console.log('Connection rejected by a user');\n    }\n  } catch (error) {\n    console.error('Connection handler error:', error);\n    await kit.rejectConnectRequest(event, 'Fatal error in the connection handler');\n  }\n});\n```\n\n#### QR codes and deep links\n\nThe `handleTonConnectUrl()` method of the WalletKit parses a TON Connect link and creates a new [connection request event](#handle-onconnectrequest).\n\nUsually, this link comes from a QR code generated on the dApp side, but it can also be provided within the mobile dApp as a deep link.\n\n```ts title=\"TypeScript\"\nasync function handleQrCode(content: string) {\n  try {\n    // On success, this will fire the onConnectRequest handler:\n    await kit.handleTonConnectUrl(content);\n  } catch (error) {\n    console.error('Invalid QR code:', error);\n    // Make sure to present an error to the user.\n    throw new Error('Failed to process TON Connect QR code');\n  }\n}\n\nasync function handleDeepLink(url: string) {\n  if (url.startsWith('tc://') || url.includes('ton-connect')) {\n    try {\n      // On success, this will fire the onConnectRequest handler:\n      await kit.handleTonConnectUrl(url);\n    } catch (error) {\n      console.error('Invalid link:', error);\n      // Make sure to present an error to the user.\n      throw new Error('Failed to process TON Connect deep link');\n    }\n  }\n}\n```\n\n### Handle `onDisconnect`\n\nWhen a user disconnects a wallet service and its TON wallet from the dApp, the dApp fires the `disconnect` request over the bridge. The wallet service then handles it with the `onDisconnect` method of the WalletKit.\n\n```ts title=\"TypeScript\"\nkit.onDisconnect(async (event) => {\n  // Clean up any UI state related to this connection.\n  console.log(`Disconnected from a dApp that used this TON wallet: ${event.walletAddress}`);\n});\n```\n\n## Next steps\n\n<Columns cols={2}>\n  <Card\n    title=\"Handle other events\"\n    icon=\"signature\"\n    horizontal=\"true\"\n    href=\"/ecosystem/walletkit/web/events\"\n  />\n</Columns>\n\n## See also\n\n- [WalletKit overview](/ecosystem/walletkit/overview)\n- [TON Connect overview](/ecosystem/ton-connect/overview)\n"
  },
  {
    "path": "ecosystem/walletkit/web/events.mdx",
    "content": "---\ntitle: \"How to handle other events with WalletKit on the Web platform\"\nsidebarTitle: \"Handle other events\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside>\n  [Initialize the WalletKit](/ecosystem/walletkit/web/init), [set up at least one TON wallet](/ecosystem/walletkit/web/wallets) and [handle connection requests](/ecosystem/walletkit/web/connections) before using examples on this page.\n</Aside>\n\nIn total, there are five distinct kinds of incoming requests from the TON Connect bridge. They form the corresponding events and their handlers:\n\n| Incoming request    | WalletKit method to listen and process the request                                      |\n| ------------------- | --------------------------------------------------------------------------------------- |\n| `connect`           | [`onConnectRequest()`](/ecosystem/walletkit/web/connections#handle-onconnectrequest)    |\n| `disconnect`        | [`onDisconnect()`](/ecosystem/walletkit/web/connections#handle-ondisconnect)            |\n| `transaction`       | [`onTransactionRequest()`](/ecosystem/walletkit/web/events#handle-ontransactionrequest) |\n| `signData`          | [`onSignDataRequest()`](/ecosystem/walletkit/web/events#handle-onsigndatarequest)       |\n| `restoreConnection` | None — this is a connection health check of the JS bridge                               |\n| Any event error     | [`onRequestError()`](#handle-request-errors)                                            |\n\n## Handle `onTransactionRequest`\n\nIf a dApp is connected to the wallet service, the former can request to initiate a blockchain transaction, which fires the `transaction` request over the bridge. The wallet service then handles it with the `onTransactionRequest` method of the WalletKit.\n\nOn TON, transactions are initiated by sending an external message to the TON wallet contract, which then processes it and sends internal messages as requested. To estimate money flows for planned transactions, WalletKit uses emulation via the configured API client, if supported.\n\n<Aside>\n  The API client in use is determined by the required [`networks` configuration parameter](/ecosystem/walletkit/web/init#param-networks) during [WalletKit initialization](/ecosystem/walletkit/web/init#initialization).\n</Aside>\n\n```ts title=\"TypeScript\"\nkit.onTransactionRequest(async (event) => {\n  try {\n    if (!event.preview.data) {\n      console.log('Transaction emulation skipped');\n    } else if (event.preview.data.result === 'success') {\n      // If the emulation was successful,\n      // show net asset changes to the user for a confirmation.\n      // There, positive amounts mean incoming transfers,\n      // and negative mean outgoing ones.\n      console.log(event.preview.data.moneyFlow?.ourTransfers ?? []);\n    } else {\n      // Transaction emulation was not successful,\n      // but you can still allow a user to proceed — with a warning.\n      console.warn('Transaction emulation failed');\n    }\n    if (confirm('Do you confirm this transaction?')) {\n      await kit.approveTransactionRequest(event);\n    } else {\n      await kit.rejectTransactionRequest(event, 'User rejected');\n    }\n  } catch (error) {\n    console.error('Transaction handler error:', error);\n    await kit.rejectTransactionRequest(event, 'Fatal error in the connection handler');\n  }\n});\n```\n\n## Handle `onSignDataRequest`\n\nIf a dApp is connected to the wallet service, the former can request to sign data with the private key used by the selected TON wallet, which fires the `signData` request over the bridge. The wallet service then handles it with the `onSignDataRequest` method of the WalletKit.\n\nThe data to sign can be of several kinds: `text`, `binary`, or a raw [`cell`](/foundations/serialization/cells).\n\n```ts title=\"TypeScript\"\nkit.onSignDataRequest(async (event) => {\n  try {\n    // Data to be signed can be of three distinct types.\n    // Depending on a type, show it to the user for a confirmation.\n    const dataToSign = event.payload.data;\n    switch (dataToSign.type) {\n      case 'text':\n        console.log(dataToSign.value.content);\n        break;\n      case 'binary':\n        console.log(dataToSign.value.content);\n        break;\n      case 'cell':\n        // The `request.cell` contains a hex-encoded string with a serialized cell\n        // and the `request.schema` describes a TL-B schema to parse the `request.cell`\n        console.log(dataToSign.value.content);\n        console.log(dataToSign.value.schema);\n        break;\n    }\n    if (confirm('Do you confirm this data sign request?')) {\n      try {\n        // Sign the data with the user's approval\n        const result = await kit.approveSignDataRequest(event);\n        console.log('Signed successfully:', result);\n      } catch (error) {\n        console.error('Signing failed:', error);\n      }\n    } else {\n      await kit.rejectSignDataRequest(event, 'User rejected');\n    }\n  } catch (error) {\n    console.error('Data sign handler error:', error);\n    await kit.rejectSignDataRequest(event, 'Fatal error in the data sign handler');\n  }\n});\n```\n\n## Handle request errors\n\nUpon any error in any of the requests, the `onRequestError()` method is invoked. Provide it with a callback function that would handle arbitrary errors and display useful information to the user.\n\n```ts title=\"TypeScript\"\nkit.onRequestError(async (event) => {\n  console.error('Error in request ID:', event.id);\n  console.error('Details:', event.error);\n  console.error('Data:', event.data);\n});\n```\n\n## Next steps\n\n<Columns cols={2}>\n  <Card\n    title=\"Work with Toncoin\"\n    icon=\"gem\"\n    horizontal=\"true\"\n    href=\"/ecosystem/walletkit/web/toncoin\"\n  />\n</Columns>\n\n## See also\n\n- [WalletKit overview](/ecosystem/walletkit/overview)\n- [TON Connect overview](/ecosystem/ton-connect/overview)\n"
  },
  {
    "path": "ecosystem/walletkit/web/init.mdx",
    "content": "---\ntitle: \"How to initialize the TON Connect's WalletKit on the Web platform\"\nsidebarTitle: \"Initialize the kit\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nBefore initializing the TON Connect's WalletKit, install it in the web project:\n\n```shell\nnpm i @ton/walletkit\n```\n\nAlternatively, explore the complete demo wallet with WalletKit integration:\n\n<Columns cols={2}>\n  <Card\n    title=\"Demo wallet, deployed\"\n    icon=\"link\"\n    arrow=\"true\"\n    horizontal=\"true\"\n    href=\"https://walletkit-demo-wallet.vercel.app\"\n  />\n\n  <Card\n    title=\"Demo wallet, GitHub\"\n    icon=\"github\"\n    arrow=\"true\"\n    horizontal=\"true\"\n    href=\"https://github.com/ton-connect/kit/tree/main/apps/demo-wallet\"\n  />\n</Columns>\n\n## Initialization\n\nThe basic kit initialization consists of creating a corresponding object by passing it a minimal set of necessary arguments: TON networks to operate on.\n\nYet, it is often useful to configure optional parameters right away — the following example also specifies core wallet information, TON Connect manifest, and bridge settings.\n\n```ts\nimport {\n  // Main class\n  TonWalletKit,\n  // Network object\n  Network,\n  // Helper functions\n  createDeviceInfo,\n  createWalletManifest,\n} from '@ton/walletkit';\n\n// 0. Create a kit object.\nconst kit = new TonWalletKit({\n  // 1. Configure networks.\n  networks: {\n    // Production network. All contracts and funds are real.\n    [Network.mainnet().chainId]: {\n      apiClient: {\n        // Most commonly used, official API provider.\n        url: 'https://toncenter.com',\n\n        // A key to access higher RPS limits.\n        // Get it from https://t.me/toncenter\n        key: '<MAINNET_API_KEY>',\n      },\n    },\n    // Testing network. For experiments, beta tests, and feature previews.\n    [Network.testnet().chainId]: {\n      apiClient: {\n        url: 'https://testnet.toncenter.com',\n        key: '<TESTNET_API_KEY>',\n      },\n    },\n  },\n\n  // 2. Specify core information and constraints of the given wallet.\n  deviceInfo: createDeviceInfo({\n    // Version of your wallet\n    appVersion: '0.0.1',\n\n    // The rest of the params will have default values set for you,\n    // including the features your wallet should support,\n    // maximum supported TON Connect protocol version,\n    // human-readable name of your wallet,\n    // and a current platform ('browser').\n  }),\n\n  // 3. Specify the TON Connect's wallet manifest.\n  //    The following function provides initial defaults,\n  //    but you may want to specify some custom values,\n  //    such as the human-readable name of your wallet or its icon image url.\n  walletManifest: createWalletManifest(),\n\n  // 4. Specify the TON Connect's bridge settings\n  bridge: {\n    // The main TON Connect bridge for dApp communication.\n    // It is capable to withstand significant load.\n    //\n    // To self-host, see https://github.com/ton-connect/bridge\n    bridgeUrl: 'https://connect.ton.org/bridge',\n  },\n});\n\n// 5. Finally, wait for the initialization to complete\nawait kit.waitForReady();\n```\n\nSee also: [TON Connect's wallet manifest](/ecosystem/ton-connect/manifest#wallet-manifest).\n\n<Aside\n  type=\"caution\"\n  title=\"Web only!\"\n>\n  The given example must be invoked in **browser environments only**. To run it locally with Node.js or other JS runtimes, set `storage.allowMemory` to `true`. It enables a built-in storage adapter for non-browser environments that do not have `localStorage` available.\n\n  ```ts\n  const kit = new TonWalletKit({\n    // ...prior fields...\n    storage: { allowMemory: true },\n    // ...later fields...\n  });\n  ```\n\n  Remember to disable this adapter in web environments or provide a dedicated [`storage` adapter](#param-storage) wrapper to switch between environments.\n</Aside>\n\n## Configuration parameters\n\n### Required\n\n<ParamField\n  path=\"networks\"\n  type=\"Record<CHAIN, NetworkConfig>\"\n  required\n>\n  For one or more TON networks, configure their respective API or RPC providers to interact with.\n\n  ```ts\n  import { Network } from '@ton/walletkit';\n\n  new TonWalletKit({\n    networks: {\n      // Production network. All contracts and funds are real.\n      [Network.mainnet().chainId]: { // \"-239\"\n        apiClient: {\n          // Most commonly used, official API provider.\n          //\n          // To self-host, see:\n          // * Real-time API: https://github.com/toncenter/ton-http-api-cpp\n          // * Indexer: https://github.com/toncenter/ton-indexer\n          // It is important to put real-time API under `/api/v2` route and indexer API under `/api/v3` route.\n          url: 'https://toncenter.com',\n\n          // Optional key to access higher RPS limits.\n          key: '<MAINNET_API_KEY>',\n        },\n      },\n      // Testing network. For experiments, beta tests, and feature previews.\n      [Network.testnet().chainId]: { // \"-3\"\n        apiClient: {\n          url: 'https://testnet.toncenter.com',\n          key: '<TESTNET_API_KEY>',\n        },\n      },\n    },\n    // ...later fields...\n  });\n  ```\n\n  It is also possible to provide an entirely custom provider with its own `ApiClient` interface implementation.\n\n  ```ts\n  import { Network } from '@ton/walletkit';\n\n  new TonWalletKit({\n    networks: {\n      [Network.testnet().chainId]: { // \"-3\"\n        apiClient: /*  A complete ApiClient interface implementation */,\n      },\n    },\n    // ...later fields...\n  });\n  ```\n</ParamField>\n\n### Optional\n\n<ParamField\n  path=\"deviceInfo\"\n  type=\"DeviceInfo\"\n>\n  Core information and constraints of the given wallet. If not provided, defaults will be used.\n\n  ```ts\n  interface DeviceInfo {\n    // Name of the wallet.\n    appName: string;\n\n    // The platform it works on. Select 'browser' for the web wallets.\n    platform: 'iphone' | 'ipad' | 'android' | 'windows' | 'mac' | 'linux' | 'browser';\n\n    // The current wallet version.\n    appVersion: string;\n\n    // Latest protocol version to use.\n    maxProtocolVersion: number;\n\n    // Which features are supported in the wallet.\n    features: Feature[];\n  }\n  ```\n\n  There, `Feature` type is defined as:\n\n  ```ts\n  type Feature =\n    | {\n        // Wallet can send transactions.\n        name: \"SendTransaction\";\n\n        // Max number of messages that can be sent in a single transaction.\n        // Depends on the TON wallet used, because different kinds can handle\n        // different number of messages. For example,\n        // - ledger wallet would only handle 1 message per transaction\n        // - wallet v4r2 handles up to 4 messages\n        // - wallet v5r1 handles up to 255 messages\n        maxMessages: number;\n\n        // Are messages sending extra-currencies supported?\n        extraCurrencySupported?: boolean;\n      }\n    | {\n        // Wallet can sign data.\n        name: \"SignData\";\n\n        // A type of data to sign.\n        // Either of: \"text\", \"binary\", \"cell\".\n        types: SignDataType[];\n      }\n  ```\n\n  The `maxMessages` number depends on the TON wallet used, because every wallet has its own limit on the volume of messages.\n\n  For example,\n\n  - Ledger wallet would only handle 1 message per transaction\n  - Wallet `v4r2` handles up to 4 messages\n  - Wallet `v5r1` handles up to 255 messages\n</ParamField>\n\n<ParamField\n  path=\"walletManifest\"\n  type=\"WalletInfo\"\n>\n  How your wallet interacts with the TON Connect. If not provided, defaults will be used. This field is closely related to the [corresponding JSON manifest file](/ecosystem/ton-connect/manifest#wallet-manifest).\n\n  ```ts expandable\n  interface WalletInfo {\n    /**\n     * Human-readable name of the wallet.\n     */\n    name: string;\n\n    /**\n     * ID of the wallet, equals to the `appName` property of the `deviceInfo`.\n     */\n    appName: string;\n\n    /**\n     * Url to the icon of the wallet. Resolution 288×288px. On a non-transparent background, without rounded corners. PNG format.\n     */\n    imageUrl: string;\n\n    /**\n     * Will be used in the protocol later.\n     */\n    tondns?: string;\n\n    /**\n     * Info or landing page of your wallet. It may be useful for TON newcomers.\n     */\n    aboutUrl: string;\n\n    /**\n     * List of features supported by the wallet.\n     */\n    features?: Feature[];\n\n    /**\n     * OS and browsers where the wallet could be installed\n     */\n    platforms: ('ios' | 'android' | 'macos' | 'windows' | 'linux' | 'chrome' | 'firefox' | 'safari')[];\n\n    /**\n     * Base part of the wallet universal url. The link should support TON Connect parameters: https://github.com/ton-connect/docs/blob/main/bridge.md#universal-link.\n     */\n    universalLink: string;\n\n    /**\n     * Native wallet app deep link. The link should support TON Connect parameters: https://github.com/ton-connect/docs/blob/main/bridge.md#universal-link.\n     */\n    deepLink?: string;\n\n    /**\n     * Url of the wallet's implementation of the HTTP bridge: https://github.com/ton-connect/docs/blob/main/bridge.md#http-bridge.\n     */\n    bridgeUrl: string;\n\n    // JS-injectable wallet information\n\n    /**\n     * If the wallet handles JS Bridge connection, specifies the binding for the bridge object accessible through window. Example: the key \"tonkeeper\" means the bridge can be accessed as window.tonkeeper.\n     */\n    jsBridgeKey: string;\n\n    /**\n     * Indicates if the wallet currently is injected to the webpage.\n     */\n    injected: boolean;\n\n    /**\n     * Indicates if the dapp is opened inside this wallet's browser.\n     */\n    embedded: boolean;\n  }\n  ```\n</ParamField>\n\n<ParamField\n  path=\"bridge\"\n  type=\"BridgeConfig\"\n>\n  Connectivity options: either an HTTP or JavaScript bridge setup. The former's `bridgeUrl` points to the publicly exposed bridge URL, while the latter's `jsBridgeKey` points to the property name within the `window` object on the same web page.\n\n  Bridges are used for dApp communication — if the dApp exists in the same web environment as the wallet, then the JavaScript bridge is enough. Otherwise, use an HTTP bridge setup.\n\n  <Aside>\n    For HTTP bridge setups, use a publicly available and production-ready bridge deployed at `https://connect.ton.org/bridge`.\n  </Aside>\n\n  ```ts\n  interface BridgeConfig {\n    // Defaults to `walletInfo`'s `bridgeUrl`, if it exists\n    bridgeUrl?: string;\n\n    // Defaults to true if `walletInfo`'s `jsBridgeKey` exists\n    enableJsBridge?: boolean;\n\n    // Defaults to `walletInfo`'s `jsBridgeKey`, if it exists\n    jsBridgeKey?: string;\n\n    // Defaults to false\n    disableHttpConnection?: boolean;\n\n    // Settings for bridge-sdk\n    heartbeatInterval?: number;\n    reconnectInterval?: number;\n    maxReconnectAttempts?: number;\n  }\n  ```\n</ParamField>\n\n<ParamField\n  path=\"storage\"\n  type=\"StorageConfig | StorageAdapter\"\n>\n  How to store intermediate events.\n\n  ```ts\n  // Either a small object:\n  interface StorageConfig {\n    prefix?: string;\n    maxRetries?: number;\n    retryDelay?: number;\n    allowMemory?: boolean;\n  }\n\n  // Or a complete StorageAdapter interface implementation:\n  interface StorageAdapter {\n    get(key: string): Promise<string | null>;\n    set(key: string, value: string): Promise<void>;\n    remove(key: string): Promise<void>;\n    clear(): Promise<void>;\n  }\n  ```\n</ParamField>\n\n<ParamField\n  path=\"eventProcessor\"\n  type=\"EventProcessorConfig\"\n>\n  How TON Connect events are processed. This is useful for background scripts in browser extensions that process incoming events and log them, but do so outside a queue.\n\n  ```ts\n  interface EventProcessorConfig {\n    disableEvents?: boolean;\n\n    // If true, transaction events will not be emulated,\n    // and their `preview` field will be undefined.\n    disableTransactionEmulation?: boolean;\n  }\n  ```\n</ParamField>\n\n<ParamField\n  path=\"analytics\"\n  type=\"AnalyticsConfig\"\n>\n  Collect and gather analytical data.\n\n  ```ts\n  interface AnalyticsConfig {\n    enabled?: boolean;\n\n    // A web URL to send analytics data to.\n    endpoint?: string;\n  }\n  ```\n</ParamField>\n\n<ParamField\n  path=\"dev\"\n  type=\"object\"\n>\n  Extra configuration used when developing WalletKit itself. Irrelevant in other cases.\n</ParamField>\n\n## Next steps\n\n<Columns cols={2}>\n  <Card\n    title=\"Manage TON wallets\"\n    icon=\"wallet\"\n    horizontal=\"true\"\n    href=\"/ecosystem/walletkit/web/wallets\"\n  />\n\n  <Card\n    title=\"Handle connections\"\n    icon=\"plug\"\n    horizontal=\"true\"\n    href=\"/ecosystem/walletkit/web/connections\"\n  />\n</Columns>\n\n## See also\n\n- [WalletKit overview](/ecosystem/walletkit/overview)\n- [TON Connect's wallet manifest](/ecosystem/ton-connect/manifest#wallet-manifest)\n- [TON Connect overview](/ecosystem/ton-connect/overview)\n"
  },
  {
    "path": "ecosystem/walletkit/web/jettons.mdx",
    "content": "---\ntitle: \"How to work with Jettons using WalletKit on the Web platform\"\nsidebarTitle: \"Work with Jettons\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside>\n  [Initialize the WalletKit](/ecosystem/walletkit/web/init), [set up at least one TON wallet](/ecosystem/walletkit/web/wallets), handle [connection requests](/ecosystem/walletkit/web/connections) and [transaction requests](/ecosystem/walletkit/web/events) before using examples on this page.\n</Aside>\n\n[Jettons](/standard/tokens/jettons/overview) are fungible tokens on TON, similar to ERC-20 tokens on Ethereum. Unlike Toncoin, which is the native TON currency used in all transfers, each Jetton has a separate master (minter) contract and an individual wallet contract for each holder.\n\nFor example, USDT on TON is implemented as a Jetton, and its minter contract address is `EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs`. By providing this address and the recipient's TON wallet contract address, WalletKit knows which tokens to send and to whom.\n\nTo work with Jettons, the wallet service needs to handle [Jetton balances](#balances) and perform transfers initiated [from dApps](#transfers-from-dapps) and [from within the wallet service itself](#transfers-in-the-wallet-service).\n\n<Aside\n  type=\"caution\"\n  title=\"Decimals matter\"\n>\n  Each Jetton stores a [`decimals`](/standard/tokens/metadata#decimals) parameter in its metadata. Transferring without accounting for `decimals` can result in sending drastically more tokens than expected — irreversible on mainnet.\n\n  Mitigation: Always retrieve and apply the correct `decimals` value. Test on testnet first.\n</Aside>\n\n## Balances\n\nJetton balances are stored in individual Jetton wallet contracts, one per holder per Jetton kind.\n\nIt is possible to obtain the current Jetton balance by providing the address of the Jetton master (minter) contract for a given Jetton, or by querying a TON wallet. The latter can be done either by the `getJettons()` method of wallet adapters or by calling `kit.jettons.getAddressJettons()` and passing it the TON wallet address.\n\nSimilar to Toncoin balance checks, [discrete one-off checks](#on-demand-balance-check) have limited value on their own and [continuous monitoring](#continuous-balance-monitoring) should be used for UI display.\n\n### On-demand balance check\n\nUse the `getJettonBalance()` method to check a specific Jetton balance for a wallet managed by WalletKit. The balance is returned in the smallest Jetton unit, where `1` token equals 10<sup>decimals</sup> smallest units.\n\n<Aside\n  type=\"caution\"\n>\n  Do not store the balance check results anywhere in the wallet service's state, as they become outdated very quickly. For UI purposes, do [continuous balance monitoring](#continuous-balance-monitoring).\n</Aside>\n\n```ts title=\"TypeScript\"\n// Jetton master (minter) contract address\n// E.g., USDT on TON has the following address in mainnet:\n// EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs\nconst JETTON_MASTER_ADDRESS = '<JETTON_MASTER_ADDRESS>';\n\nasync function getJettonBalance(walletId: string): Promise<string | undefined> {\n  // Get TON wallet instance\n  const wallet = kit.getWallet(walletId);\n  if (!wallet) return;\n\n  // Query Jetton balance in smallest Jetton units\n  return await wallet.getJettonBalance(JETTON_MASTER_ADDRESS);\n}\n```\n\nThe most practical use of one-off balance checks is right before approving a transaction request. At this point, the actual balance usually is not less than the checked amount, though it might be higher if new funds arrived right after the check.\n\n<Aside>\n  Despite this check, the transaction may still fail due to insufficient balance at the time of transfer.\n</Aside>\n\n```ts title=\"TypeScript\"\n// An enumeration of various common error codes\nimport { SEND_TRANSACTION_ERROR_CODES } from '@ton/walletkit';\n\n// Address of the Jetton master (minter) contract\nconst JETTON_MASTER_ADDRESS = '<JETTON_MASTER_ADDRESS>';\n\nkit.onTransactionRequest(async (event) => {\n  const wallet = kit.getWallet(event.walletId ?? '');\n  if (!wallet) {\n    console.error('Wallet not found for a transaction request', event);\n    await kit.rejectTransactionRequest(event, {\n      code: SEND_TRANSACTION_ERROR_CODES.UNKNOWN_ERROR,\n      message: 'Wallet not found',\n    });\n    return;\n  }\n\n  // Check Jetton balance before proceeding\n  const jettonBalance = BigInt(await wallet.getJettonBalance(JETTON_MASTER_ADDRESS));\n\n  // Calculate minimum needed from the transaction request:\n  // transfers include Toncoin for fees plus Jetton amounts\n  const minNeededJettons = calculateJettonAmount(event.request.messages);\n\n  // Reject early if Jetton balance is clearly insufficient\n  if (jettonBalance < minNeededJettons) {\n    await kit.rejectTransactionRequest(event, {\n      code: SEND_TRANSACTION_ERROR_CODES.BAD_REQUEST_ERROR,\n      message: 'Insufficient Jetton balance',\n    });\n    return;\n  }\n\n  // Proceed with the regular transaction flow\n  // ...\n});\n```\n\n### Continuous balance monitoring\n\nPoll the balance at regular intervals to keep the displayed value up to date. Use an appropriate interval based on UX requirements — shorter intervals provide fresher data but increase API usage.\n\nThis example should be modified according to the wallet service's logic:\n\n```ts title=\"TypeScript\" expandable\n// Not runnable: implement the updateUI()!\n\n/**\n * Starts the monitoring of a given wallet's Jetton balance,\n * calling `onBalanceUpdate()` every `intervalMs` milliseconds\n *\n * @returns a function to stop monitoring\n */\nexport function startJettonBalanceMonitoring(\n  walletId: string,\n  jettonMasterAddress: string,\n  onBalanceUpdate: (balance: string) => void,\n  intervalMs: number = 10_000,\n): () => void {\n  let isRunning = true;\n\n  const poll = async () => {\n    while (isRunning) {\n      const wallet = kit.getWallet(walletId);\n      if (wallet) {\n        const balance = await wallet.getJettonBalance(jettonMasterAddress);\n        onBalanceUpdate(balance);\n      }\n      await new Promise((resolve) => setTimeout(resolve, intervalMs));\n    }\n  };\n\n  // Start monitoring\n  poll();\n\n  // Return a cleanup function to stop monitoring\n  return () => {\n    isRunning = false;\n  };\n}\n\n// Usage\nconst stopMonitoring = startJettonBalanceMonitoring(\n  walletId,\n  // Jetton master (minter) contract address\n  // E.g., USDT on TON mainnet:\n  'EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs',\n  // The updateUI() function is exemplary and should be replaced by\n  // a wallet service function that refreshes the\n  // state of the balance displayed in the interface\n  (balance) => updateUI(balance),\n);\n\n// Stop monitoring once it is no longer needed\nstopMonitoring();\n```\n\n## Transfers from dApps\n\nWhen a connected dApp requests a Jetton transfer, the wallet service follows the same flow as [Toncoin transfers](/ecosystem/walletkit/web/toncoin#transfers-from-dapps): the dApp sends a transaction request through the bridge, WalletKit emulates it and presents a preview, the user approves or declines, and the result is returned to the dApp.\n\n```ts title=\"TypeScript\"\nkit.onTransactionRequest(async (event) => {\n  if (!event.preview.data) {\n    console.warn('Transaction emulation skipped');\n  } else if (event.preview.data?.result === 'success') {\n    // Emulation succeeded — show the predicted money flow\n    const { ourTransfers } = event.preview.data.moneyFlow;\n\n    // This is an array of values,\n    // where positive amounts mean incoming funds\n    // and negative amounts — outgoing funds.\n    console.log('Predicted transfers:', ourTransfers);\n\n    // Filter Jetton transfers specifically\n    const jettonTransfers = ourTransfers.filter(\n      (transfer) => transfer.assetType === 'jetton',\n    );\n    console.log('Jetton transfers:', jettonTransfers);\n  } else {\n    // Emulation failed — warn the user but allow proceeding\n    console.warn('Transaction emulation failed:', event.preview);\n  }\n\n  // By knowing the Jetton master (minter) contract address,\n  // one can obtain and preview Jetton's name, symbol and image.\n  //\n  // Present the enriched preview to the user and await their decision.\n  // ...\n});\n```\n\nThere is an additional consideration for Jetton transfers: they involve multiple internal messages between contracts. As such, Jetton transfers always take longer than regular Toncoin-only transfers.\n\nAs with Toncoin transfers, the wallet service should not block the UI while waiting for confirmation. With [continuous wallet balance monitoring](#continuous-balance-monitoring) and subsequent transaction requests, users will receive the latest information either way. Confirmations are only needed to display a list of past transactions reliably.\n\n## Transfers in the wallet service\n\nJetton transactions can be created directly from the wallet service (not from dApps) and fed into the regular approval flow via the `handleNewTransaction()` method of the WalletKit. It creates a new [transaction request event](/ecosystem/walletkit/web/events#handle-ontransactionrequest), enabling the same UI confirmation-to-transaction flow for both dApp-initiated and wallet-initiated transactions.\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  Verify the `decimals` value from the Jetton metadata before calculating transfer amounts. Incorrect decimals can result in sending drastically more or fewer tokens than intended.\n\n  For USDTs, the correct decimals value is 6.\n</Aside>\n\nThis example should be modified according to the wallet service's logic:\n\n```ts title=\"TypeScript\"\nimport { type JettonsTransferRequest } from '@ton/walletkit';\n\nasync function sendJetton(\n  // Sender's TON `walletId` as a string\n  walletId: string,\n  // Jetton master (minter) contract address\n  jettonAddress: string,\n  // Recipient's TON wallet address as a string\n  recipientAddress: string,\n  // Amount in the smallest Jetton units (accounting for decimals)\n  jettonAmount: bigint,\n  // Optional comment string\n  comment?: string,\n) {\n  const fromWallet = kit.getWallet(walletId);\n  if (!fromWallet) {\n    console.error('No wallet contract found');\n    return;\n  }\n\n  const transferParams: JettonsTransferRequest = {\n    jettonAddress,\n    recipientAddress,\n    transferAmount: jettonAmount.toString(),\n    // Optional comment\n    ...(comment && { comment: comment }),\n  };\n\n  // Build transaction content\n  const tx = await fromWallet.createTransferJettonTransaction(transferParams);\n\n  // Route into the normal flow,\n  // triggering the onTransactionRequest() handler\n  await kit.handleNewTransaction(fromWallet, tx);\n}\n```\n\n<Aside\n  type=\"caution\"\n>\n  To avoid triggering the `onTransactionRequest()` handler and send the transaction directly, use the `sendTransaction()` method of the wallet instead of the `handleNewTransaction()` method of the WalletKit, modifying the last part of the previous code snippet:\n\n  ```ts title=\"TypeScript\"\n  // Instead of calling kit.handleNewTransaction(fromWallet, tx)\n  // one can avoid routing into the normal flow,\n  // skip the transaction requests handler,\n  // and make the transaction directly.\n  await fromWallet.sendTransaction(tx);\n  ```\n\n  Do not use this approach unless it is imperative to complete a transaction without the user's direct consent. Funds at risk: test this approach using testnet and proceed with utmost caution.\n</Aside>\n\n## See also\n\nJettons:\n\n- [Jettons overview](/standard/tokens/jettons/overview)\n- [Jetton transfers](/standard/tokens/jettons/transfer)\n- [Token metadata and decimals](/standard/tokens/metadata#decimals)\n\nGeneral:\n\n- [Handle transaction requests](/ecosystem/walletkit/web/events#handle-ontransactionrequest)\n- [Transaction fees](/foundations/fees)\n- [WalletKit overview](/ecosystem/walletkit/overview)\n- [TON Connect overview](/ecosystem/ton-connect/overview)\n"
  },
  {
    "path": "ecosystem/walletkit/web/nfts.mdx",
    "content": "---\ntitle: \"How to work with NFTs using WalletKit on the Web platform\"\nsidebarTitle: \"Work with NFTs\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside>\n  [Initialize the WalletKit](/ecosystem/walletkit/web/init), [set up at least one TON wallet](/ecosystem/walletkit/web/wallets), handle [connection requests](/ecosystem/walletkit/web/connections) and [transaction requests](/ecosystem/walletkit/web/events) before using examples on this page.\n</Aside>\n\n[NFTs](/standard/tokens/nft/overview) (non-fungible tokens) are unique digital assets on TON, similar to ERC-721 tokens on Ethereum. Unlike jettons, which are fungible and interchangeable, each NFT is unique and represents ownership of a specific item. NFTs consist of a collection contract and individual NFT item contracts for each token.\n\nTo work with NFTs, the wallet service needs to handle [NFT ownership queries](#ownership) and perform transfers initiated [from dApps](#transfers-from-dapps) and [from within the wallet service itself](#transfers-in-the-wallet-service).\n\n<Aside\n  type=\"caution\"\n  title=\"Verify NFT authenticity\"\n>\n  Before displaying or transferring NFTs, verify they belong to legitimate collections. Scammers may create fake NFTs mimicking popular collections.\n\n  Mitigation: Always verify the collection address matches the official one. Check NFT metadata for suspicious content.\n</Aside>\n\n## Ownership\n\nNFT ownership is tracked through individual NFT item contracts. Unlike jettons, which have a balance, one either owns a specific NFT item or does not.\n\nTo obtain a list of NFTs owned by a user, query their TON wallet by either the `getNfts()` method of wallet adapters or by calling `kit.nfts.getAddressNfts()` and passing it the TON wallet address.\n\nSimilar to other asset queries, [discrete one-off checks](#on-demand-ownership-check) have limited value on their own and [continuous monitoring](#continuous-ownership-monitoring) should be used for UI display.\n\n### On-demand ownership check\n\nUse the `getNfts()` method to check which NFTs are owned by a wallet managed by WalletKit. The method returns an array of NFT items with their addresses, collection info, and metadata.\n\n<Aside\n  type=\"caution\"\n>\n  Do not store the ownership check results anywhere in the wallet service's state, as they become outdated very quickly. For UI purposes, do [continuous ownership monitoring](#continuous-ownership-monitoring).\n</Aside>\n\n```ts title=\"TypeScript\"\nasync function getNfts(walletId: string): Promise<NftItem[] | undefined> {\n  // Get TON wallet instance\n  const wallet = kit.getWallet(walletId);\n  if (!wallet) return;\n\n  // Query 100 NFTs owned by this wallet\n  const ownedNfts = await wallet.getNfts({ pagination: { limit: 100 } });\n\n  // Optionally filter by a specific collection address\n  const collectionNfts = ownedNfts.nfts.filter(\n    (nft) => nft.collection?.address === '<NFT_COLLECTION_ADDRESS>',\n  );\n\n  return collectionNfts;\n}\n```\n\nThe most practical use of one-off ownership checks is right before approving an NFT transfer request. At this point, verify that the wallet actually owns the NFT being transferred.\n\n<Aside type=\"note\">\n  Despite this check, the transaction may still fail if the NFT is not owned or unaccessible at the time of transfer.\n</Aside>\n\n```ts title=\"TypeScript\"\n// An enumeration of various common error codes\nimport { SEND_TRANSACTION_ERROR_CODES } from '@ton/walletkit';\n\n// Address of the NFT item contract\nconst NFT_ITEM_ADDRESS = '<NFT_ITEM_ADDRESS>';\n\nkit.onTransactionRequest(async (event) => {\n  const wallet = kit.getWallet(event.walletId ?? '');\n  if (!wallet) {\n    console.error('Wallet not found for a transaction request', event);\n    await kit.rejectTransactionRequest(event, {\n      code: SEND_TRANSACTION_ERROR_CODES.UNKNOWN_ERROR,\n      message: 'Wallet not found',\n    });\n    return;\n  }\n\n  // Verify ownership\n  const ownsNft = await wallet.getNft(NFT_ITEM_ADDRESS);\n\n  // Reject early if NFT is not owned\n  if (!ownsNft) {\n    await kit.rejectTransactionRequest(event, {\n      code: SEND_TRANSACTION_ERROR_CODES.BAD_REQUEST_ERROR,\n      message: 'NFT not owned by this wallet',\n    });\n    return;\n  }\n\n  // Proceed with the regular transaction flow\n  // ...\n});\n```\n\n### Continuous ownership monitoring\n\nPoll the NFT ownership at regular intervals to keep the displayed information up to date. Use an appropriate interval based on UX requirements — shorter intervals provide fresher data but increase API usage.\n\nThis example should be modified according to the wallet service's logic:\n\n```ts title=\"TypeScript\" expandable\nimport { type NFT } from '@ton/walletkit';\n\n// Configuration\nconst POLLING_INTERVAL_MS = 15_000;\n\n/**\n * Starts the monitoring of a given wallet's NFT ownership,\n * calling `onNftsUpdate()` every `intervalMs` milliseconds\n *\n * @returns a function to stop monitoring\n */\nexport function startNftOwnershipMonitoring(\n  walletId: string,\n  onNftsUpdate: (nfts: NFT[]) => void,\n  intervalMs: number = POLLING_INTERVAL_MS,\n): () => void {\n  let isRunning = true;\n\n  const poll = async () => {\n    while (isRunning) {\n      const wallet = kit.getWallet(walletId);\n      if (wallet) {\n        // Only looks for up to 100 NFTs.\n        // To get more, call the `getNfts()` function\n        // multiple times with increasing offsets\n        const { nfts } = await wallet.getNfts({ pagination: { limit: 100 } });\n        onNftsUpdate(nfts);\n      }\n      await new Promise((resolve) => setTimeout(resolve, intervalMs));\n    }\n  };\n\n  // Start monitoring\n  poll();\n\n  // Return a cleanup function to stop monitoring\n  return () => {\n    isRunning = false;\n  };\n}\n\n// Usage\nconst stopMonitoring = startNftOwnershipMonitoring(\n  walletId,\n  // The updateNftGallery() function is exemplary and should be replaced by\n  // a wallet service function that refreshes the\n  // NFT gallery displayed in the interface\n  (nfts) => updateNftGallery(nfts),\n);\n\n// Stop monitoring once it is no longer needed\nstopMonitoring();\n```\n\n## Transfers from dApps\n\nWhen a connected dApp requests an NFT transfer, the wallet service follows the same flow as [Toncoin transfers](/ecosystem/walletkit/web/toncoin#transfers-from-dapps): the dApp sends a transaction request through the bridge, WalletKit emulates it and presents a preview, the user approves or declines, and the result is returned to the dApp.\n\n```ts title=\"TypeScript\"\nkit.onTransactionRequest(async (event) => {\n  if (!event.preview.data) {\n    console.warn('Transaction emulation skipped');\n  } else if (event.preview.data?.result === 'success') {\n    // Emulation succeeded — show the predicted asset flow\n    const { ourTransfers } = event.preview.data.moneyFlow;\n\n    // This is an array of values,\n    // where positive amounts mean incoming assets\n    // and negative amounts — outgoing assets.\n    console.log('Predicted transfers:', ourTransfers);\n\n    // Filter NFT transfers specifically\n    const nftTransfers = ourTransfers.filter(\n      (transfer) => transfer.assetType === 'nft',\n    );\n    console.log('NFT transfers:', nftTransfers);\n  } else {\n    // Emulation failed — warn the user but allow proceeding\n    console.warn('Transaction emulation failed:', event.preview);\n  }\n\n  // By knowing the NFT item contract address,\n  // one can obtain and preview NFT's name, description, image, and attributes.\n  //\n  // Present the enriched preview to the user and await their decision.\n  // ...\n});\n```\n\nThere is an additional consideration for NFT transfers: they involve multiple internal messages between contracts. As such, NFT transfers always take longer than regular Toncoin-only transfers.\n\nAs with Toncoin transfers, the wallet service should not block the UI while waiting for confirmation. With [continuous NFT ownership monitoring](#continuous-ownership-monitoring) and subsequent transaction requests, users will receive the latest information either way. Confirmations are only needed to display a list of past transactions reliably.\n\n## Transfers in the wallet service\n\nNFT transactions can be created directly from the wallet service (not from dApps) and fed into the regular approval flow via the `handleNewTransaction()` method of the WalletKit. It creates a new [transaction request event](/ecosystem/walletkit/web/events#handle-ontransactionrequest), enabling the same UI confirmation-to-transaction flow for both dApp-initiated and wallet-initiated transactions.\n\n<Aside\n  type=\"danger\"\n  title=\"Assets at risk\"\n>\n  Verify the NFT address before initiating a transfer. Transferring an NFT is irreversible — once sent, only the new owner can transfer it back.\n\n  Double-check the recipient address to avoid permanent loss of valuable NFTs.\n</Aside>\n\nThis example should be modified according to the wallet service's logic:\n\n```ts title=\"TypeScript\"\nimport { type NFTTransferRequest } from '@ton/walletkit';\n\nasync function sendNft(\n  // Sender's TON `walletId` as a string\n  walletId: string,\n  // NFT item contract address\n  nftAddress: string,\n  // Recipient's TON wallet address as a string\n  recipientAddress: string,\n  // Optional comment string\n  comment?: string,\n) {\n  const fromWallet = kit.getWallet(walletId);\n  if (!fromWallet) {\n    console.error('No wallet contract found');\n    return;\n  }\n\n  // Verify ownership before creating the transfer\n  const ownsNft = await fromWallet.getNft(nftAddress);\n  if (!ownsNft) {\n    console.error('NFT not owned by this wallet');\n    return;\n  }\n\n  const transferParams: NFTTransferRequest = {\n    nftAddress,\n    recipientAddress,\n    // Optional comment\n    ...(comment && { comment }),\n  };\n\n  // Build transaction content\n  const tx = await fromWallet.createTransferNftTransaction(transferParams);\n\n  // Route into the normal flow,\n  // triggering the onTransactionRequest() handler\n  await kit.handleNewTransaction(fromWallet, tx);\n}\n```\n\n<Aside\n  type=\"caution\"\n>\n  To avoid triggering the `onTransactionRequest()` handler and send the transaction directly, use the `sendTransaction()` method of the wallet instead of the `handleNewTransaction()` method of the WalletKit, modifying the last part of the previous code snippet:\n\n  ```ts title=\"TypeScript\"\n  // Instead of calling kit.handleNewTransaction(fromWallet, tx)\n  // one can avoid routing into the normal flow,\n  // skip the transaction requests handler,\n  // and make the transaction directly.\n  await fromWallet.sendTransaction(tx);\n  ```\n\n  Do not use this approach unless it is imperative to complete a transaction without the user's direct consent. Assets at risk: proceed with utmost caution.\n</Aside>\n\n## See also\n\nNFTs:\n\n- [NFT overview](/standard/tokens/nft/overview)\n- [NFT metadata](/standard/tokens/nft/metadata)\n\nGeneral:\n\n- [Handle transaction requests](/ecosystem/walletkit/web/events#handle-ontransactionrequest)\n- [Transaction fees](/foundations/fees)\n- [WalletKit overview](/ecosystem/walletkit/overview)\n- [TON Connect overview](/ecosystem/ton-connect/overview)\n"
  },
  {
    "path": "ecosystem/walletkit/web/toncoin.mdx",
    "content": "---\ntitle: \"How to work with Toncoin using WalletKit on the Web platform\"\nsidebarTitle: \"Work with Toncoin\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside>\n  [Initialize the WalletKit](/ecosystem/walletkit/web/init), [set up at least one TON wallet](/ecosystem/walletkit/web/wallets), handle [connection requests](/ecosystem/walletkit/web/connections) and [transaction requests](/ecosystem/walletkit/web/events) before using examples on this page.\n</Aside>\n\nTo work with Toncoin, the wallet service needs to handle [contract balances](#balances) and perform transfers initiated [from dApps](#transfers-from-dapps) and [from within the wallet service itself](#transfers-from-the-wallet-service).\n\n## Balances\n\nBlockchain state changes constantly as new blocks are produced. This has implications for when and how to check TON wallet contract balances:\n\n- [Discrete one-off checks](#on-demand-balance-check) have almost no value on their own — the state might change immediately after the query completes, invalidating its results. Thus, such checks are only practical when handling `transaction` requests.\n- [Continuous monitoring](#continuous-balance-monitoring) is useful for UI display, showing the most recent balance to users, but should not be used for transaction confirmations.\n\nNotice that both cases require querying the blockchain data via the API client set during the [WalletKit initialization](/ecosystem/walletkit/web/init#param-networks). Obtain and provide the key from the selected client to access higher requests-per-second limits.\n\n### On-demand balance check\n\nUse the `getBalance()` method to check the wallet contract balance in TON wallets managed by WalletKit. The balance is returned in nanoToncoin, with 1 Toncoin equal to 10<sup>9</sup> nanoToncoin.\n\n<Aside\n  type=\"caution\"\n>\n  Do not store the balance check results anywhere in the wallet service's state, as they become outdated very quickly. For UI purposes, do [continuous balance monitoring](#continuous-balance-monitoring).\n</Aside>\n\n```ts title=\"TypeScript\"\nasync function getBalance(walletId: string): Promise<string | undefined> {\n  // Get TON wallet instance\n  const wallet = kit.getWallet(walletId);\n  if (!wallet) return;\n\n  // Query its balance in nanoToncoin\n  return await wallet.getBalance();\n}\n```\n\nThe most practical use of one-off balance checks is right before approving a transaction request. At this point, the actual wallet contract balance usually is not less than the checked amount, though it might be higher if new funds arrived right after the check.\n\n<Aside>\n  Despite this check, the transaction may still fail due to insufficient balance at the time of transfer.\n</Aside>\n\n```ts title=\"TypeScript\"\n// An enumeration of various common error codes\nimport { SEND_TRANSACTION_ERROR_CODES } from '@ton/walletkit';\n\nkit.onTransactionRequest(async (event) => {\n  const wallet = kit.getWallet(event.walletId ?? '');\n  if (!wallet) {\n    console.error('Wallet not found for a transaction request', event);\n    await kit.rejectTransactionRequest(event, {\n      code: SEND_TRANSACTION_ERROR_CODES.UNKNOWN_ERROR,\n      message: 'Wallet not found',\n    });\n    return;\n  }\n\n  // Calculate the minimum balance needed for this transaction\n  const balance = BigInt(await wallet.getBalance());\n  const minNeededBalance = event.request.messages.reduce(\n    (acc, message) => acc + BigInt(message.amount),\n    0n,\n  );\n\n  // Reject early if balance is clearly insufficient\n  if (balance < minNeededBalance) {\n    await kit.rejectTransactionRequest(event, {\n      code: SEND_TRANSACTION_ERROR_CODES.BAD_REQUEST_ERROR,\n      message: 'Insufficient balance',\n    });\n    return;\n  }\n\n  // Proceed with the regular transaction flow\n  // ...\n});\n```\n\n### Continuous balance monitoring\n\nPoll the balance at regular intervals to keep the displayed value up to date. Use an appropriate interval based on UX requirements — shorter intervals provide fresher data but increase API usage.\n\nThis example should be modified according to the wallet service's logic:\n\n```ts title=\"TypeScript\" expandable\n// Not runnable: implement the updateUI()!\n\n/**\n * Starts the monitoring of a given `walletId`,\n * calling `onBalanceUpdate()` every `intervalMs` milliseconds\n *\n * @returns a function to stop monitoring\n */\nexport function startBalanceMonitoring(\n  walletId: string,\n  onBalanceUpdate: (balance: string) => void,\n  intervalMs: number = 10_000,\n): () => void {\n  let isRunning = true;\n\n  const poll = async () => {\n    while (isRunning) {\n      const wallet = kit.getWallet(walletId);\n      if (wallet) {\n        const balance = await wallet.getBalance();\n        onBalanceUpdate(balance);\n      }\n      await new Promise((resolve) => setTimeout(resolve, intervalMs));\n    }\n  };\n\n  // Start monitoring\n  poll();\n\n  // Return a cleanup function to stop monitoring\n  return () => {\n    isRunning = false;\n  };\n}\n\n// Usage\nconst stopMonitoring = startBalanceMonitoring(\n  walletId,\n  // The updateUI() function is exemplary and should be replaced by\n  // a wallet service function that refreshes the\n  // state of the balance displayed in the interface\n  (balance) => updateUI(balance),\n);\n\n// Stop monitoring once it is no longer needed\nstopMonitoring();\n```\n\n## Transfers from dApps\n\nWhen a connected dApp requests a Toncoin transfer, the wallet service follows this flow:\n\n```mermaid\nsequenceDiagram\n    participant dApp\n    participant Bridge\n    participant WalletKit\n    participant User\n    participant Blockchain\n\n    dApp->>Bridge: Send transaction request\n    Bridge->>WalletKit: Forward request\n    WalletKit->>WalletKit: Emulate transaction\n    WalletKit->>User: Show preview (money flow)\n    User-->>WalletKit: Approve / Decline\n    alt Approved\n        WalletKit->>Blockchain: Send transaction\n        WalletKit->>Bridge: Return success + BoC\n        Bridge->>dApp: Transaction sent\n    else Declined\n        WalletKit->>Bridge: Return rejection\n        Bridge->>dApp: User rejected\n    end\n```\n\n### Emulation and preview\n\nWalletKit tries to automatically emulate every incoming transaction request before presenting it to the user. The emulation result is available in the `event.preview.data` object, which can be `undefined` if emulation was skipped:\n\n```ts title=\"TypeScript\"\nkit.onTransactionRequest(async (event) => {\n  if (!event.preview.data) {\n    console.log('Transaction emulation skipped');\n  } else if (event.preview.data.result === 'success') {\n    // Emulation succeeded — show the predicted money flow\n    const { ourTransfers } = event.preview.data.moneyFlow;\n\n    // This is an array of values,\n    // where positive amounts mean incoming funds\n    // and negative amounts — outgoing funds\n    console.log('Predicted transfers:', ourTransfers);\n  } else {\n    // Emulation failed — warn the user but allow proceeding\n    console.warn('Transaction emulation failed:', event.preview);\n  }\n\n  // Present the preview to the user and await their decision\n  // ...\n});\n```\n\n<Aside>\n  Emulation uses the API client configured during [WalletKit initialization](/ecosystem/walletkit/web/init#param-networks).\n</Aside>\n\n### Approve or reject\n\nAfter showing the preview, handle the user's decision:\n\n```ts title=\"TypeScript\" expandable\nimport {\n  // An enumeration of various common error codes\n  SEND_TRANSACTION_ERROR_CODES,\n  // The transfer type\n  type TransactionTraceMoneyFlowItem,\n} from '@ton/walletkit';\n\nkit.onTransactionRequest(async (event) => {\n  try {\n    // Show the emulation preview to the wallet service user\n    const preview = event.preview;\n    const isEmulationSuccessful = preview.data?.result === 'success';\n\n    // Build a confirmation message\n    let confirmMessage = 'Confirm this transaction?';\n    if (isEmulationSuccessful) {\n      const transfers = preview.data.moneyFlow?.ourTransfers || [];\n      confirmMessage = `Send ${formatTransfers(transfers)}?`;\n    } else {\n      confirmMessage = 'Emulation failed or skipped. Proceed anyway?';\n    }\n\n    // Handle user's decision\n    if (confirm(confirmMessage)) {\n      // Approve — this sends the transaction to the blockchain\n      // and returns the signed message BoC to the dApp\n      await kit.approveTransactionRequest(event);\n      console.log('Transaction approved and sent');\n    } else {\n      // Reject — notify the dApp that the user declined\n      await kit.rejectTransactionRequest(event, {\n        code: SEND_TRANSACTION_ERROR_CODES.USER_REJECTS_ERROR,\n        message: 'User rejected the transaction',\n      });\n    }\n  } catch (error) {\n    console.error('Transaction handler error:', error);\n    await kit.rejectTransactionRequest(event, {\n      code: SEND_TRANSACTION_ERROR_CODES.UNKNOWN_ERROR,\n      message: 'Transaction processing failed',\n    });\n  }\n});\n\nfunction formatTransfers(transfers: Array<TransactionTraceMoneyFlowItem>): string {\n  const formatNano = (value: string, decimals: number = 9): string => {\n    const bigintValue = BigInt(value);\n    const isNegative = bigintValue < 0n;\n    const absoluteValue = bigintValue < 0n ? -bigintValue : bigintValue;\n    const str = absoluteValue.toString().padStart(decimals + 1, '0');\n\n    const intPart = str.slice(0, -decimals) || '0';\n    const fracPart = str.slice(-decimals).replace(/0+$/, '');\n\n    const formatted = fracPart ? `${intPart}.${fracPart}` : intPart;\n    return `${isNegative ? '-' : ''}${formatted}`;\n  };\n\n  return transfers.map((t) => `${formatNano(t.amount)} ${t.assetType}`).join(', ');\n}\n```\n\n### Confirm transaction delivery\n\nTON achieves transaction [finality](https://en.wikipedia.org/wiki/Blockchain#Finality) after a single masterchain block confirmation, where new blocks are produced approximately every 3 seconds. Once a transaction appears in a masterchain block, it becomes irreversible.\n\nTherefore, to reliably confirm the transaction delivery and status, one needs to check whether a transaction has achieved masterchain finality using the selected API client.\n\nThat said, the wallet service should not block the UI while waiting for such confirmation. After all, with [continuous wallet balance monitoring](#continuous-balance-monitoring) and subsequent transaction requests, users will receive the latest information either way. Confirmations are only needed to reliably display a list of past transactions, including the most recent ones.\n\nFor detailed transaction tracking and message lookups, the [message lookup guide](/ecosystem/ton-connect/message-lookup) covers finding transactions by external message hash, waiting for confirmations, and applying message normalization.\n\n## Transfers in the wallet service\n\nTransactions can be created directly from the wallet service (not from dApps) and fed into the regular approval flow via `handleNewTransaction()` method of the WalletKit. It creates a new [transaction request event](/ecosystem/walletkit/web/events#handle-ontransactionrequest), enabling the same UI confirmation-to-transaction flow for both dApp-initiated and wallet-initiated transactions.\n\nThis example should be modified according to the wallet service's logic:\n\n```ts title=\"TypeScript\"\nimport type { TONTransferRequest, Base64String } from '@ton/walletkit';\n\nasync function sendToncoin(\n  // Sender's TON `walletId` as a string\n  walletId: string,\n  // Recipient's TON wallet address as a string\n  recipientAddress: string,\n  // Amount in nanoToncoins\n  nanoAmount: BigInt,\n  // Optional comment string\n  comment?: string,\n  // Optional payload body as a BoC in Base64-encoded string\n  payload?: Base64String,\n) {\n  if (comment && payload) {\n    console.error('Cannot attach both a comment or a payload body');\n    return;\n  }\n\n  const fromWallet = kit.getWallet(walletId);\n  if (!fromWallet) {\n    console.error('No wallet contract found');\n    return;\n  }\n\n  const transferParams: TONTransferRequest = {\n    recipientAddress: recipientAddress,\n    transferAmount: nanoAmount.toString(),\n    // Optional comment OR payload, not both\n    ...(comment && { comment }),\n    ...(payload && { payload }),\n  }\n\n  // Build transaction content\n  const tx = await fromWallet.createTransferTonTransaction(transferParams);\n\n  // Route into the normal flow,\n  // triggering the onTransactionRequest() handler\n  await kit.handleNewTransaction(fromWallet, tx);\n}\n```\n\n<Aside\n  type=\"caution\"\n>\n  To avoid triggering the `onTransactionRequest()` handler and send the transaction directly, use the `sendTransaction()` method of the wallet instead of the `handleNewTransaction()` method of the WalletKit, modifying the last part of the previous code snippet:\n\n  ```ts title=\"TypeScript\"\n  // Instead of calling kit.handleNewTransaction(fromWallet, tx)\n  // one can avoid routing into the normal flow,\n  // skip the transaction requests handler,\n  // and make the transaction directly.\n  await fromWallet.sendTransaction(tx);\n  ```\n\n  Do not use this approach unless it is imperative to complete a transaction without the user's direct consent. Funds at risk: test this approach using testnet and proceed with utmost caution.\n</Aside>\n\n## See also\n\n- [Handle transaction requests](/ecosystem/walletkit/web/events#handle-ontransactionrequest)\n- [Transaction fees](/foundations/fees)\n- [WalletKit overview](/ecosystem/walletkit/overview)\n- [TON Connect overview](/ecosystem/ton-connect/overview)\n"
  },
  {
    "path": "ecosystem/walletkit/web/wallets.mdx",
    "content": "---\ntitle: \"How to manage TON wallets with WalletKit on the Web platform\"\nsidebarTitle: \"Manage TON wallets\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside>\n  [Initialize the WalletKit](/ecosystem/walletkit/web/init) before using examples on this page.\n</Aside>\n\nThe [basic configuration earlier](/ecosystem/walletkit/web/init#initialization) is enough to outline necessary wallet information and initialize the WalletKit, but it isn't enough for deeper interactions with the blockchain. For that, you need to set up at least one TON wallet contract.\n\n## Initialization\n\n1. First, obtain the signer. It can be instantiated [from a mnemonic](#from-mnemonic), from [a private key](#from-private-key), or be [made custom](#from-custom-signer).\n\n1. Then, select a wallet adapter — it is an implementation of the `WalletInterface` type for a particular TON wallet contract. Currently, WalletKit provides two: `WalletV5R1Adapter` (recommended) and `WalletV4R2Adapter`.\n\n   Adapter takes in a signer from the previous step and a number of options, namely:\n\n   - `network` — TON Blockchain network: `Network.mainnet()`, `Network.testnet()`, or `Network.custom(chainId)`.\n   - `client` — API client to communicate with TON Blockchain. Use `kit.getApiClient(network)` to get the client for the specified network from the `networks` configuration passed during [WalletKit initialization](/ecosystem/walletkit/web/init).\n   - `walletId` — identifier of the new wallet, which is used to make its smart contract address unique.\n   - `workchain` — either `0` for the basechain (default), or `-1` for the masterchain.\n\n   ```ts title=\"TypeScript\"\n   import {\n     // Network object\n     Network,\n     // Latest wallet version (recommended)\n     WalletV5R1Adapter,\n     defaultWalletIdV5R1,\n     // Legacy wallet version\n     WalletV4R2Adapter,\n     defaultWalletIdV4R2,\n   } from '@ton/walletkit';\n\n   const walletAdapter = await WalletV5R1Adapter.create(signer, {\n     network: Network.mainnet(),\n     client: kit.getApiClient(Network.mainnet()),\n\n     // Either 0 for the basechain (default),\n     // or -1 for the masterchain\n     workchain: 0,\n\n     // Specify an ID for this wallet when you plan\n     // on adding more than one wallet to the kit\n     // under the same mnemonic or private key.\n     //\n     // In such cases, ID is used to make wallet addresses unique,\n     // because the same ID for the same mnemonic results in wallets\n     // with the same address, i.e., the same smart contract.\n     walletId: defaultWalletIdV5R1, // 2147483409\n   });\n   ```\n\n1. Finally, pass the adapter to the `addWallet()` method of the kit to complete the wallet initialization process:\n\n   ```ts title=\"TypeScript\"\n    // Notice that addWallet() method returns an initialized TON wallet,\n    // which can be used on its own elsewhere.\n    const wallet = await kit.addWallet(walletAdapter);\n    console.log('Wallet address:', wallet.getAddress());\n   ```\n\n   <Aside>\n     Apart from adding a new wallet, an adapter is also helpful when [removing one](#remove-a-single-wallet) too.\n   </Aside>\n\nSee the complete example for each signer kind:\n\n<Columns cols={3}>\n  <Card\n    title=\"Mnemonic\"\n    horizontal=\"true\"\n    href=\"#from-mnemonic\"\n  />\n\n  <Card\n    title=\"Private key\"\n    horizontal=\"true\"\n    href=\"#from-private-key\"\n  />\n\n  <Card\n    title=\"Custom signer\"\n    horizontal=\"true\"\n    href=\"#from-custom-signer\"\n  />\n</Columns>\n\n### From mnemonic\n\nTo initialize a TON wallet from an existing BIP-39 or TON-specific mnemonic seed phrase, the signer should be instantiated with the `fromMnemonic()` method of the utility `Signer` class of the WalletKit.\n\n<Aside\n  type=\"danger\"\n>\n  Never specify the mnemonic phrase directly in your code. It is a \"password\" to your wallet and all its funds.\n\n  Instead, prefer sourcing the seed phrase from a secure storage, backend environment variables, or a special `.env` file that is Git-ignored and handled with care.\n</Aside>\n\n```ts title=\"TypeScript\" expandable\nimport {\n  // Handles cryptographic signing\n  Signer,\n  // Latest wallet version (recommended)\n  WalletV5R1Adapter,\n  // Network object\n  Network,\n} from '@ton/walletkit';\n\n// 1.\nconst signer = await Signer.fromMnemonic(\n  // (REQUIRED)\n  // A 12 or 24-word seed phrase obtained with general BIP-39 or TON-specific derivation.\n  // The following value assumes a corresponding MNEMONIC localStorage entry\n  // that contains 24 space-separated seed phrase words as a single string:\n  localStorage.getItem('MNEMONIC')!.split(' '), // list of 24 strings\n  {\n    // Type of derivation used to produce a mnemonic.\n    // If you've used a pure BIP-39 derivation, specify 'bip-39'.\n    // Otherwise, specify 'ton'.\n    // Defaults to: 'ton'\n    type: 'ton',\n  },\n);\n\n// 2.\nconst walletAdapter = await WalletV5R1Adapter.create(signer, {\n  network: Network.mainnet(),\n  client: kit.getApiClient(Network.mainnet()),\n});\n\n// 3.\nconst wallet = await kit.addWallet(walletAdapter);\n```\n\n<Aside\n  type=\"caution\"\n>\n  If you do not yet have a mnemonic for an existing TON wallet or you want to create a new one, you can generate a TON-specific mnemonic with the `CreateTonMnemonic()` function. However, it is crucial to use that function only **once per wallet** and then save it securely.\n\n  You **must NOT** invoke this function amidst the rest of your project code.\n\n  The following is an example of a simple one-off standalone script to produce a new mnemonic that then should be saved somewhere private:\n\n  ```ts\n  import { CreateTonMnemonic } from '@ton/walletkit';\n\n  console.log(await CreateTonMnemonic()); // word1, word2, ..., word24\n  ```\n</Aside>\n\n### From private key\n\nTo initialize a TON wallet from an existing private key, the signer should be instantiated with the `fromPrivateKey()` method of the utility `Signer` class of the WalletKit.\n\nIf there is a [mnemonic](#from-mnemonic), one can convert it to an Ed25519 key pair with public and private key by using the `MnemonicToKeyPair()` function.\n\n<Aside\n  type=\"danger\"\n  title=\"Private keys are sensitive data!\"\n>\n  Handle private keys carefully. Use test keys, keep them in a secure keystore, and avoid logs or commits.\n</Aside>\n\n```ts title=\"TypeScript\" expandable\nimport {\n  // Handles cryptographic signing\n  Signer,\n  // Latest wallet version (recommended)\n  WalletV5R1Adapter,\n  // Conversion function\n  MnemonicToKeyPair,\n  // Network object\n  Network,\n} from '@ton/walletkit';\n\n// 1.\nconst signer = await Signer.fromPrivateKey(\n  // Private key as a hex-encoded string or Uint8Array of bytes.\n  // The following value assumes a corresponding PRIVATE_KEY localStorage entry\n  // that contains the private key as a hex-encoded string:\n  localStorage.getItem('PRIVATE_KEY')!,\n);\n\n// 2.\nconst walletAdapter = await WalletV5R1Adapter.create(signer, {\n  network: Network.mainnet(),\n  client: kit.getApiClient(Network.mainnet()),\n});\n\n// 3.\nconst wallet = await kit.addWallet(walletAdapter);\n```\n\n### From custom signer\n\nTo provide a custom signing mechanism as an alternative to using a [mnemonic phrase](#from-mnemonic) or a [private key](#from-private-key), create an object of type `WalletSigner` and then pass it to the target wallet adapter's `create()` method.\n\nThe signer object has to have two fields:\n\n- Signing function of type `ISigner`, which takes an iterable bytes object, such as `array`, `Uint8Array`, or `Buffer`, and asynchronously produces an Ed25519-encoded signature of the input as `Hex`. The `Hex` type is a string containing a hexadecimal value that starts with an explicit `0x` prefix.\n\n  ```ts title=\"TypeScript\"\n  type ISigner = (bytes: Iterable<number>) => Promise<Hex>;\n  ```\n\n- Relevant Ed25519 public key of type `Hex`.\n\n  ```ts title=\"TypeScript\"\n  type Hex = `0x${string}`;\n  ```\n\nA custom signer is useful to maintain complete control over the signing process, such as when using a hardware wallet or signing data on the backend.\n\n```ts title=\"TypeScript\" expandable\nimport {\n  // Network object\n  Network,\n  // Latest wallet version (recommended)\n  WalletV5R1Adapter,\n  // Conversion function\n  MnemonicToKeyPair,\n  // Utility function to convert an array of bytes into a string of type Hex\n  Uint8ArrayToHex,\n  // Utilify function to obtain an Ed25519 signature\n  DefaultSignature,\n  // Handles cryptographic signing\n  type WalletSigner,\n  // String with a hexadecimal value, which starts with the `0x` prefix\n  type Hex,\n} from '@ton/walletkit';\n\n// A Ed25519 key pair from a mnemonic\nconst keyPair = await MnemonicToKeyPair(\n  // The following value assumes a corresponding MNEMONIC localStorage entry\n  // that contains 24 space-separated seed phrase words as a single string:\n  localStorage.getItem('MNEMONIC')!.split(' '),\n  'ton',\n);\n\n// 1.\nconst signer: WalletSigner = {\n  // The following is a simple demo of a signing function.\n  // Make sure to replace it with a production-ready one!\n  sign: async (bytes: Iterable<number>): Promise<Hex> => {\n    return DefaultSignature(Uint8Array.from(bytes), keyPair.secretKey);\n  },\n\n  // Public key as a Hex\n  publicKey: Uint8ArrayToHex(keyPair.publicKey) as Hex,\n};\n\n// 2.\nconst walletAdapter = await WalletV5R1Adapter.create(signer, {\n  network: Network.mainnet(),\n  client: kit.getApiClient(Network.mainnet()),\n});\n\n// 3.\nconst wallet = await kit.addWallet(walletAdapter);\n```\n\n### Multiple wallets\n\nYou can add multiple TON wallets to WalletKit and switch between them as needed.\n\n```ts title=\"TypeScript\"\nconst wallet1 = await kit.addWallet(walletAdapter1);\nconst wallet2 = await kit.addWallet(walletAdapter2);\n// ...\nconst walletN = await kit.addWallet(walletAdapterN);\n```\n\nProviding the same wallet adapter to the kit multiple times will return the wallet that was already added in the first attempt.\n\n## Methods\n\n### Get a single wallet\n\nThe `getWallet()` method expects a wallet identifier string. Note that the same wallet on different chains must have different identifiers. Compose it via the `createWalletId()` helper function:\n\n```ts title=\"TypeScript\"\nimport { createWalletId, Network, type Wallet } from '@ton/walletkit';\n\n// Using the helper function to create a wallet identifier.\nconst walletId = createWalletId(\n  Network.mainnet(),\n  walletAdapter.getAddress(),\n);\nconst wallet: Wallet | undefined = kit.getWallet(walletId);\n\nif (wallet) {\n  console.log('Wallet address: ', wallet.getAddress());\n}\n```\n\n### Get all wallets\n\nTo obtain all added wallets, use the `getWallets()` method of the initialized kit.\n\n```ts title=\"TypeScript\"\nconst wallets: Wallet[] = kit.getWallets();\nwallets.forEach(w => console.log('TON wallet address:', w.getAddress()));\n```\n\n### Remove a single wallet\n\nThe `kit.removeWallet()` method accepts either a `walletId` or the adapter instance itself. Compose the identifier via the `createWalletId()` helper function or pass the adapter used when adding the wallet:\n\n```ts title=\"TypeScript\"\nimport { createWalletId, Network } from '@ton/walletkit';\n\n// Using the helper function to create a wallet identifier.\nconst walletId = createWalletId(\n  Network.mainnet(),\n  walletAdapter.getAddress(),\n);\nawait kit.removeWallet(walletId);\n\n// Alternatively, pass the adapter directly.\nawait kit.removeWallet(walletAdapter);\n```\n\n### Clear all wallets\n\nTo remove all previously added wallets from the kit, use the `clearWallets()` method of the initialized kit.\n\n```ts title=\"TypeScript\"\nawait kit.clearWallets();\n```\n\n## Next steps\n\n<Columns cols={2}>\n  <Card\n    title=\"Handle connections\"\n    icon=\"plug\"\n    horizontal=\"true\"\n    href=\"/ecosystem/walletkit/web/connections\"\n  />\n</Columns>\n\n## See also\n\n- [WalletKit overview](/ecosystem/walletkit/overview)\n- [TON Connect overview](/ecosystem/ton-connect/overview)\n"
  },
  {
    "path": "extra.css",
    "content": "/* See: https://mintlify.com/docs/settings/custom-scripts#custom-css */\n\n/* Fixing width of the API reference navigation tags */\nspan.method-nav-pill {\n  width: fit-content;\n  /* or 3rem */\n}\n\n/* Prevent word breaks in inline code items in tables */\ntd>code,\ntd>em>code,\ntd>strong>code,\ntd>a>code {\n  white-space: nowrap;\n}\n\n/* Make links not bold */\n.link {\n  font-weight: 400;\n}\n\n/* Enhance links that wrap inline code snippets */\n\n.link:has(code) {\n  padding-bottom: 3px;\n}\n\n.link>code {\n  border-bottom-left-radius: 0;\n  border-bottom-right-radius: 0;\n  text-decoration: none;\n}\n\n/* Fix Mermaid's Sankey diagrams for both themes */\n\nsvg[aria-roledescription=\"sankey\"]>g.links>g.link {\n  mix-blend-mode: normal !important;\n}\n\n/* A style to hide scrollbar for Chrome, Safari and Opera */\n.no-scrollbar::-webkit-scrollbar {\n  display: none;\n}\n\n/* A class to hide scrollbar for IE, Edge and Firefox */\n.no-scrollbar {\n  /* IE and Edge */\n  -ms-overflow-style: none;\n  /* Firefox */\n  scrollbar-width: none;\n}\n\n/* Sticky table headers */\n\ntable {\n  overflow: unset !important;\n}\n\nthead>tr>th {\n  position: sticky;\n  top: 0;\n  background: rgb(var(--background-light));\n}\n\nhtml.dark thead>tr>th {\n  background: rgb(var(--background-dark));\n}\n\n/* Tabular numbers for better alignment in tables */\ntable {\n  font-variant-numeric: tabular-nums;\n}\n\n/* Reduction of bottom margins for code blocks as last items of <Aside> components */\ndiv[data-component-part=\"callout-content\"]>.code-block:last-child {\n  margin-bottom: 0;\n}\n\n/*\n  A temporary solution syntax highlighting of Tolk snippets: invoke Prism.js on a client-side.\n  See `snippets/tolk-highlight.jsx`.\n  @link https://github.com/ton-org/docs/issues/1473\n */\n\n:root {\n  --tolk-token-comment: #808080;\n  --tolk-token-type-hint: #D500EC;\n  --tolk-token-keyword: #0000FF;\n  --tolk-token-struct: #007EA2;\n  --tolk-token-variable: #444444;\n  --tolk-token-attr-name: #808000;\n  --tolk-token-function: #A82D2D;\n  --tolk-token-number: #0B9000;\n  --tolk-token-string: #008000;\n  --tolk-token-string-bg: #FAF9EF;\n  --tolk-token-operator: #A0A000;\n  --tolk-token-punctuation: #808000;\n  --tolk-token-three-dots: #999999;\n}\n\ncode.language-tolk  { color: var(--tolk-token-variable); }\n.token.comment      { color: var(--tolk-token-comment); font-style: italic; }\n.token.type-hint    { color: var(--tolk-token-type-hint); }\n.token.boolean      { color: var(--tolk-token-keyword); }\n.token.keyword      { color: var(--tolk-token-keyword); }\n.token.self         { color: var(--tolk-token-variable); font-weight: bold; }\n.token.attr-name    { color: var(--tolk-token-attr-name); }\n.token.function     { color: var(--tolk-token-function); }\n.token.number       { color: var(--tolk-token-number); }\n.token.string       { color: var(--tolk-token-string); background-color: var(--tolk-token-string-bg); }\n.token.operator     { color: var(--tolk-token-operator); }\n.token.punctuation  { color: var(--tolk-token-punctuation); }\n.token.three-dots   { color: var(--tolk-token-three-dots); }\n.token.struct       { color: var(--tolk-token-struct); }\n.token.variable     { color: var(--tolk-token-variable); }\n\nhtml.dark {\n  --tolk-token-comment: #808080;\n  --tolk-token-type-hint: #DF90F8;\n  --tolk-token-keyword: #D75F02;\n  --tolk-token-struct: #56C1FF;\n  --tolk-token-variable: #C5D2E0;\n  --tolk-token-attr-name: #808000;\n  --tolk-token-function: #F9B900;\n  --tolk-token-number: #33A033;\n  --tolk-token-string: #33A033;\n  --tolk-token-string-bg: #1B1C1E;\n  --tolk-token-operator: #A0A000;\n  --tolk-token-punctuation: #85B2A0;\n  --tolk-token-three-dots: #777777;\n}\n"
  },
  {
    "path": "extra.js",
    "content": "/* See: https://mintlify.com/docs/settings/custom-scripts#custom-javascript */\n/*\n  A temporary solution syntax highlighting of Tolk snippets: invoke Prism.js on a client-side.\n  Sources of Prism.js are embedded right here, it's not downloaded separately.\n  @link https://github.com/ton-org/docs/issues/1473\n\n  All code blocks for the Tolk language are highlighted:\n  ```tolk\n  // automatically highlighted: see isTolkBlockCode()\n  ```\n\n  Visual appearance is defined in `extra.css`.\n */\n\n(function() {\n  const TOLK_GRAMMAR = {\n    'comment': [\n      { pattern: /\\/\\/.*/, greedy: true },\n      // http://stackoverflow.com/questions/13014947/regex-to-match-a-c-style-multiline-comment/36328890#36328890\n      { pattern: /\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\//, greedy: true },\n    ],\n    'attr-name': /@[a-zA-Z0-9_]+/,\n    'keyword': /\\b(do|if|as|is|try|else|while|break|throw|catch|return|assert|repeat|continue|asm|builtin|import|export|true|false|null|redef|mutate|tolk|global|const|var|val|fun|get\\sfun|struct|match|type|lazy|enum|private|readonly)\\b/,\n    'function': /[a-zA-Z$_][a-zA-Z0-9$_]*(?=(<[^>]+>)*\\()/,\n    'type-hint': /\\b(int|cell|void|never|bool|slice|tuple|builder|continuation|coins|int\\d+|uint\\d+|bytes\\d+|bits\\d+|address|any_address|map|dict)\\b/,\n    'boolean': /\\b(false|true|null)\\b/,\n    'self': /\\b(self)\\b/,\n    'number': /\\b(-?\\d+|0x[\\da-fA-F]+|0b[01]+)\\b/,\n    'string': [\n      { pattern: /\"\"\"[\\s\\S]*?\"\"\"/, greedy: true },\n      { pattern: /\"[^\\n\"]*\"\\w?/, greedy: true },\n    ],\n    'operator': new RegExp(\"\\\\+|-|\\\\*|/|%|\\\\?|:|=|<|>|!|&|\\\\||\\\\^|==|!=|<=|>=|<<|>>|&&|\\\\|\\\\||~/|\\\\^/|\\\\+=|-=|\\\\*=|/=|%=|&=|\\\\|=|\\\\^=|->|<=>|~>>|\\\\^>>|<<=|>>=|=>\"),\n    'three-dots': /\\.\\.\\./,\n    'punctuation': /[.,;(){}\\[\\]]/,\n    'struct': /\\b[A-Z][a-z][a-zA-Z0-9$_]*\\b/,\n    'variable': [\n      { pattern: /`[^`]+`/ },\n      { pattern: /\\b[a-zA-Z$_][a-zA-Z0-9$_]*\\b/ },\n    ],\n  };\n\n  // code blocks inserted with ```tolk are rendered as <code language=\"text\"> actually,\n  // because Mintlify knows nothing about custom languages;\n  // here we try to detect whether it's not func/fift/tlb\n  function isTolkBlockCode(/**HTMLElement*/ codeElement) {\n    if (codeElement.getAttribute('language') !== 'text') {\n      return false;\n    }\n\n    // highlight all snippets inside the \"Tolk\" left menu sections\n    // (even small ones, like `var x = 123`; they cannot be distinguished from FunC,\n    //  but on \"Tolk\" pages, no other languages are present)\n    const isTolkPage = window.location.href.includes('/languages/tolk');\n    if (isTolkPage) {\n      return true;\n    }\n\n    // highlight if markdown has a title: ```tolk title=\"filename.tolk\"\n    const hasTitleFilenameTolk = codeElement\n      .closest('div.code-block')\n      ?.querySelector('div[data-component-part=\"code-block-header-filename\"]')\n      ?.innerText\n      ?.toLowerCase()\n      ?.endsWith('tolk');\n    if (hasTitleFilenameTolk) {\n      return true;\n    }\n\n    // try to detect the language based on innerText;\n    // treat the occurrence of fun/struct/enum/etc. as Tolk;\n    // it works without false positives for quite big, \"real-world\", meaningful snippets;\n    // it does not work for small snippets like `var x = 123` or `if (x != 0) {}`\n    const innerText = codeElement.innerText;\n    return /\\b(fun\\s\\w+|struct\\s\\w+|struct\\s*\\([0-9a-fx]{4,}|enum\\s\\w+|lazy\\s\\w+)\\b/.test(innerText);\n  }\n\n  // check if Prism was called for <code>\n  function isCodeHighlighted(/**HTMLElement*/ codeElement) {\n    return codeElement.classList.contains('language-tolk');\n  }\n\n  // call Prism for <code>\n  function highlightCode(/**HTMLElement*/ codeElement, Prism) {\n    codeElement.classList.add('language-tolk');\n    codeElement.parentElement.style.backgroundColor = '';       // parent is <pre>\n    codeElement.parentElement.classList.remove('shiki'); // avoid css mixing\n    try {\n      Prism.highlightElement(codeElement);\n    } catch (ex) {\n      console.error('suppressed Prism error for code', codeElement, ex);\n    }\n  }\n\n  function highlightAllCodeElementsOnPage(Prism) {\n    let allCodes = document.querySelectorAll('code');\n    for (let i = 0; i < allCodes.length; ++i) {\n      if (isTolkBlockCode(allCodes[i]) && !isCodeHighlighted(allCodes[i])) {\n        highlightCode(allCodes[i], Prism)\n      }\n    }\n\n    // call it iteratively in case of dynamic content changes\n    setTimeout(function() {\n      highlightAllCodeElementsOnPage(Prism)\n    }, 500);\n  }\n\n  if (typeof window !== \"undefined\") {\n    /* PrismJS 1.30.0 */\n    var _self=\"undefined\"!=typeof window?window:\"undefined\"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(e){var n=/(?:^|\\s)lang(?:uage)?-([\\w-]+)(?=\\s|$)/i,t=0,r={},a={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof i?new i(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/\\u00a0/g,\" \")},type:function(e){return Object.prototype.toString.call(e).slice(8,-1)},objId:function(e){return e.__id||Object.defineProperty(e,\"__id\",{value:++t}),e.__id},clone:function e(n,t){var r,i;switch(t=t||{},a.util.type(n)){case\"Object\":if(i=a.util.objId(n),t[i])return t[i];for(var l in r={},t[i]=r,n)n.hasOwnProperty(l)&&(r[l]=e(n[l],t));return r;case\"Array\":return i=a.util.objId(n),t[i]?t[i]:(r=[],t[i]=r,n.forEach((function(n,a){r[a]=e(n,t)})),r);default:return n}},getLanguage:function(e){for(;e;){var t=n.exec(e.className);if(t)return t[1].toLowerCase();e=e.parentElement}return\"none\"},setLanguage:function(e,t){e.className=e.className.replace(RegExp(n,\"gi\"),\"\"),e.classList.add(\"language-\"+t)},currentScript:function(){if(\"undefined\"==typeof document)return null;if(document.currentScript&&\"SCRIPT\"===document.currentScript.tagName)return document.currentScript;try{throw new Error}catch(r){var e=(/at [^(\\r\\n]*\\((.*):[^:]+:[^:]+\\)$/i.exec(r.stack)||[])[1];if(e){var n=document.getElementsByTagName(\"script\");for(var t in n)if(n[t].src==e)return n[t]}return null}},isActive:function(e,n,t){for(var r=\"no-\"+n;e;){var a=e.classList;if(a.contains(n))return!0;if(a.contains(r))return!1;e=e.parentElement}return!!t}},languages:{plain:r,plaintext:r,text:r,txt:r,extend:function(e,n){var t=a.util.clone(a.languages[e]);for(var r in n)t[r]=n[r];return t},insertBefore:function(e,n,t,r){var i=(r=r||a.languages)[e],l={};for(var o in i)if(i.hasOwnProperty(o)){if(o==n)for(var s in t)t.hasOwnProperty(s)&&(l[s]=t[s]);t.hasOwnProperty(o)||(l[o]=i[o])}var u=r[e];return r[e]=l,a.languages.DFS(a.languages,(function(n,t){t===u&&n!=e&&(this[n]=l)})),l},DFS:function e(n,t,r,i){i=i||{};var l=a.util.objId;for(var o in n)if(n.hasOwnProperty(o)){t.call(n,o,n[o],r||o);var s=n[o],u=a.util.type(s);\"Object\"!==u||i[l(s)]?\"Array\"!==u||i[l(s)]||(i[l(s)]=!0,e(s,t,o,i)):(i[l(s)]=!0,e(s,t,null,i))}}},plugins:{},highlightAll:function(e,n){a.highlightAllUnder(document,e,n)},highlightAllUnder:function(e,n,t){var r={callback:t,container:e,selector:'code[class*=\"language-\"], [class*=\"language-\"] code, code[class*=\"lang-\"], [class*=\"lang-\"] code'};a.hooks.run(\"before-highlightall\",r),r.elements=Array.prototype.slice.apply(r.container.querySelectorAll(r.selector)),a.hooks.run(\"before-all-elements-highlight\",r);for(var i,l=0;i=r.elements[l++];)a.highlightElement(i,!0===n,r.callback)},highlightElement:function(n,t,r){var i=a.util.getLanguage(n),l=a.languages[i];a.util.setLanguage(n,i);var o=n.parentElement;o&&\"pre\"===o.nodeName.toLowerCase()&&a.util.setLanguage(o,i);var s={element:n,language:i,grammar:l,code:n.textContent};function u(e){s.highlightedCode=e,a.hooks.run(\"before-insert\",s),s.element.innerHTML=s.highlightedCode,a.hooks.run(\"after-highlight\",s),a.hooks.run(\"complete\",s),r&&r.call(s.element)}if(a.hooks.run(\"before-sanity-check\",s),(o=s.element.parentElement)&&\"pre\"===o.nodeName.toLowerCase()&&!o.hasAttribute(\"tabindex\")&&o.setAttribute(\"tabindex\",\"0\"),!s.code)return a.hooks.run(\"complete\",s),void(r&&r.call(s.element));if(a.hooks.run(\"before-highlight\",s),s.grammar)if(t&&e.Worker){var c=new Worker(a.filename);c.onmessage=function(e){u(e.data)},c.postMessage(JSON.stringify({language:s.language,code:s.code,immediateClose:!0}))}else u(a.highlight(s.code,s.grammar,s.language));else u(a.util.encode(s.code))},highlight:function(e,n,t){var r={code:e,grammar:n,language:t};if(a.hooks.run(\"before-tokenize\",r),!r.grammar)throw new Error('The language \"'+r.language+'\" has no grammar.');return r.tokens=a.tokenize(r.code,r.grammar),a.hooks.run(\"after-tokenize\",r),i.stringify(a.util.encode(r.tokens),r.language)},tokenize:function(e,n){var t=n.rest;if(t){for(var r in t)n[r]=t[r];delete n.rest}var a=new s;return u(a,a.head,e),o(e,a,n,a.head,0),function(e){for(var n=[],t=e.head.next;t!==e.tail;)n.push(t.value),t=t.next;return n}(a)},hooks:{all:{},add:function(e,n){var t=a.hooks.all;t[e]=t[e]||[],t[e].push(n)},run:function(e,n){var t=a.hooks.all[e];if(t&&t.length)for(var r,i=0;r=t[i++];)r(n)}},Token:i};function i(e,n,t,r){this.type=e,this.content=n,this.alias=t,this.length=0|(r||\"\").length}function l(e,n,t,r){e.lastIndex=n;var a=e.exec(t);if(a&&r&&a[1]){var i=a[1].length;a.index+=i,a[0]=a[0].slice(i)}return a}function o(e,n,t,r,s,g){for(var f in t)if(t.hasOwnProperty(f)&&t[f]){var h=t[f];h=Array.isArray(h)?h:[h];for(var d=0;d<h.length;++d){if(g&&g.cause==f+\",\"+d)return;var v=h[d],p=v.inside,m=!!v.lookbehind,y=!!v.greedy,k=v.alias;if(y&&!v.pattern.global){var x=v.pattern.toString().match(/[imsuy]*$/)[0];v.pattern=RegExp(v.pattern.source,x+\"g\")}for(var b=v.pattern||v,w=r.next,A=s;w!==n.tail&&!(g&&A>=g.reach);A+=w.value.length,w=w.next){var P=w.value;if(n.length>e.length)return;if(!(P instanceof i)){var E,S=1;if(y){if(!(E=l(b,A,e,m))||E.index>=e.length)break;var L=E.index,O=E.index+E[0].length,C=A;for(C+=w.value.length;L>=C;)C+=(w=w.next).value.length;if(A=C-=w.value.length,w.value instanceof i)continue;for(var j=w;j!==n.tail&&(C<O||\"string\"==typeof j.value);j=j.next)S++,C+=j.value.length;S--,P=e.slice(A,C),E.index-=A}else if(!(E=l(b,0,P,m)))continue;L=E.index;var N=E[0],_=P.slice(0,L),M=P.slice(L+N.length),W=A+P.length;g&&W>g.reach&&(g.reach=W);var I=w.prev;if(_&&(I=u(n,I,_),A+=_.length),c(n,I,S),w=u(n,I,new i(f,p?a.tokenize(N,p):N,k,N)),M&&u(n,w,M),S>1){var T={cause:f+\",\"+d,reach:W};o(e,n,t,w.prev,A,T),g&&T.reach>g.reach&&(g.reach=T.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function u(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function c(e,n,t){for(var r=n.next,a=0;a<t&&r!==e.tail;a++)r=r.next;n.next=r,r.prev=n,e.length-=a}if(e.Prism=a,i.stringify=function e(n,t){if(\"string\"==typeof n)return n;if(Array.isArray(n)){var r=\"\";return n.forEach((function(n){r+=e(n,t)})),r}var i={type:n.type,content:e(n.content,t),tag:\"span\",classes:[\"token\",n.type],attributes:{},language:t},l=n.alias;l&&(Array.isArray(l)?Array.prototype.push.apply(i.classes,l):i.classes.push(l)),a.hooks.run(\"wrap\",i);var o=\"\";for(var s in i.attributes)o+=\" \"+s+'=\"'+(i.attributes[s]||\"\").replace(/\"/g,\"&quot;\")+'\"';return\"<\"+i.tag+' class=\"'+i.classes.join(\" \")+'\"'+o+\">\"+i.content+\"</\"+i.tag+\">\"},!e.document)return e.addEventListener?(a.disableWorkerMessageHandler||e.addEventListener(\"message\",(function(n){var t=JSON.parse(n.data),r=t.language,i=t.code,l=t.immediateClose;e.postMessage(a.highlight(i,a.languages[r],r)),l&&e.close()}),!1),a):a;var g=a.util.currentScript();function f(){a.manual||a.highlightAll()}if(g&&(a.filename=g.src,g.hasAttribute(\"data-manual\")&&(a.manual=!0)),!a.manual){var h=document.readyState;\"loading\"===h||\"interactive\"===h&&g&&g.defer?document.addEventListener(\"DOMContentLoaded\",f):window.requestAnimationFrame?window.requestAnimationFrame(f):window.setTimeout(f,16)}return a}(_self);\"undefined\"!=typeof module&&module.exports&&(module.exports=Prism),\"undefined\"!=typeof global&&(global.Prism=Prism);\n    Prism.languages.tolk = TOLK_GRAMMAR;\n\n    setTimeout(function() {\n      highlightAllCodeElementsOnPage(Prism);\n    }, 0);\n  }\n})();\n"
  },
  {
    "path": "foundations/actions/change-library.mdx",
    "content": "---\ntitle: \"Change library\"\n---\n\nChange a library is one of the actions that a smart contract can perform during the [action phase](/foundations/phases#action-phase). It adds libraries to or removes them from the collection of libraries of this smart contract. It can be appended to an [out action list](https://github.com/ton-blockchain/ton/blob/5c0349110bb03dd3a241689f2ab334ae1a554ffb/crypto/block/block.tlb#L411) by:\n\n- The [`SETLIBCODE`](/tvm/instructions#fb06-setlibcode) instruction.\n- The [`CHANGELIB`](/tvm/instructions#fb07-changelib) instruction.\n- The [`POPCTR`](/tvm/instructions#ed5-popctr) instruction.\n\nThe change library action consists of\n\n- a 7-bit bitmask `mode` specifying the way of changing the library;\n- a ref to a cell containing the new library code or the hash of this code as an unsigned 256-bit integer.\n\n## Modes\n\nThe `mode` can have the following values that can be combined together:\n\n| Mode value | Convenient name     | Description                                                                                                                                                                                                                              |\n| ---------: | :------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n|        `0` | `RemoveLibrary`     | Default mode. Removes library if it was in the collection. Otherwise, action does nothing.                                                                                                                                               |\n|       `+1` | `AddPrivateLibrary` | A library is added as a private library.                                                                                                                                                                                                 |\n|       `+2` | `AddPublicLibrary`  | A library is added as a public library and becomes available to all smart contracts in all workchains if the current smart contract resides in the masterchain. If current contract is in other workchain, works as `AddPrivateLibrary`. |\n|      `+16` | `BounceOnFail`      | Bounces the transaction if the action fails.                                                                                                                                                                                             |\n\nThe other values of `mode` are invalid and lead to an error. Simultaneous usage of the `AddPrivateLibrary` and `AddPublicLibrary` modes also leads to an error. If the library was present in the collection before, its public/private status is changed according to the `mode`.\n\n## Serialization\n\n```tlb\nlibref_hash$0 lib_hash:bits256 = LibRef;\nlibref_ref$1 library:^Cell = LibRef;\naction_change_library#26fa1dd4 mode:(## 7)\n    libref:LibRef = OutAction;\n```\n"
  },
  {
    "path": "foundations/actions/overview.mdx",
    "content": "---\ntitle: \"Actions\"\nsidebarTitle: \"Overview\"\n---\n\nThere are four actions that a smart contract can perform during the [action phase](/foundations/phases#action-phase):\n\n- [send a message](/foundations/actions/send);\n- [reserve coins](/foundations/actions/reserve);\n- [change its libraries](/foundations/actions/change-library);\n- [change its code](/foundations/actions/set-code).\n\nA smart contract can create up to 255 such actions during its execution. Actions are created during the compute phase by special [TVM instructions](/tvm/instructions). When an action is created, it is populated into the output action list of the smart contract. From the low-level perspective, the output action list is a linked list where each action is represented as a cell.\n\nFinally, in the action phase, created actions are executed in the order they were populated into the output action list.\n\n```tlb\nout_list_empty$_ = OutList 0;\nout_list$_ {n:#} prev:^(OutList n) action:OutAction\n    = OutList (n + 1);\naction_send_msg#0ec3c86d mode:(## 8) \n    out_msg:^(MessageRelaxed Any) = OutAction;\naction_set_code#ad4de08e new_code:^Cell = OutAction;\naction_reserve_currency#36e6b809 mode:(## 8)\n    currency:CurrencyCollection = OutAction;\nlibref_hash$0 lib_hash:bits256 = LibRef;\nlibref_ref$1 library:^Cell = LibRef;\naction_change_library#26fa1dd4 mode:(## 7)\n    libref:LibRef = OutAction;\n```\n"
  },
  {
    "path": "foundations/actions/reserve.mdx",
    "content": "---\ntitle: \"Reserve coins\"\n---\n\n_Reserving coins_ is one of the actions that a smart contract can perform during the [action phase](/foundations/phases#action-phase). In TVM it is implemented via the [`RAWRESERVE`](/tvm/instructions#fb02-rawreserve) instruction that takes from the stack an `amount` of Toncoin (in nanotoncoins) to reserve and an integer `mode` specifying a way of the reservation. The reservation action is queued to the _output action list_ of a smart contract, which contains other actions such as _message sends_.\n\nThe `RAWRESERVE` instruction is equivalent to creating an outbound message carrying the specified `amount` of nanotoncoin to oneself. But unlike regular sending of a message, the reservation action does not create a new message and does not incur any forward fees. Its primary goal is to limit the amount of Toncoin that can be spent by subsequent actions.\n\n## Modes\n\nThe `mode` parameter is a bitmask that specifies how a reserved amount is calculated. The resulting mode value can have the following base modes:\n\n| Mode value | Convenient name    | Description                                             |\n| ---------: | :----------------- | ------------------------------------------------------- |\n|        `0` | `ReserveExact`     | Reserves exactly the specified `amount` of nanotoncoin. |\n|        `1` | `ReserveAllExcept` | Reserves all but the specified `amount` of nanotoncoin. |\n|        `2` | `ReserveAtMost`    | Reserves at most the specified `amount` of nanotoncoin. |\n\nAdditionally, the resulting `mode` can have the following optional flags added:\n\n| Flag value | Convenient name             | Description                                                                                                                           |\n| ---------: | :-------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |\n|       `+4` | `ReserveAddOriginalBalance` | Increases the `amount` by the original balance (i.e. without incoming message value) of the current account before the compute phase. |\n|       `+8` | `ReserveInvertSign`         | Negates the `amount` value before performing the reservation.                                                                         |\n|      `+16` | `ReserveBounceIfActionFail` | Bounces the transaction if the reservation fails.                                                                                     |\n\n## Behavior\n\nNotation:\n\n- `amount` – the amount of Toncoin passed to the `RAWRESERVE` instruction.\n- `mode` – the integer mode passed to the `RAWRESERVE` instruction.\n- `original_balance`:\n  - if after the storage phase, account's balance is less than the value of incoming message with bounce flag set to `false`, then `original_balance` is set to $0$;\n  - otherwise, `original_balance` equals account's balance before the compute phase minus incoming message value.\n- `remaining_balance` – account's balance before the reservation action.\n- `reserve` – the final amount to be reserved.\n\nThe algorithm is as follows:\n\n1. Check that `mode` has flag `ReserveBounceIfActionFail`:\n   - if so, then in case of any failure the action phase will be interrupted and the bounce phase will be initiated;\n   - if not, then in case of any failure the reservation action will be skipped.\n1. Set `reserve` to `amount`.\n1. Check that `mode` has flag `ReserveAddOriginalBalance`:\n   1. If so, then check that `mode` has flag `ReserveInvertSign`:\n      - if so, then set `reserve` to `original_balance - reserve`;\n      - otherwise, increase `reserve` by `original_balance`.\n   1. Otherwise, if `mode` has flag `ReserveInvertSign`, throw the error \"invalid reserve mode\".\n1. Check that `mode` has flag `ReserveAtMost`:\n   - if so, then set `reserve` to `min(reserve, remaining_balance)`.\n1. Check that `mode` has flag `ReserveAllExcept`:\n   - if so, then set `reserve` to `remaining_balance - reserve`.\n1. Set `remaining_balance` to `remaining_balance - reserve`.\n\nIf there were no errors, then the reservation action was successful, and the subsequent actions can spend only at most the new `remaining_balance`.\n\nFor example, suppose that:\n\n- `amount` = `0.1` Ton;\n- `mode` = `1 + 4 + 8` (`ReserveAllExcept`, `ReserveAddOriginalBalance`, `ReserveInvertSign`);\n- `original_balance` = `2` Ton;\n- `remaining_balance` = `3` Ton.\n\nThen the reservation proceeds as follows:\n\n1. `mode` has flag `ReserveBounceIfActionFail`? No.\n1. `reserve` = `0.1` Ton.\n1. `mode` has flag `ReserveAddOriginalBalance`? Yes.\n   - `mode` has flag `ReserveInvertSign`? Yes.\n   - Thus, `reserve` = `original_balance - reserve` = `2 - 0.1` = `1.9` Ton.\n1. `mode` has flag `ReserveAtMost`? No.\n1. `mode` has flag `ReserveAllExcept`? Yes.\n   - Thus, `reserve` = `remaining_balance - reserve` = `3 - 1.9` = `1.1` Ton.\n1. `remaining_balance` = `remaining_balance - reserve` = `3 - 1.1` = `1.9` Ton.\n\n## Errors\n\nThe following errors can occur during the reservation flow:\n\n- If the `mode` bitmask has more than first five ones positive bits, then the error [`34`](/tvm/exit-codes#34%3A-invalid-or-unsupported-action) is thrown.\n- If `mode` has flag `8` but not flag `4`, then the error [`34`](/tvm/exit-codes#34%3A-invalid-or-unsupported-action) is thrown.\n- If after step 3, `reserve` is negative, then the error [`34`](/tvm/exit-codes#34%3A-invalid-or-unsupported-action) is thrown.\n- Passing a negative `amount` also results in the same error.\n- If after step 4, `reserve` is greater than `remaining_balance`, then the error [`37`](/tvm/exit-codes#37%3A-not-enough-toncoin) (\"Not enough Toncoin\") is thrown.\n- Some problems with unpacking the reserve action cell.\n- A problem related to extra-currency.\n\nIf the action had flag `16`, then in case of any of the above errors a [bounce message](/foundations/messages/internal#bounces) is sent back to a sender.\n"
  },
  {
    "path": "foundations/actions/send.mdx",
    "content": "---\ntitle: \"Send message\"\n---\n\nSending a message is the most frequent action that a smart contract performs during the [action phase](/foundations/phases#action-phase). It can get into the [out action list](https://github.com/ton-blockchain/ton/blob/5c0349110bb03dd3a241689f2ab334ae1a554ffb/crypto/block/block.tlb#L411) by:\n\n- The [`SENDRAWMSG`](/tvm/instructions#fb00-sendrawms) instruction.\n- The [`SENDMSG`](/tvm/instructions#fb08-sendmsg) instruction.\n- The [`POPCTR`](/tvm/instructions#ed5-popctr) instruction.\n\nThe sending message action consists of:\n\n- an 8-bit bitmask [`mode`](/foundations/messages/modes) specifying the way of sending;\n- a cell containing the message to send, which is serialized as `MessageRelaxed` type.\n\n## Message normalization\n\nDuring the process of sending, the original message is normalized. In the final message that is sent to the destination address, the following changes are applied to the fields of the [`CommonMsgInfoRelaxed`](https://github.com/ton-blockchain/ton/blob/5c0349110bb03dd3a241689f2ab334ae1a554ffb/crypto/block/block.tlb#L135-L140) type:\n\n- `ihr_disabled` is set to `true`;\n- `bounced` is set to `false`;\n- `fwd_fee` is set to actual forward fee dedicated to the validators of the destination address shard;\n- `src` address is set to address of the sender smart contract;\n- `created_at` is set to the current Unix timestamp;\n- `created_lt` is set to the logical time of that action.\n\nAs a result, when composing a message cell, it is acceptable to:\n\n- fill the `ihr_disabled`, `bounced`, `fwd_fee`, `created_at`, and `created_lt` fields with any values;\n- fill the `src` field with [`addr_none`](/foundations/addresses/overview#external-addresses).\n\nIf the message cell does not fit into the maximum allowed size (1023 bits) after the normalization, the process is repeated with different ways to pack it:\n\n- with `init` packed in a separate cell, referred from the root cell;\n- with `init` and `body` packed in separate cells.\n\nIf after the second attempt the message is still too large, the exception is thrown in the action phase. This can lead to rejecting the whole action phase, sending a bounce message, or skipping this action. The exact behavior depends on the `mode` bitmask of the action.\n\n## Serialization\n\n```tlb\naction_send_msg#0ec3c86d mode:(## 8) \n    out_msg:^(MessageRelaxed Any) = OutAction;\n\nout_list_node$_ prev:^Cell action:OutAction = OutListNode;\n\nmessage$_ {X:Type} info:CommonMsgInfoRelaxed\n    init:(Maybe (Either StateInit ^StateInit))\n    body:(Either X ^X) = MessageRelaxed X;\n\nint_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool\n    src:MsgAddress dest:MsgAddressInt \n    value:CurrencyCollection extra_flags:(VarUInteger 16) fwd_fee:Grams\n    created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed;\n\next_out_msg_info$11 src:MsgAddress dest:MsgAddressExt\n    created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed;    \n```\n"
  },
  {
    "path": "foundations/actions/set-code.mdx",
    "content": "---\ntitle: \"Set code\"\n---\n\nSetting a code is one of the actions that a smart contract can perform during the [action phase](/foundations/phases#action-phase). It can get into the [out action list](https://github.com/ton-blockchain/ton/blob/5c0349110bb03dd3a241689f2ab334ae1a554ffb/crypto/block/block.tlb#L411) by:\n\n- The [`SETCODE`](/tvm/instructions#fb04-setcode) instruction.\n- The [`POPCTR`](/tvm/instructions#ed5-popctr) instruction.\n\nThe set code action consists of a cell containing the new code of a smart contract.\n\nIf there are several such actions in the action phase, the smart contract code, upon successful completion of the action phase, will be changed to the one specified in the last one. If the action phase fails, the code change will not be applied, even if the set code action was processed successfully.\n\nThe only error that can happen when processing a set code action is that the action cell does not match the expected TL-B scheme.\n\n## Serialization\n\n```tlb\naction_set_code#ad4de08e new_code:^Cell = OutAction;\n```\n"
  },
  {
    "path": "foundations/addresses/derive.mdx",
    "content": "---\ntitle: \"Deriving addresses\"\nsidebarTitle: \"Deriving\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nIt is often useful to derive an [address](/foundations/addresses/overview) of an account to interact with it, either on-chain or off-chain. The general algorithm for address derivation is to compose the [`StateInit`](/foundations/messages/deploy) of an account, calculate its hash, and build the address in the desired [format](/foundations/addresses/overview#internal-addresses).\n\nThe `StateInit` is distinct from the account's current state. It is the initial state, which an account stores at deployment. After that, state can be changed by the smart contract itself — for example, by updating the data. Since the address depends on `StateInit`, to derive the address it is necessary to compose the initial state rather than the current one. In practice, address derivation is mostly about composing the correct `StateInit`.\n\n## On-chain derivation\n\n### On-chain — simple\n\nIf it's known how to compose the contract's initial `code` and `data`, it's enough to follow the general algorithm mentioned above as is. Code and data form a `StateInit`, and the [workchain](/foundations/addresses/overview#workchain-id) is usually hardcoded. Below is one of the most common patterns when `code` is a constant cell known in advance and `data` is composed at runtime.\n\n```tolk title=\"Tolk\" expandable\n// Compose an address builder\nfun calculateAddress(\n    code: cell,\n    data: cell,\n    workchain: int\n): builder {\n    val addr = AutoDeployAddress {\n        workchain,\n        stateInit: ContractState { code, data }\n    };\n    return addr.buildAddress();\n}\n\n// Placeholder for the code cell encoded as a bag of cells\nfun getCode(): cell asm \"B{b5ee9c724101010100020000004cacb9cd} B>boc PUSHREF\";\n\n// Placeholder for data that is usually assembled at runtime\nfun getData(): cell {\n    return beginCell()\n        .storeUint(123, 123)\n        .storeSlice(\"hello, world\")\n    .endCell();\n}\n\nfun main() {\n    val code = getCode();\n    val data = getData();\n    val workchain = BASECHAIN;\n\n    val builderWithAddress = calculateAddress(code, data, workchain);\n\n    // Example usage if the derived address has to be written in another cell.\n    val exampleCell = beginCell()\n        .storeBuilder(builderWithAddress)\n    .endCell();\n    debug.print(exampleCell);\n}\n```\n\nThe `b5ee9c724101010100020000004cacb9cd` in the `getCode` function is a placeholder for a hardcoded code cell in [BoC](/foundations/serialization/boc) format known at compile-time. The `getData` function is a placeholder for building a data cell, and the actual implementation depends on the storage layout of the target smart contract. Usually, data is composed in a parametrized way, but this does not alter the rest of the logic — only the `getData` function.\n\nThe `calculateAddress` function uses the [`AutoDeployAddress`](/languages/tolk/features/message-sending) built-in that handles all the underlying `StateInit` and address composing logic. In the Tolk stdlib, the code and data pair is represented by `ContractState`. The `buildAddress` method returns a builder containing the resulting address, which can be cheaply stored in another builder — the most common use case.\n\n### On-chain — contract sharding\n\nWhen working with the [contract sharding](/contract-dev/contract-sharding) pattern, child contracts usually have a `StateInit` that depends on the parent. In the example below, the dependence is implemented by adding the parent address to the child `StateInit`. The same logic from the [simple on-chain](#on-chain-simple) case works here, and only `getData` has to be changed.\n\n```tolk title=\"Tolk\" expandable\n// Compose an address builder using the AutoDeployAddress built-in.\nfun calculateAddress(code: cell, data: cell, workchain: int): builder {\n    val addr = AutoDeployAddress {\n        workchain,\n        stateInit: ContractState { code, data }\n    };\n    return addr.buildAddress();\n}\n\n// Placeholder for the code cell encoded as a BoC.\nfun getCode(): cell asm \"B{b5ee9c724101010100020000004cacb9cd} B>boc PUSHREF\";\n\n// Placeholder for child data that depends on the parent address.\nfun getChildData(parentAddress: address): cell {\n    return beginCell()\n        .storeSlice(\"hello, world\")\n        .storeAddress(parentAddress)\n    .endCell();\n}\n\nfun main() {\n    val code = getCode();\n    val parentAddress = contract.getAddress();\n    val data = getChildData(parentAddress);\n    val workchain = BASECHAIN;\n\n    val builderWithAddress = calculateAddress(code, data, workchain);\n\n    // Example usage if the derived address has to be written in another cell.\n    val exampleCell = beginCell()\n        .storeBuilder(builderWithAddress)\n    .endCell();\n    debug.print(exampleCell);\n}\n```\n\nChild contracts also often have some kind of index or additional data that they depend on, but it is case-specific and up to the implementation. The common pattern is to include at least the parent address in `StateInit`.\n\n### On-chain — vanity\n\nA [vanity contract](/contract-dev/vanity) allows _customizing_ the address of a smart contract that is being deployed. It does that by making its own `StateInit` depend on some salt that is randomly generated many times until a desired address is found.\n\nIn this case, there is no real correlation between the data the contract holds and its final address. So there is no way to actually _derive_ the address. The only option left is to define a constant with the actual address that is obtained in advance.\n\n```tolk title=\"Tolk\"\n// Constant address in raw format.\nconst VANITY_ADDRESS_RAW: address = address(\"0:4de24b95c1c3c9b6a94231460716192c7d2b4e444ca6ae9a98bc5c4b3fcdef3f\");\n\n// Constant address in user-friendly format.\nconst VANITY_ADDRESS_USER_FRIENDLY: address = address(\"EQBN4kuVwcPJtqlCMUYHFhksfStOREymrpqYvFxLP83vP-Ci\");\n\nfun main() {\n    debug.print(VANITY_ADDRESS_RAW);\n    debug.print(VANITY_ADDRESS_USER_FRIENDLY);\n}\n```\n\n### On-chain — prefixed\n\nThe `toShard` field in `AutoDeployAddress` allows smart contracts to have a specific prefix in the address for the purpose of deploying it to a certain shardchain. This can be useful for cross-contract latency optimization, as in [Jetton 2.0](/standard/tokens/jettons/comparison).\n\nThis may seem similar to the [vanity](#on-chain-vanity) case, but it serves a different purpose. A vanity generator finds such a `StateInit` that an address composed from its hash will have certain letters in a prefix or suffix. The `toShard` does not alter the whole address and only tells the blockchain to replace the first few bits of the address to which the contract is being deployed. This optimization is used in [Jetton 2.0](/standard/tokens/jettons/comparison).\n\nThe logic here is more similar to the [simple](#on-chain-simple) case. The only difference is the additional `toShard` field.\n\n```tolk title=\"Tolk\" expandable\n// Compose an address builder using the AutoDeployAddress built-in.\nfun deriveAddress(target: address, prefixLength: int): builder {\n    val code = getCode();\n    val data = getData();\n    val workchain = BASECHAIN;\n    val addr = AutoDeployAddress {\n        workchain,\n        stateInit: ContractState { code, data },\n        toShard: {\n            fixedPrefixLength: prefixLength,\n            closeTo: target\n        }\n    };\n    return addr.buildAddress();\n}\n\n// Placeholder for the code cell encoded as a BoC.\nfun getCode(): cell asm \"B{b5ee9c724101010100020000004cacb9cd} B>boc PUSHREF\";\n\n// Placeholder for data cell composition.\nfun getData(): cell {\n    return beginCell().endCell();\n}\n\nfun main() {\n    // Using a constant as a target.\n    val constTarget: address = address(\"0:AA00000000000000000000000000000000000000000000000000000000000000\");\n    val constBuilder = deriveAddress(constTarget, 8);\n\n    // Example usage if the derived address has to be written in another cell.\n    val constCell = beginCell()\n        .storeBuilder(constBuilder)\n        .endCell();\n    debug.print(constCell);\n\n    // Using contract's own address as a target.\n    val runtimeTarget = contract.getAddress();\n    val runtimeBuilder = deriveAddress(runtimeTarget, 8);\n\n    // Example usage if the derived address has to be written in another cell.\n    val runtimeCell = beginCell()\n        .storeBuilder(runtimeBuilder)\n        .endCell();\n    debug.print(runtimeCell);\n}\n```\n\n<Aside\n  type=\"tip\"\n  title=\"Prefix length limit\"\n>\n  The max possible prefix length is defined in the blockchain config's\n  [param 43](/foundations/config#param-43-account-and-message-limits)\n  as `max_acc_fixed_prefix_length`.\n</Aside>\n\n## Off-chain derivation\n\n### Off-chain — simple\n\nThe logic mirrors the [on-chain](#on-chain-simple) example. The `@ton/core` library has the `contractAddress` function that handles `StateInit` hash calculation and composes the address.\n\n```ts expandable\nimport { contractAddress, Cell, beginCell } from \"@ton/core\";\n\n// constant code from a BoC\nconst code = Cell.fromBoc(\n  Buffer.from(\"b5ee9c724101010100020000004cacb9cd\", \"hex\"),\n)[0];\n\n// data composing example\nconst data = beginCell()\n  .storeUint(123, 123)\n  .storeStringTail(\"hello, world!\")\n  .endCell();\n\nconst init = {\n  code,\n  data,\n};\n\nconst addr = contractAddress(0, init);\n\nconsole.log(addr); // EQC235M1tplyIg2OUQZQgG8D3BNF6_TZJ1932iaIV26XBVCH\n```\n\n### Off-chain — contract sharding\n\nThe logic mirrors the [on-chain](#on-chain-contract-sharding) example. The parent address is hardcoded in this example but could just as well be derived on its own.\n\n```ts\nimport { contractAddress, Cell, beginCell, Address } from \"@ton/core\";\n\n// constant code from a BoC\nconst code = Cell.fromBoc(\n  Buffer.from(\"b5ee9c724101010100020000004cacb9cd\", \"hex\"),\n)[0];\n\nconst parentAddress = Address.parse(\n  \"EQBKgXCNLPexWhs2L79kiARR1phGH1LwXxRbNsCFF9doc2lN\",\n);\nconst data = beginCell()\n  .storeStringTail(\"hello, world!\")\n  // include the parent address in the child StateInit\n  .storeAddress(parentAddress)\n  .endCell();\n\nconst init = {\n  code,\n  data,\n};\n\nconst addr = contractAddress(0, init);\n\nconsole.log(addr);\n// EQAE74NUORgCfJQqcKy6GTCEs1hlZ--um6PWEmWX25fgDuuZ\n```\n\n### Off-chain — vanity\n\nSimilarly to the [on-chain](#on-chain-vanity) case, there is no way to derive the address. Define a constant with the predetermined address obtained in advance.\n\n```ts\nimport { contractAddress, Cell, beginCell, Address } from \"@ton/core\";\n\nconst addr1 = Address.parse(\"EQBKgXCNLPexWhs2L79kiARR1phGH1LwXxRbNsCFF9doc2lN\");\n\nconsole.log(addr1);\n// EQBKgXCNLPexWhs2L79kiARR1phGH1LwXxRbNsCFF9doc2lN\n```\n\n### Off-chain — prefixed\n\nThe logic mirrors the [on-chain](#on-chain-prefixed) example. Since `@ton/core` does not define helpers for prefixed addresses, the prefix must be replaced manually.\n\n```ts\nimport { contractAddress, Cell, beginCell } from \"@ton/core\";\n\n// constant code from a BoC\nconst code = Cell.fromBoc(\n  Buffer.from(\"b5ee9c724101010100020000004cacb9cd\", \"hex\"),\n)[0];\n\n// data composing example\nconst data = beginCell()\n  .storeUint(123, 123)\n  .storeStringTail(\"hello, world!\")\n  .endCell();\n\nconst init = {\n  splitDepth: 8, // prefix length\n  code,\n  data,\n};\n\nconst addr = contractAddress(0, init); // 0 - basechain\naddr.hash[0] = parseInt(\"00000000\", 2); // replace first byte with 0x00\n\nconsole.log(addr); // EQAAO5BKgRAfcMawxnHYUkZ2Ga74iZMA7uPoD_JkwWfyOwMA\n```\n"
  },
  {
    "path": "foundations/addresses/formats.mdx",
    "content": "---\ntitle: \"Internal address formats\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nAccordingly to [TEP 0002](https://github.com/ton-blockchain/TEPs/blob/master/text/0002-address.md#smart-contract-addresses)\nthere exist two internal address formats on TON Blockchain:\n\n- **raw**;\n- **user-friendly**.\n\nEvery internal address can be represented in each of these formats. However, these representations are equivalent: refer to exactly one address,\nalthough they visually differ significantly from each other.\nFor a detection how wallets and other applications use these formats, see the [address workflow](/ecosystem/wallet-apps/addresses-workflow) page.\n\n## Raw format\n\nThe raw format is the canonical, on-chain representation of the address of a smart contract.\nIt is this format that is used by developers of smart contracts in the manual creation\nof messages and is inspired by the [corresponding TL-B schemes](https://github.com/ton-blockchain/ton/blob/cac968f77dfa5a14e63db40190bda549f0eaf746/crypto/block/block.tlb#L100-L110).\n\n### Structure\n\nIn existing workchains, the raw format consists of two components separated by a colon:\n\n- `workchain_id`: a signed 8-bit integer identifying the workchain.<br />\n  Examples: `-1` for the masterchain and `0` for the basechain.\n- `account_id`: a 256-bit identifier that is derived from a smart contract [`StateInit`](/foundations/messages/deploy).\n\nExample:\n`0:ca6e321c7cce9ecedf0a8ca2492ec8592494aa5fb5ce0387dff96ef6af982a3e`\n\nUppercase letters (A–F) may be used in address strings instead of their lowercase counterparts (a-f).\n\n### Drawbacks\n\nRaw addresses lack built-in safety features, making them unsuitable for general use:\n\n- **No error detection**: the format includes no checksum. A single-character mistake can cause irreversible loss of funds.\n- **No metadata**: for instance, each smart contract can be deployed on both Testnet and Mainnet, in which it will have the same address.\n  An attempt to send real funds to the Testnet variant will result in their loss. It is desirable to have a flag in the address that prevents users from making such a mistake.\n\n## User-friendly format\n\nThe main purpose of the user-friendly format is to help prevent users from accidentally losing their funds due to a small mistake\nin the raw format, unwise use of the bounce flag, or from having to manually compose a message when they interact with the\nintended recipient through wallet applications (for instance, [Tonkeeper](https://tonkeeper.com/)).\n\nIn fact, the user-friendly address format is a secure, base64-encoded (or base64url-encoded) wrapper around the raw format. It adds metadata\nflags and a checksum to prevent common errors and provide greater control over message routing.\n\n<Aside\n  type=\"caution\"\n>\n  This format can be applied only to addresses that are described according to the `addr_std` TL-B scheme, see addresses [general info](/foundations/addresses/overview) subpage.\n</Aside>\n\n### Structure\n\nA user-friendly address is a 36-byte structure with the following components:\n\n1. Flags (1 byte): metadata that changes the handling of messages in the wallet application. `0x11` for sending bounceable messages, `0x51` for non-bounceable, add the `0x80` summand if that address should not be accepted by software running in Mainnet.\n1. `workchain_id` (1 byte): an 8-bit signed integer.\n1. `account_id` (32 bytes): the 256-bit ([big-endian](https://www.freecodecamp.org/news/what-is-endianness-big-endian-vs-little-endian/)) account identifier.\n1. Checksum (2 bytes): a [CRC16-CCITT](https://github.com/ton-blockchain/ton-kotlin/blob/main/crypto/src/crc16.kt) checksum of the preceding 34 bytes.\n\nThe checksum mechanism in user-friendly addresses is similar to the [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm), providing a first-line defense against input errors by validating format integrity upfront.\n\n### Flag definitions\n\nThe first 8 bits of the user-friendly format encode the handling of messages, as defined in [TEP 0002](https://github.com/ton-blockchain/TEPs/blob/master/text/0002-address.md#smart-contract-addresses):\n\n| Address prefix | Binary form | Bounceable | Testnet-only |\n| :------------: | :---------: | :--------: | :----------: |\n|     `E...`     |  `00010001` |     Yes    |      No      |\n|     `U...`     |  `01010001` |     No     |      No      |\n|     `k...`     |  `10010001` |     Yes    |      Yes     |\n|     `0...`     |  `11010001` |     No     |      Yes     |\n\nAs we can see, there are four variants of the handling:\n\n- send a **bounceable** message to a **Mainnet** address;\n- send a **non-bounceable** message to a **Mainnet** address;\n- send a **bounceable** message to a **Testnet** address;\n- send a **non-bounceable** message to a **Testnet** address;\n\n### Encoding\n\nThe 36-byte structure is encoded into a 48-character non-space string using either standard base64 (i.e., with digits, upper- and lowercase Latin letters, `/` and `+`) or URL-safe base64 (with `_` and `-` instead of `/` and `+`). Both encodings are valid and must be supported by applications.\n\nExamples:\n\n- Bounceable: `EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPrHF`\n- Non-bounceable: `UQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPuwA`\n- Bounceable-Testnet: `kQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPgpP`\n- Non-bounceable-Testnet: `0QDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPleK`\n\n<Aside>\n  The same encoding is used for the so-called armored versions of [public keys](/contract-dev/security)\n  and ADNL addresses.\n</Aside>\n\n### Custom address safety\n\nWhen developing custom solutions on TON Blockchain, it is critical to implement proper address handling logic. First, always verify whether the recipient address is initialized before sending funds to prevent unintended losses.\n\nFor user-friendly format forms selection: use _bounceable_ addresses for user smart contracts with custom logic to ensure funds are returned if the contract is invalid, and _non-bounceable_ addresses for wallets to guarantee funds are credited even if the recipient is uninitialized.\n\n### Drawbacks\n\n- **Public key extraction**: it is impossible to extract the public key from the address, which is needed for some tasks (for example,\n  to send an encrypted message to this address). Thus, until the smart contract is deployed for this address, there is no way to get the public key on-chain.\n- **UI**: most OS do not allow you to select an address with a double click because of `_`, `-`, `/`, `+` base64 symbols.\n\n## Summary\n\n- **Raw format** is for system-level use and lacks safety features.\n- **User-friendly format** is for application-level use; it includes flags and a checksum.\n\n## Next steps\n\nFor more technical details, refer to:\n\n- [Account status](/foundations/status): how addresses evolve (active, frozen, etc.).\n"
  },
  {
    "path": "foundations/addresses/overview.mdx",
    "content": "---\ntitle: \"Addresses overview\"\nsidebarTitle: \"Overview\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nTON implements **Actor model**, where all entities, including wallets, are smart contracts. Each actor:\n\n- processes incoming messages;\n- updates its internal state;\n- generates outgoing messages.\n\nAs a result, every actor must have a unique address to ensure the correct message routing. This section explains how these addresses are structured and why they are fundamental to the TON architecture.\n\nThere are several types of addresses used in the TON blockchain. Here, we will focus on the two most important ones for developers: **internal** and **external**.\nEvery account in the TON blockchain has an internal address. External addresses are intended to be used by off-chain software.\n\n## Internal addresses\n\nEach smart contract deployed on TON blockchain has this type of the address. Let's look at the corresponding TL-B schemes:\n\n```\naddr_std$10 anycast:(Maybe Anycast)\n   workchain_id:int8 address:bits256 = MsgAddressInt;\naddr_var$11 anycast:(Maybe Anycast) addr_len:(## 9)\n   workchain_id:int32 address:(bits addr_len) = MsgAddressInt.\n```\n\nAs we can see, there are two constructors:\n\n- `addr_std`: standardized addresses with a fixed length that are suitable for [SHA256 encryption](https://en.wikipedia.org/wiki/SHA-2). Must be used whenever possible.\n- `addr_var`: represents addresses in workchains with a _large_ `workchain_id`, or addresses with a length not equal to 256. Currently, it is not used and is intended for future extensions.\n\nAnd four components:\n\n- `workchain_id`: the workchain ID (signed 8- or 32-bit integer).\n- `address`: an address of the account (64-512 bits, depending on the workchain). In order not to confuse this field with a whole address, it is usually called `account_id`.\n- `addr_len`: a length of the non-standardized address.\n- `anycast`: not currently used in the blockchain and is always replaced with a zero bit. It was designed to implement shard splitting of _global_ (or _large_) accounts, but then was deprecated since [TVM 10](https://github.com/ton-blockchain/ton/blob/master/doc/GlobalVersions.md#anycast-addresses-and-address-rewrite).\n\n### Workchain ID\n\nTON Blockchain is actually a collection of blockchains, with workchain being one of them. TON supports up to `2^32` unique workchains, each with its own rules and even virtual machines. The 8- or 32-bit `workchain_id` prefix in smart contract addresses ensures interoperability, allowing contracts to send and receive messages across different workchains.\n\nCurrently, two workchains are active:\n\n- **masterchain** (`workchain_id = -1`): contains general information about the TON blockchain protocol and the current values of its parameters, the set of validators and their stakes, the set of currently active workchains and their shards, and, most importantly, the set of hashes of the most recent blocks of all workchains and shard chains.\n- **basechain** (`workchain_id = 0`): the default workchain for most operations.\n\nBoth use **256-bit addresses** for accounts.\n\n### Account ID\n\nIn the currently used workchains, an account ID is defined as the result of applying a hash function to a [`StateInit`](/foundations/messages/deploy) structure that stores initial code and data of a smart contract.\n\n```\naccount_id = hash(initial_code, initial_data)\n```\n\nSo, for each pair (`initial_code`, `initial_data`), there exists a unique account ID to which a smart contract with such code and data can be deployed (this logic may become more complex when [TVM 11](https://github.com/ton-blockchain/ton/blob/master/doc/GlobalVersions.md#version-11) is deployed on the main network.).\n\n<Aside type=\"tip\">\n  Although the deployed smart contract code and data may change during its lifetime, the address where it's deployed does not change.\n</Aside>\n\nAdditionally, a 64-bit prefix of an account ID is crucial for the sharding process and delivering messages from one shard to another during [Hypercube Routing](/foundations/shards).\n\n## External addresses\n\nExternal addresses are closely related to [External messages](/foundations/messages/overview): ones that originate outside the blockchain or are intended for actors outside it. These messages enable interaction between smart contracts and the external world.\n\nActually, external addresses are ignored by the TON Blockchain software altogether, but may be used by external software for its own purposes.\n\nThe corresponding TL-B schemes are as follows:\n\n```tlb\naddr_none$00 = MsgAddressExt;\naddr_extern$01 len:(## 9) external_address:(bits len)\n             = MsgAddressExt.\n```\n\n- `addr_none`: it is used as a stub for the source or destination field in incoming and outgoing external messages when there is no need to put any explanatory information for off-chain actors. It is also used as a stub for the source address of internal messages, since this field is always overwritten to the correct one by the validators.\n- `addr_extern`: contains up to nine bits of additional information. For example, a special external service may inspect the destination address of all outbound external messages found in all blocks of the blockchain, and, if a special magic number is present in the `external_address` field, parse the remainder as an IP address and UDP port or a (TON Network) ADNL address, and send a datagram with a copy of the message to the network address thus obtained.\n\n## Summary\n\n- **Every actor is a smart contract**, each with a unique address for message routing.\n- **Main internal address fields**:\n  - `workchain_id` (8- or 32-bit): identifies the workchain.\n  - `account_id` (256-bit): a hash of the contract’s initial code and data.\n- **Active workchains**: masterchain and basechain, both using 256-bit ids.\n- **Flexibility**: TON supports up to `2^32` workchains, allowing future chains to customize address lengths (64–512 bits).\n- **External addresses**: may be used by external software for its own purposes but are ignored by the TON Blockchain software.\n\n## Next steps\n\nFor more technical details, refer to:\n\n- [Internal address formats](/foundations/addresses/formats): encoding rules and practical examples.\n- [Account status](/foundations/status): how addresses evolve (active, frozen, etc.).\n"
  },
  {
    "path": "foundations/addresses/serialize.mdx",
    "content": "---\ntitle: \"Reading and writing addresses\"\n---\n\nimport { Image } from '/snippets/image.jsx';\n\nOn this page, the main issues of interaction with the addresses are described:\n\n- **how to create and parse**;\n- **how to check the validity**;\n- **how to convert from one format to another**.\n\n## Using online converter\n\nThe best user-friendly online parser and address converter in TON blockchain is [TON Address tool](https://ton.org/address).\nIf the address is entered in any format, the system will provide all possible formats for the address, provided that it is entered correctly.\nOtherwise, a warning will be displayed indicating that the address is invalid.\n\n<Image\n  src=\"/resources/images/ton-addresses.png\"\n  darkSrc=\"/resources/images/ton-addresses.png\"\n  alt=\"example of query to the tool\"\n/>\n\n## Using SDK\n\nThere are at least four SDKs for interacting with TON blockchain, written in\n\n- [TypeScript](https://github.com/ton-org/ton);\n- [Java](https://github.com/neodix42/ton4j);\n- [Go](https://github.com/xssnick/tonutils-go);\n- [Python](https://github.com/nessshon/tonutils).\n\nYou can use any of them, including for working with addresses. However, we focus here on the most used one: the one written in TypeScript.\nNamely, we examine [ton-core address module](https://github.com/ton-org/ton-core/tree/main/src/address).\n\nThe internal addresses are represented as instances of the `Address` class. You can access it in your favorite IDE using the following import.\n\n```typescript\nimport { Address } from \"@ton/core\";\n\nreadonly workChain: number;\nreadonly hash: Buffer;\n```\n\nAs for the external addresses, they are represented as instances of the `ExternalAddress` class. Similarly, you can access it as follows.\n\n```typescript\nimport { ExternalAddress } from \"@ton/core\";\n\nreadonly value: bigint;\nreadonly bits: number;\n```\n\n### Create, parse, and convert addresses\n\nThe creation is simple.\n\n```typescript\n// There is a hash validation check inside the Address constructor.\nconst internalAddress = new Address(some_wc, some_valid_hash);\n\nconst externalAddress = new ExternalAddress(some_value, some_bits);\n```\n\nYou can parse the internal addresses string and then convert from one format to another as follows.\n\n```typescript\nconst address1 = Address.parse('EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPrHF');\nconst address2 = Address.parse('0:ca6e321c7cce9ecedf0a8ca2492ec8592494aa5fb5ce0387dff96ef6af982a3e');\n// or via its convenient wrapper\n// const address1 = address('EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPrHF');\n\n// const address2 = address('0:ca6e321c7cce9ecedf0a8ca2492ec8592494aa5fb5ce0387dff96ef6af982a3e');\n\n// these two addresses are equal\nconsole.log(address1.equals(address2)); // true\n\n// toString arguments: urlSafe    {true means using '-' and '_' instead of '+' and '/'; false means the opposite};\n//                     bounceable {true means the address is bounceable; false means non-bounceable};\n//                     testOnly   {true means the address is for Testnet; false means for Mainnet}.\n// default values: true, true, false.\n\nconsole.log(address1.toString()); // EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPrHF\nconsole.log(address1.toString({urlSafe: false})) // EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff+W72r5gqPrHF\nconsole.log(address1.toString({bounceable: false})) // UQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPuwA\nconsole.log(address1.toString({testOnly: true})) // kQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPgpP\nconsole.log(address1.toString({bounceable: false, testOnly: true})) // 0QDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPleK\n\n// output the address in raw format\nconsole.log(address1.toRawString()); // 0:ca6e321c7cce9ecedf0a8ca2492ec8592494aa5fb5ce0387dff96ef6af982a3e\n\n// returns a Buffer with the user‑friendly format address\naddress1.toStringBuffer();\n\n// the same for address2\nconsole.log(address2.toString()); // EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPrHF\nconsole.log(address2.toRawString()); // 0:ca6e321c7cce9ecedf0a8ca2492ec8592494aa5fb5ce0387dff96ef6af982a3e\n\n// returns a Buffer with the raw format address\naddress2.toStringBuffer();\n\n```\n\nIf you are sure that your string accurately represents the address in raw or user-friendly format, you can also use the following methods.\n\n```typescript\nconst address1 = Address.parseFriendly('EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPrHF');\nconst address2 = Address.parseRaw('0:ca6e321c7cce9ecedf0a8ca2492ec8592494aa5fb5ce0387dff96ef6af982a3e');\n```\n\n**However, there is no separate method for parsing external addresses from a string.**\n\n### Validate addresses\n\nThe validity of the address is checked at the time of its parsing. An attempt to parse an invalid address will result in an error.\nHowever, you can check separately whether a string is a valid address in raw or user-friendly formats.\n\n```typescript\nconsole.log(Address.isFriendly('EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPrHF')) // true\nconsole.log(Address.isRaw('EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPrHF')) // false\n\nconsole.log(Address.isFriendly('0:ca6e321c7cce9ecedf0a8ca2492ec8592494aa5fb5ce0387dff96ef6af982a3e')) // false\nconsole.log(Address.isRaw('0:ca6e321c7cce9ecedf0a8ca2492ec8592494aa5fb5ce0387dff96ef6af982a3e')) // true\n```\n"
  },
  {
    "path": "foundations/config.mdx",
    "content": "---\ntitle: \"Blockchain config\"\nsidebarTitle: \"Config\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\nimport { Image } from '/snippets/image.jsx';\n\n<Aside>\n  You can view live values by using [Tonviewer](https://tonviewer.com/config).\n</Aside>\n\nThis page provides a description of the configuration parameters used in the TON Blockchain.\n\nTON features a complex configuration consisting of many technical parameters, some of which are utilized by the blockchain itself, while others serve the ecosystem. However, only a limited number of individuals fully understand the significance of these parameters. This article aims to offer users a straightforward explanation of each parameter and its purpose.\n\n## Prerequisites\n\nThis material should be read alongside the parameter list.\n\nYou can view the parameter values in the [current configuration](https://tonviewer.com/config), and the method of writing them into [cells](/foundations/serialization/boc) is outlined in the [`block.tlb`](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb) file in [TL-B](/languages/tl-b/overview) format.\n\n<Aside>\n  Configuration values are TL-B typed cells serialized into [Bags of Cells (BoC)](/foundations/serialization/boc).\n</Aside>\n\nAll parameters are in place, and you won't get lost. For your convenience, please use the right sidebar for quick navigation.\n\n## Param 0: config address\n\nThis parameter is the address of a special smart contract that stores the blockchain's configuration. The configuration is stored in the contract to simplify its loading and modification during validator voting.\n\n<Aside>\n  In the configuration parameter, only the hash portion of the address is recorded, as the contract always resides in the masterchain (workchain -1). Therefore, the full address of the contract will be written as `-1:<value of the configuration parameter>`.\n</Aside>\n\n[Parameter #0 on mainnet](https://tonviewer.com/config#0)\n\n## Param 1: elector address\n\nThis parameter is the address of the [elector smart contract](/foundations/system), responsible for appointing validators, distributing rewards, and voting on changes to blockchain parameters.\n\n[Parameter #1 on mainnet](https://tonviewer.com/config#1)\n\n## Param 2: TON minting address\n\nThis parameter represents the address of the system, on behalf of which new Toncoin are minted and sent as rewards for validating the blockchain.\n\n<Aside>\n  If parameter 2 is missing, parameter 0 is used instead (newly minted Toncoin come from the configuration smart contract).\n</Aside>\n\n[Parameter #2 on mainnet](https://tonviewer.com/config#2)\n\n## Param 3: fee collector address\n\nThis parameter is the address of the transaction fee collector.\n\n<Aside>\n  If this parameter is missing (for the time being), transaction fees are directed to the elector smart contract (parameter 1).\n</Aside>\n\n[Parameter #3 on mainnet](https://tonviewer.com/config#3)\n\n## Param 4: root DNS address\n\nThis parameter is the address of the root DNS contract of the TON network.\n\n<Aside>\n  For details, see the [original specification](https://github.com/ton-blockchain/TEPs/blob/master/text/0081-dns-standard.md).\n\n  This contract is not responsible for selling **.ton** domains.\n</Aside>\n\n[Parameter #4 on mainnet](https://tonviewer.com/config#4)\n\n## Param 6: extra currency fee\n\nThis parameter is responsible for minting fees for new currencies.\n\n[Parameter #6 on mainnet](https://tonviewer.com/config#6)\n\n## Param 7: extra currency volume\n\nThis parameter stores the volume of each extra currency in circulation. The data is organized as a dictionary (also referred to as a **hashmap**). The structure uses the format `currency_id -> amount`, where the amount is represented as a `VarUInteger 32`, which is an integer ranging from `0` to `2^248-1`.\n\n[Parameter #7 on mainnet](https://tonviewer.com/config#7)\n\n## Param 8: network version\n\nThis parameter indicates the network version and additional capabilities supported by the validators.\n\n<Aside>\n  Validators are nodes in the TON Blockchain network that are responsible for creating new blocks and verifying transactions.\n</Aside>\n\n- `version`: This field specifies the version.\n\n- `capabilities`: This field is a set of flags that are used to indicate the presence or absence of certain features or capabilities.\n\nThus, when updating the network, validators will vote to change parameter 8. This way, the TON Blockchain network can be updated without downtime.\n\n[Parameter #8 on mainnet](https://tonviewer.com/config#8)\n\n## Param 9: mandatory params\n\nThis parameter contains a list (binary tree) of mandatory parameters. It ensures that certain configuration parameters are always present and cannot be removed by a proposal to change the configuration until parameter 9 changes.\n\n[Parameter #9 on mainnet](https://tonviewer.com/config#9)\n\n## Param 10: critical params\n\nThis parameter represents a list (binary tree) of critical TON parameters whose change significantly affects the network, so more voting rounds are held.\n\n[Parameter #10 on mainnet](https://tonviewer.com/config#10)\n\n## Param 11: config params\n\nThis parameter indicates under what conditions proposals to change the TON configuration are accepted.\n\n- `min_tot_rounds`: The minimum number of rounds before a proposal can be applied. Currently, this parameter is not used: only `max_tot_round` (when the proposal will be rejected) and `min_wins` (when the proposal will be accepted) matter.\n\n- `max_tot_rounds`: The maximum number of rounds, upon reaching which the proposal will automatically be rejected\n\n- `min_wins`: The required number of wins (3/4 of validators by the sum of the pledges must vote in favor)\n\n- `max_losses`: The maximum number of losses, upon reaching which the proposal will automatically be rejected\n\n- `min_store_sec` and `max_store_sec` determine the possible time interval during which the proposal will be stored\n\n- `bit_price` and `cell_price` indicate the price of storing one bit or one cell of the proposal\n\n[Parameter #11 on mainnet](https://tonviewer.com/config#11)\n\n## Param 12: Workchain config\n\nThis parameter represents the configuration of a workchain in the TON Blockchain. workchains are designed as independent blockchains that can operate in parallel, allowing TON to scale and process a large number of transactions and smart contracts.\n\n### Workchain configuration parameters\n\n- `enabled_since`: A UNIX timestamp of the moment this workchain was enabled.\n\n- `actual_min_split`: The minimum depth of the split (sharding) of this workchain, supported by validators.\n\n- `min_split`: The minimum depth of the split of this workchain, set by the configuration.\n\n- `max_split`: The maximum depth of the split of this workchain.\n\n- `basic`: A boolean flag (1 for true, 0 for false) indicating whether this workchain is basic (handles TON coins, smart contracts based on the TON Virtual Machine).\n\n- `active`: A boolean flag indicating whether this workchain is active at the moment.\n\n- `accept_msgs`: A boolean flag indicating whether this workchain is accepting messages at the moment.\n\n- `flags`: Additional flags for the workchain (reserved, currently always 0).\n\n- `zerostate_root_hash` and `zerostate_file_hash`: Hashes of the first block of the workchain.\n\n- `version`: Version of the workchain.\n\n- `format`: The format of the workchain, which includes `vm_version` and `vm_mode` - the virtual machine used there.\n\n[Parameter #12 on mainnet](https://tonviewer.com/config#12)\n\n## Param 13: complaint cost\n\nThis parameter defines the cost of filing complaints about the incorrect operation of validators in the [elector smart contract](/foundations/system).\n\n[Parameter #13 on mainnet](https://tonviewer.com/config#13)\n\n## Param 14: block reward\n\nThis parameter indicates the reward for creating a block in the TON Blockchain. Values are in nanotons (also referred to as nanograms); therefore, the reward for block creation in the masterchain is 1.7 Toncoin, while in the basechain, it is 1.0 Toncoin. In the event of a workchain split, the block reward is also divided: if there are two shardchains within the workchain, then the reward for each shard block will be 0.5 Toncoin.\n\n[Parameter #14 on mainnet](https://tonviewer.com/config#14)\n\n## Param 15: elections timing\n\nThis parameter contains the duration of different stages of elections and validators' work in the TON Blockchain.\n\nFor each validation period, there is an `election_id` equal to the UNIX-format time at the start of the validation.\n\nYou can get the current `election_id` (if elections are ongoing) or the past one by invoking the elector smart contract's respective get-methods `active_election_id` and `past_election_ids`.\n\n### Election and validation timing parameters\n\n- `validators_elected_for`: The number of seconds the elected validators perform their role (one round).\n\n- `elections_start_before`: The seconds before the end of the current round, when the election process for the next period will start.\n\n- `elections_end_before`: The seconds before the end of the current round, the validators for the next round will be chosen.\n\n- `stake_held_for`: The period for which a validator's stake is held (for handling complaints) after the round expires.\n\n<Aside>\n  Each value in the arguments is determined by the `uint32` data type.\n</Aside>\n\n### Examples\n\nIn the TON Blockchain, validation periods are typically divided into **even** and **odd** rounds that alternate. Voting for the next round occurs during the previous one, so a validator must allocate their funds into two separate pools to participate in both rounds.\n\n#### Mainnet\n\nCurrent values:\n\n```python\nconstants = {\n    'validators_elected_for': 65536,  # 18.2 hours\n    'elections_start_before': 32768,  # 9.1 hours\n    'elections_end_before': 8192,     # 2.2 hours\n    'stake_held_for': 32768           # 9.1 hours\n}\n```\n\nScheme:\n\n<Image\n  src=\"/resources/images/limits/config15-mainnet.png\"\n  darkSrc=\"/resources/images/limits/config15-mainnet.png\"\n  alt=\"Election timing scheme (Mainnet)\"\n/>\n\n#### How to calculate periods?\n\nLet `election_id = validation_start = 1600032768`. Then:\n\n```python\nelection_start = election_id - constants['elections_start_before'] = 1600032768 - 32768 = 1600000000\nelection_end = delay_start = election_id - constants['elections_end_before'] = 1600032768 - 8192 = 1600024576\nhold_start = validation_end = election_id + constants['validators_elected_for'] = 1600032768 + 65536 = 1600098304\nhold_end = hold_start + constants['stake_held_for'] = 1600098304 + 32768 = 1600131072\n```\n\nTherefore, at this time, the length of one round of one parity is `1600131072 - 1600000000 = 131072 seconds = 36.40888... hours`\n\n#### Testnet\n\nCurrent values:\n\n```python\nconstants = {\n    'validators_elected_for': 7200,  # 2 hours\n    'elections_start_before': 2400,  # 40 minutes\n    'elections_end_before': 180,     # 3 minutes\n    'stake_held_for': 900            # 15 minutes\n}\n```\n\nScheme:\n\n<Image\n  src=\"/resources/images/limits/config15-testnet.png\"\n  darkSrc=\"/resources/images/limits/config15-testnet.png\"\n  alt=\"Election timing scheme (Testnet)\"\n/>\n\n#### How to calculate periods?\n\nLet `election_id = validation_start = 160002400`. Then:\n\n```python\nelection_start = election_id - constants['elections_start_before'] = 160002400 - 2400 = 160000000\nelection_end = delay_start = election_id - constants['elections_end_before'] = 160002400 - 180 = 160002220\nhold_start = validation_end = election_id + constants['validators_elected_for'] = 160002400 + 7200 = 160009600\nhold_end = hold_start + constants['stake_held_for'] = 160009600 + 900 = 160010500\n```\n\nTherefore, at this time, the length of one round of one parity is `160010500 - 160000000 = 10500 seconds = 175 minutes = 2.91666... hours`\n\n[Parameter #15 on mainnet](https://tonviewer.com/config#15)\n\n## Param 16: validators limits\n\nThis parameter represents the limits on the number of validators in the TON Blockchain. It is directly used by the elector smart contract.\n\n### Configuration parameters for the number of validators for elections\n\n- `max_validators`: This parameter represents the maximum number of validators that can participate in the network operation at any given time.\n\n- `max_main_validators`: This parameter represents the maximum number of masterchain validators.\n\n- `min_validators`: This parameter represents the minimum number of validators that must support the network operation.\n\n#### Notes\n\n- The maximum number of validators is greater than or equal to the maximum number of masterchain validators.\n\n- The maximum number of masterchain validators must be greater than or equal to the minimum number of validators.\n\n- The minimum number of validators must be no less than 1.\n\n[Parameter #16 on mainnet](https://tonviewer.com/config#16)\n\n## Param 17: stake limits\n\nThis parameter represents the stake parameters configuration in the TON Blockchain. In many blockchain systems, especially those using the Proof-of-Stake or Delegated Proof-of-Stake consensus algorithm, cryptocurrency owners native to the network can \"stake\" their tokens to become validators and earn rewards.\n\n### Configuration parameters\n\n- `min_stake`: This parameter represents the minimum amount of Toncoin that an interested party needs to stake to participate in the validation process.\n\n- `max_stake`: This parameter represents the maximum amount of Toncoin that an interested party can stake.\n\n- `min_total_stake`: This parameter represents the minimum total amount of Toncoin that the chosen set of validators must hold.\n\n- `max_stake_factor`: This parameter is a multiplier indicating how many times the maximum effective stake (pledge) can exceed the minimum stake sent by any other validator.\n\n<Aside>\n  Each value in the arguments is determined by the `uint32` data type.\n</Aside>\n\n[Parameter #17 on mainnet](https://tonviewer.com/config#17)\n\n## Param 18: storage prices\n\nThis parameter represents the configuration for determining the prices for data storage on the TON Blockchain. This serves as a measure to prevent spam and encourages network maintenance.\n\n### Dictionary of storage fee parameters\n\n- `utime_since`: This parameter provides the initial Unix timestamp from which the specified prices apply.\n\n- `bit_price_ps` and `cell_price_ps`: These parameters represent the storage prices for one bit or one cell of information in the main workchains of the TON Blockchain for 65536 seconds.\n\n- `mc_bit_price_ps` and `mc_cell_price_ps`: These parameters represent the storage prices per bit and per cell in the TON masterchain for 65536 seconds.\n\n<Aside>\n  `utime_since` accepts values in the `uint32` data type.\n\n  The rest accept values in the `uint64` data type.\n</Aside>\n\n[Parameter #18 on mainnet](https://tonviewer.com/config#18)\n\n## Param 20 and 21: gas prices\n\nThese parameters define the cost of computations in the TON network. The complexity of any computation is estimated in gas units.\n\nNote: Param 20 defines gas settings for the masterchain; Param 21 defines gas settings for other workchains.\n\n- `flat_gas_limit` and `flat_gas_price`: A certain starting amount of gas is provided at a price of `flat_gas_price` (to offset the costs of launching the TON Virtual Machine).\n\n- `gas_price`: This parameter reflects the price of gas in the network, in nanotons per 65536 gas units.\n\n- `gas_limit`: This parameter represents the maximum amount of gas that can be consumed per transaction.\n\n- `special_gas_limit`: This parameter represents the limit on the amount of gas that can be consumed per transaction of a special (system) contract.\n\n- `gas_credit`: This parameter represents a credit in gas units provided to transactions to process an external message.\n\n- `block_gas_limit`: This parameter represents the maximum amount of gas that can be consumed within a single block.\n\n- `freeze_due_limit` and `delete_due_limit`: Limits of accumulated storage fees (in nanotons) at which a contract is frozen and deleted, respectively.\n\n<Aside>\n  You can find more about `gas_credit` and other parameters in the section of external messages [here](/tvm/instructions#external-messages).\n</Aside>\n\n[Parameter #20 on mainnet](https://tonviewer.com/config#20) | [Parameter #21 on mainnet](https://tonviewer.com/config#21)\n\n## Param 22 and 23: block limits\n\nThese parameters set limits on the block, upon reaching which the block is finalized and the callback of the remaining messages (if any) is carried over to the next block.\n\n### Configuration parameters\n\n- `bytes`: This section sets the limits on the block size in bytes.\n\n- `underload`: Underload is a state when the shard realizes that there is no load and is inclined to merge if a neighboring shard is willing.\n\n- `soft_limit`: Soft limit - when this limit is reached, internal messages stop being processed.\n\n- `hard_limit`: Hard limit - this is the absolute maximum size.\n\n- `gas`: This section sets the limits on the amount of gas that a block can consume. Gas, in the context of blockchain, is an indicator of computational work. The limits on underload, soft and hard limits work the same as for size in bytes.\n\n- `lt_delta`: This section sets the limits on the difference in logical time between the first and last transaction. Logical time is a concept used in the TON Blockchain for ordering events. The limits on underload, soft and hard limits work the same as for size in bytes and gas.\n\n<Aside>\n  If a shard has insufficient load and there is an intention to merge with a neighboring shard, the `soft_limit` indicates a threshold. When this threshold is exceeded, internal messages will stop being processed, while external messages will still be handled. External messages will continue to be processed until the total reaches a limit that is equal to half the sum of the `soft_limit` and `hard_limit`, or `(soft_limit + hard_limit) / 2`.\n</Aside>\n\n[Parameter #22 on mainnet](https://tonviewer.com/config#22) | [Parameter #23 on mainnet](https://tonviewer.com/config#23)\n\n## Param 24 and 25: message price\n\nParameter 24 represents the configuration for the cost of sending messages in the masterchain of the TON Blockchain.\n\nParameter 25 represents the configuration for the cost of sending messages in all other cases.\n\n### Configuration parameters defining the costs of forwarding\n\n- `lump_price`: This parameter means the base price for forwarding a message, regardless of its size or complexity.\n\n- `bit_price`: This parameter represents the cost per bit of message forwarding.\n\n- `cell_price`: This parameter reflects the cost of forwarding a message per cell. A cell is the basic unit of data storage on the TON Blockchain.\n\n- `ihr_price_factor`: This is a factor used to calculate the cost of immediate hypercube routing (IHR).\n\n<Aside>\n  IHR is a method of message delivery in the TON Blockchain network, where messages are sent directly to the recipient's shardchain.\n</Aside>\n\n- `first_frac`: This parameter defines the fraction of the remaining amount that will be used for the first transition along the message route.\n\n- `next_frac`: This parameter defines the fraction of the remaining amount that will be used for subsequent transitions along the message route.\n\n[Parameter #24 on mainnet](https://tonviewer.com/config#24) | [Parameter #25 on mainnet](https://tonviewer.com/config#25)\n\n## Param 28: catchain config\n\nThis parameter provides the configuration for the `Catchain` protocol in the TON Blockchain. `Catchain` is the lowest-level consensus protocol used in the TON to achieve agreement among validators.\n\n### Configuration parameters\n\n- `flags`: A general field that can be used to set various binary parameters. In this case, it equals 0, which means that no specific flags are set.\n\n- `shuffle_mc_validators`: A Boolean value indicating whether to shuffle the masterchain validators or not. If this parameter is set to 1, the validators will be shuffled; otherwise, they will not.\n\n- `mc_catchain_lifetime`: The lifetime of masterchain's `Catchain` groups in seconds.\n\n- `shard_catchain_lifetime`: The lifetime of shardchain's `Catchain` groups in seconds.\n\n- `shard_validators_lifetime`: The lifetime of a shardchain's validators group in seconds.\n\n- `shard_validators_num`: The number of validators in each shardchain validation group.\n\n[Parameter #28 on mainnet](https://tonviewer.com/config#28)\n\n## Param 29: consensus config\n\nThis parameter provides the configuration for the consensus protocol above `Catchain` ([Param 28](#param-28)) in the TON Blockchain. The consensus protocol is a crucial component of a blockchain network, and it ensures that all nodes agree on the state of the distributed ledger.\n\n### Configuration parameters\n\n- `flags`: A general field that can be used to set various binary parameters.\n\n- `new_catchain_ids`: A Boolean value indicating whether to generate new `Catchain` identifiers.\n\n- `round_candidates`: The number of candidates to be considered in each round of the consensus protocol.\n\n- `next_candidate_delay_ms`: The delay in milliseconds before the right to generate a block candidate passes to the next validator.\n\n- `consensus_timeout_ms`: The timeout for block consensus in milliseconds.\n\n- `fast_attempts`: The number of \"fast\" attempts to reach consensus.\n\n- `attempt_duration`: The duration of each attempt at agreement, in seconds.\n\n- `catchain_max_deps`: The maximum number of dependencies of a Catchain block.\n\n- `max_block_bytes`: The maximum size of a block in bytes.\n\n- `max_collated_bytes`: The maximum size of serialized block correctness proofs in bytes.\n\n- `proto_version`: The protocol version.\n\n- `catchain_max_blocks_coeff`: The coefficient limiting the rate of block generation in `Catchain`, [description](https://github.com/ton-blockchain/ton/blob/master/doc/catchain-dos.md).\n\nFor up-to-date values, see [https://tonviewer.com/config](https://tonviewer.com/config).\n\n[Parameter #29 on mainnet](https://tonviewer.com/config#29)\n\n## Param 31: fee-exempt contracts\n\nThis parameter represents the configuration of smart contract addresses from which no fees are charged for either gas or storage, and where **tick-tock** transactions can be created. The list usually includes governance contracts. The parameter is presented as a binary tree structure — a tree (HashMap 256), where the keys are a 256-bit representation of the address. Only addresses in the masterchain can be present in this list.\n\n[Parameter #31 on mainnet](https://tonviewer.com/config#31)\n\n## Param 32, 34, and 36: validator lists\n\nLists of validators from the previous (32), current (34), and next (36) rounds. Parameter 36 is set from the end of the elections until the start of the round.\n\n### Configuration parameters\n\n- `cur_validators`: This is the current list of validators. Validators are typically responsible for verifying transactions in a blockchain network.\n\n- `utime_since` and `utime_until`: These parameters provide the time period during which these validators are active.\n\n- `total` and `main`: These parameters provide the total number of validators and the number of validators validating the masterchain in the network.\n\n- `total_weight`: This adds up the weights of the validators.\n\n- `list`: A list of validators in the tree format `id->validator-data`: `validator_addr`, `public_key`, `weight`, `adnl_addr`: These parameters provide details about each validator - their 256-bit addresses in the masterchain, public key, weight, ADNL address (the address used at the network level of the TON).\n\n[Parameter #32 on mainnet](https://tonviewer.com/config#32) | [Parameter #34 on mainnet](https://tonviewer.com/config#34) | [Parameter #36 on mainnet](https://tonviewer.com/config#36)\n\n## Param 40: misbehavior punishment\n\nThis parameter defines the structure of the configuration for punishment for improper behavior (non-validation). In the absence of the parameter, the default fine size is 101 Toncoin.\n\n### Configuration parameters\n\n`MisbehaviourPunishmentConfig`: This data structure defines how improper behavior in the system is punished.\n\nIt contains several fields:\n\n- `default_flat_fine`: This part of the fine does not depend on the stake size.\n\n- `default_proportional_fine`: This part of the fine is proportional to the validator's stake size.\n\n- `severity_flat_mult`: This is the multiplier applied to the `default_flat_fine` value for significant violations by the validator.\n\n- `severity_proportional_mult`: This is the multiplier applied to the `default_proportional_fine` value for significant violations by the validator.\n\n- `unpunishable_interval`: This parameter represents the period during which offenders are not punished to eliminate temporary network problems or other anomalies.\n\n- `long_interval`, `long_flat_mult`, `long_proportional_mult`: These parameters define a \"long\" period of time and multipliers for flat and proportional fines for improper behavior.\n\n- `medium_interval`, `medium_flat_mult`, `medium_proportional_mult`: Similarly, they define a \"medium\" period of time and multipliers for flat and proportional fines for improper behavior.\n\n[Parameter #40 on mainnet](https://tonviewer.com/config#40)\n\n## Param 43: account and message limits\n\nThis parameter relates to the size limits and other features of accounts and messages.\n\n### Configuration parameters\n\n- `max_msg_bits`: Maximum message size in bits.\n\n- `max_msg_cells`: Maximum number of cells (a form of storage unit) a message can occupy.\n\n- `max_library_cells`: Maximum number of cells that can be used for library cells.\n\n- `max_vm_data_depth`: Maximum cell depth in messages and account state.\n\n- `max_ext_msg_size`: Maximum external message size in bits.\n\n- `max_ext_msg_depth`: Maximum external message depth. This could refer to the depth of the data structure within the message.\n\n- `max_acc_state_cells`: Maximum number of cells that an account state can occupy.\n\n- `max_acc_state_bits`: Maximum account state size in bits.\n\nIf absent, the default parameters are taken:\n\n- `max_size` = 65535\n\n- `max_depth` = 512\n\n- `max_msg_bits` = 1 \\<\\< 21\n\n- `max_msg_cells` = 1 \\<\\< 13\n\n- `max_library_cells` = 1000\n\n- `max_vm_data_depth` = 512\n\n- `max_acc_state_cells` = 1 \\<\\< 16\n\n- `max_acc_state_bits` = (1 \\<\\< 16) \\* 1023\n\n<Aside>\n  You can view more details about the standard parameters [here](https://github.com/ton-blockchain/ton/blob/fc9542f5e223140fcca833c189f77b1a5ae2e184/crypto/block/mc-config.h#L379) in the source code.\n</Aside>\n\n[Parameter #43 on mainnet](https://tonviewer.com/config#43)\n\n## Param 44: suspended addresses\n\nThis parameter defines the list of suspended addresses, which cannot be initialized until `suspended_until`. It only applies to yet uninitiated accounts. This is a measure for stabilizing the tokenomics (limiting early miners). If not set, there are no limitations. Each address is represented as an end node in this tree, and the tree-like structure allows efficient checking of whether an address is in the list.\n\n<Aside>\n  The stabilization of the tokenomics is further described in the [official report](https://t.me/tonblockchain/178) of the `@tonblockchain` Telegram channel.\n</Aside>\n\n[Parameter #44 on mainnet](https://tonviewer.com/config#44)\n\n## Param 45: precompiled contracts\n\nThe list of precompiled contracts is stored in the masterchain config:\n\n```tlb\nprecompiled_smc#b0 gas_usage:uint64 = PrecompiledSmc;\nprecompiled_contracts_config#c0 list:(HashmapE 256 PrecompiledSmc) = PrecompiledContractsConfig;\n_ PrecompiledContractsConfig = ConfigParam 45;\n```\n\nMore details about precompiled contracts are on [this page](/foundations/precompiled).\n\n[Parameter #45 on mainnet](https://tonviewer.com/config#45)\n\n## Param 71 - 73: outbound bridges\n\nThis parameter pertains to bridges for wrapping Toncoin in other networks:\n\n- ETH-TON **(71)**\n\n- BNB-TON **(72)**\n\n- Polygon-TON **(73)**\n\n### Configuration parameters\n\n- `bridge_address`: This is the bridge contract address that accepts TON to issue wrapped Toncoin in other networks.\n\n- `oracle_multisig_address`: This is the bridge management wallet address. A multisig wallet is a type of digital wallet that requires signatures from multiple parties to authorize a transaction. It is often used to increase security. The oracles act as the parties.\n\n- `oracles`: List of oracles in the form of a tree `id->address`\n\n- `external_chain_address`: This is the bridge contract address in the corresponding external blockchain.\n\n[Parameter #71 on mainnet](https://tonviewer.com/config#71) | [Parameter #72 on mainnet](https://tonviewer.com/config#72) | [Parameter #73 on mainnet](https://tonviewer.com/config#73)\n\n## Param 79, 81, and 82: inbound bridges\n\nThis parameter relates to bridges for wrapping tokens from other networks into tokens on the TON network:\n\n- ETH-TON **(79)**\n\n- BNB-TON **(81)**\n\n- Polygon-TON **(82)**\n\n### Configuration parameters\n\n- `bridge_address` and `oracles_address`: These are the blockchain addresses of the bridge and the bridge management contract (oracles multisig), respectively.\n\n- `oracles`: List of oracles in the form of a tree `id->address`\n\n- `state_flags`: State flag. This parameter is responsible for enabling/disabling separate bridge functions.\n\n- `prices`: This parameter contains a list or dictionary of prices for different operations or fees associated with the bridge, such as `bridge_burn_fee`, `bridge_mint_fee`, `wallet_min_tons_for_storage`, `wallet_gas_consumption`, `minter_min_tons_for_storage`, `discover_gas_consumption`.\n\n- `external_chain_address`: The bridge contract address in another blockchain.\n\n[Parameter #79 on mainnet](https://tonviewer.com/config#79) | [Parameter #81 on mainnet](https://tonviewer.com/config#81) | [Parameter #82 on mainnet](https://tonviewer.com/config#82)\n\n## Negative parameters\n\n<Aside>\n  Validators enforce TL-B validity only for configuration parameters with non-negative indices. Values with negative indices are not validated against a specific `ConfigParam i` type. See the explanation in [Configuration parameters](/foundations/config) section.\n</Aside>\n\n## Next steps\n\nAfter thoroughly reviewing this article, it is highly recommended that you dedicate time to a more in-depth study of the following documents:\n\n- The original descriptions are present, but they may be limited, in the documents:\n  - [The Open Network Whitepaper](/foundations/whitepapers/ton)\n  - [Telegram Open Network Blockchain](/foundations/whitepapers/tblkch)\n\n- Source code:\n  - [`mc-config.h`](https://github.com/ton-blockchain/ton/blob/fc9542f5e223140fcca833c189f77b1a5ae2e184/crypto/block/mc-config.h)\n  - [`block.tlb`](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb)\n"
  },
  {
    "path": "foundations/consensus/catchain-visualizer.mdx",
    "content": "---\ntitle: \"Catchain & BCP visualizer\"\ndescription: \"Interactive visual simulation of Catchain + BCP rounds\"\nmode: \"wide\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\"\nimport { CatchainVisualizer } from \"/snippets/catchain-visualizer.jsx\"\n\nTo understand this simulation, read [Catchain whitepaper](/foundations/whitepapers/catchain) first.\n\n<CatchainVisualizer\n\n/>\n\n## Interact with the simulation\n\n- Click nodes to view status (locks/commits) and toggle behavior (good, crash, lagging).\n- Click **Adjust simulation config** at the top to change consensus simulation parameters.\n- Hover over the **Event types** at the bottom to read short description.\n- Click moving messages to inspect sender/receiver, timings, and embedded actions; drop a message from the overlay with **Drop message** button.\n- Click **Candidates** in the sidebar to see proposer, priority, and per-node approvals/votes/pre-commits/commits observed.\n- Use the speed slider to slow down/accelerate the sim; use **Restart round** to begin a new round.\n\n## Simulation notes\n\n<Aside>\n  This is a teaching simulation, not the exact C++ `validator-session` implementation of the whitepaper. It contains certain simplifications.\n</Aside>\n\n- Timing is approximate; actions are driven by the sim loop and simplified delays, not the precise `check_all/process_blocks` cadence.\n- Catchain dependency handling is simplified: if a node sees a message but lacks one of its parents, it asks peers for that missing block (no vector-time sync).\n- Quorums use equal weights (counts), not stake weights.\n- Submits are auto-scheduled per priority window; retries and network sync differ from the real catchain/validator logic.\n- Null candidate is assumed after its delay; VoteFor/slow-mode handling is simplified.\n"
  },
  {
    "path": "foundations/fees.mdx",
    "content": "---\ntitle: \"Transaction fees\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nFees in TON align with the [execution phases](/foundations/phases) of a transaction:\n\n- Storage fees are charged in the [storage phase](/foundations/phases#storage-phase).\n- Compute fees are charged in the [compute phase](/foundations/phases#compute-phase).\n- Forward and action fees are charged in the [action](/foundations/phases#action-phase) and [bounce phases](/foundations/phases#bounce-phase).\n- Import fees apply at the start of smart contract execution, not a specific phase.\n\nThe total transaction fee is the sum of these components.\n\nValidators set fee levels through voting:\n\n- Storage fees are set in [config parameter 18](/foundations/config#param-18:-storage-prices).\n- Compute fees are set in [config parameters 20 and 21](/foundations/config#param-20-and-21:-gas-prices).\n- Forward, import, and action fees are set in [config parameters 24 and 25](/foundations/config#param-24-and-25:-message-price).\n\n## Storage fees\n\n```cpp\nbasic_price = (account.bits * bit_price +\n              account.cells * cell_price)\nstorage_fee = ceil(basic_price * time_delta / 2^16)\n```\n\nThe storage fee uses `account.bits` and `account.cells` from `AccountStorage`, excluding `ExtraCurrencyCollection` stored in the `other` field. The `other` field is replaced with a single `0` bit that represents an empty `HashmapE`.\n\n```tlb\nextra_currencies$_ dict:(HashmapE 32 (VarUInteger 32))\n                 = ExtraCurrencyCollection;\ncurrencies$_ grams:Grams other:ExtraCurrencyCollection\n           = CurrencyCollection;\n\naccount_storage$_ last_trans_lt:uint64\n    balance:CurrencyCollection state:AccountState\n  = AccountStorage;\n```\n\n<Aside\n  type=\"note\"\n  title=\"Deduplication\"\n>\n  Storage and forward fees treat identical subtrees referenced in multiple branches as one cell. Reused subtrees share a single stored copy and do not accrue additional charges.\n</Aside>\n\n## Compute fees\n\nAll computation is measured in gas units. A TVM operation typically has a fixed gas cost, but that is [not always the case](/tvm/gas). Network configuration defines gas prices; users cannot override them.\n\n### Flat gas limit\n\nA contract invocation pays for at least `flat_gas_limit` gas units. Spending up to that limit costs `flat_gas_price` TON. If the contract spends `gasUsed` gas units, the fee is:\n\n```ts\nconst gasUsed = 50_000n;\n// 0 = basechain, -1 = masterchain\nconst prices = getGasPrices(configCell, 0);\nconst gasFee =\n    gasUsed <= prices.flat_gas_limit\n    ? prices.flat_gas_price\n    : prices.flat_gas_price +\n    (prices.gas_price * (gasUsed - prices.flat_gas_limit)) / 65536n;\n```\n\n## Forward fee\n\nForward fee is calculated with this formula:\n\n```\nbodyFwdFee = priceForCells * (msgSizeInCells - 1)\n           + priceForBits * (msgSizeInBits - bitsInRoot)\n\nfwdFee = lumpPrice + ceil(bodyFwdFee / 2^16)\n```\n\nwhere:\n\n- `lumpPrice` is the fixed value [from config](/foundations/config#param-24-and-25%3A-message-price) paid once for the message.\n- `msgSizeInCells` is the number of cells in the message.\n- `msgSizeInBits` is the number of bits in all the cells of the message.\n- `bitsInRoot` is the number of bits in the root cell of the message.\n\nThe formula excludes the message root cell because it mainly contains headers. `lumpPrice` covers that root cell.\n\n### Action fee\n\nAction fee is the portion of `fwdFee` granted to the validator of the message's source [shard](/foundations/shards#blockchain-sharding). The remaining `fwdFee - actionFee` amount goes to the validator of the destination shard.\n\nAction fee exists only for [internal messages](/foundations/messages/internal#internal-messages).\n\n```cpp\naction_fee = floor(fwd_fee * first_frac / 2^16)\n```\n\nStarting with Global Version 4, a failed [SENDMSG action](/foundations/actions/send#send-message) incurs a penalty proportional to the attempted message size. It is calculated as:\n\n```cpp\nfine_per_cell = floor((cell_price >> 16) / 4)\nmax_cells = floor(remaining_balance / fine_per_cell)\naction_fine = fine_per_cell * min(max_cells, cells_in_msg);\n```\n\n## Import fee\n\nImport fee mirrors forward fee for inbound external messages. The root cell and its contents are covered by `lumpPrice` in the same way as internal messages.\n\n## Helper functions (full code)\n\n```ts expandable\nimport { Cell, Slice, beginCell, Dictionary, Message, DictionaryValue } from '@ton/core';\n\nexport type GasPrices = {\n\tflat_gas_limit: bigint,\n\tflat_gas_price: bigint,\n\tgas_price: bigint\n};\n\nexport type StorageValue = {\n    utime_since: number,\n    bit_price_ps: bigint,\n    cell_price_ps: bigint,\n    mc_bit_price_ps: bigint,\n    mc_cell_price_ps: bigint\n};\n\nexport class StorageStats {\n    bits: bigint;\n    cells: bigint;\n\n    constructor(bits?: number | bigint, cells?: number | bigint) {\n        this.bits  = bits  !== undefined ? BigInt(bits)  : 0n;\n        this.cells = cells !== undefined ? BigInt(cells) : 0n;\n    }\n    add(...stats: StorageStats[]) {\n        let cells = this.cells, bits = this.bits;\n        for (let stat of stats) {\n            bits  += stat.bits;\n            cells += stat.cells;\n        }\n        return new StorageStats(bits, cells);\n    }\n    addBits(bits: number | bigint) {\n        return new StorageStats(this.bits + BigInt(bits), this.cells);\n    }\n    addCells(cells: number | bigint) {\n        return new StorageStats(this.bits, this.cells + BigInt(cells));\n    }\n}\n\nfunction shr16ceil(src: bigint) {\n    const rem = src % 65536n;\n    let res = src / 65536n;\n    if (rem !== 0n) res += 1n;\n    return res;\n}\n\nexport function collectCellStats(cell: Cell, visited: Array<string>, skipRoot: boolean = false): StorageStats {\n    let bits  = skipRoot ? 0n : BigInt(cell.bits.length);\n    let cells = skipRoot ? 0n : 1n;\n    const hash = cell.hash().toString();\n    if (visited.includes(hash)) {\n        return new StorageStats();\n    }\n    visited.push(hash);\n    for (const ref of cell.refs) {\n        const r = collectCellStats(ref, visited);\n        cells += r.cells;\n        bits += r.bits;\n    }\n    return new StorageStats(bits, cells);\n}\n\nexport function getGasPrices(configRaw: Cell, workchain: 0 | -1): GasPrices {\n    const config = configRaw.beginParse().loadDictDirect(Dictionary.Keys.Int(32), Dictionary.Values.Cell());\n    const ds = config.get(21 + workchain)!.beginParse();\n    if (ds.loadUint(8) !== 0xd1) throw new Error('Invalid flat gas prices tag');\n    const flat_gas_limit = ds.loadUintBig(64);\n    const flat_gas_price = ds.loadUintBig(64);\n    if (ds.loadUint(8) !== 0xde) throw new Error('Invalid gas prices tag');\n    return { flat_gas_limit, flat_gas_price, gas_price: ds.preloadUintBig(64) };\n}\n\nexport function computeGasFee(prices: GasPrices, gas: bigint): bigint {\n    if (gas <= prices.flat_gas_limit) return prices.flat_gas_price;\n    return prices.flat_gas_price + (prices.gas_price * (gas - prices.flat_gas_limit)) / 65536n;\n}\n\nexport const storageValue: DictionaryValue<StorageValue> = {\n    serialize: (src, builder) => {\n        builder\n            .storeUint(0xcc, 8)\n            .storeUint(src.utime_since, 32)\n            .storeUint(src.bit_price_ps, 64)\n            .storeUint(src.cell_price_ps, 64)\n            .storeUint(src.mc_bit_price_ps, 64)\n            .storeUint(src.mc_cell_price_ps, 64);\n    },\n    parse: (src) => {\n        return {\n            utime_since: src.skip(8).loadUint(32),\n            bit_price_ps: src.loadUintBig(64),\n            cell_price_ps: src.loadUintBig(64),\n            mc_bit_price_ps: src.loadUintBig(64),\n            mc_cell_price_ps: src.loadUintBig(64)\n        };\n    }\n};\n\nexport function getStoragePrices(configRaw: Cell): StorageValue {\n    const config = configRaw.beginParse().loadDictDirect(Dictionary.Keys.Int(32), Dictionary.Values.Cell());\n    const storageData = Dictionary.loadDirect(Dictionary.Keys.Uint(32), storageValue, config.get(18)!);\n    const values = storageData.values();\n    return values[values.length - 1];\n}\n\nexport function calcStorageFee(prices: StorageValue, stats: StorageStats, duration: bigint) {\n    return shr16ceil((stats.bits * prices.bit_price_ps + stats.cells * prices.cell_price_ps) * duration);\n}\n\nexport const configParseMsgPrices = (sc: Slice) => {\n    const magic = sc.loadUint(8);\n    if (magic !== 0xea) throw new Error('Invalid message prices magic number');\n    return {\n        lumpPrice: sc.loadUintBig(64),\n        bitPrice: sc.loadUintBig(64),\n        cellPrice: sc.loadUintBig(64),\n        ihrPriceFactor: sc.loadUintBig(32),\n        firstFrac: sc.loadUintBig(16),\n        nextFrac: sc.loadUintBig(16)\n    };\n};\n\nexport type MsgPrices = ReturnType<typeof configParseMsgPrices>;\n\nexport const getMsgPrices = (configRaw: Cell, workchain: 0 | -1) => {\n    const config = configRaw.beginParse().loadDictDirect(Dictionary.Keys.Int(32), Dictionary.Values.Cell());\n    const prices = config.get(25 + workchain);\n    if (prices === undefined) throw new Error('No prices defined in config');\n    return configParseMsgPrices(prices.beginParse());\n};\n\nexport function computeDefaultForwardFee(msgPrices: MsgPrices) {\n    return msgPrices.lumpPrice - ((msgPrices.lumpPrice * msgPrices.firstFrac) >> 16n);\n}\n\nexport function computeFwdFees(msgPrices: MsgPrices, cells: bigint, bits: bigint) {\n    return msgPrices.lumpPrice + shr16ceil(msgPrices.bitPrice * bits + msgPrices.cellPrice * cells);\n}\n\nexport function computeFwdFeesVerbose(msgPrices: MsgPrices, cells: bigint | number, bits: bigint | number) {\n    const fees = computeFwdFees(msgPrices, BigInt(cells), BigInt(bits));\n    const res = (fees * msgPrices.firstFrac) >> 16n;\n    return { total: fees, res, remaining: fees - res };\n}\n\nexport function computeCellForwardFees(msgPrices: MsgPrices, msg: Cell) {\n    const storageStats = collectCellStats(msg, [], true);\n    return computeFwdFees(msgPrices, storageStats.cells, storageStats.bits);\n}\n\nexport function computeMessageForwardFees(msgPrices: MsgPrices, msg: Message) {\n    if (msg.info.type !== 'internal') throw new Error('Helper intended for internal messages');\n    let storageStats = new StorageStats();\n\n    const defaultFwd = computeDefaultForwardFee(msgPrices);\n    if (msg.info.forwardFee === defaultFwd) {\n        return {\n            fees: msgPrices.lumpPrice,\n            res: defaultFwd,\n            remaining: defaultFwd,\n            stats: storageStats\n        };\n    }\n\n    const visited: Array<string> = [];\n\n    if (msg.init) {\n        let addBits = 5n;\n        let refCount = 0;\n        if (msg.init.splitDepth) addBits += 5n;\n        if (msg.init.libraries) {\n            refCount++;\n            storageStats = storageStats.add(\n                collectCellStats(beginCell().storeDictDirect(msg.init.libraries).endCell(), visited, true)\n            );\n        }\n        if (msg.init.code) {\n            refCount++;\n            storageStats = storageStats.add(collectCellStats(msg.init.code, visited));\n        }\n        if (msg.init.data) {\n            refCount++;\n            storageStats = storageStats.add(collectCellStats(msg.init.data, visited));\n        }\n        if (refCount >= 2) {\n            storageStats = storageStats.addCells(1).addBits(addBits);\n        }\n    }\n\n    const lumpBits = BigInt(msg.body.bits.length);\n    const bodyStats = collectCellStats(msg.body, visited, true);\n    storageStats = storageStats.add(bodyStats);\n\n    let feesVerbose = computeFwdFeesVerbose(msgPrices, storageStats.cells, storageStats.bits);\n    if (feesVerbose.remaining < msg.info.forwardFee) {\n        storageStats = storageStats.addCells(1).addBits(lumpBits);\n        feesVerbose = computeFwdFeesVerbose(msgPrices, storageStats.cells, storageStats.bits);\n    }\n    if (feesVerbose.remaining !== msg.info.forwardFee) {\n        throw new Error('Forward fee calculation mismatch');\n    }\n    return { fees: feesVerbose, stats: storageStats };\n}\n```\n"
  },
  {
    "path": "foundations/glossary.mdx",
    "content": "---\ntitle: \"Glossary\"\n---\n\n## A\n\n### Airdrop\n\na free distribution of tokens among specific participants.\n\n### Altcoin\n\nall cryptocurrencies, except Bitcoin, are called altcoins.\n\n### Application Programming Interface (API)\n\na mechanism that allows two programs to interact with each other through a series of protocols.\n\n### Annual Percentage Yield (APY)\n\na calculated yearly interest rate for a given asset.\n\n---\n\n## B\n\n### Bearish\n\nthe term “bearish” is used when the price of an asset has declined due to investors selling. (The term is often used to describe the overall market sentiment.)\n\n### Binance\n\na major cryptocurrency exchange. [Website](https://www.binance.com/).\n\n### Bitcoin (BTC)\n\nthe preeminent cryptocurrency and the first decentralized network with open-source code, which laid the groundwork for the proliferation of blockchain technology. [**Wikipedia**](https://en.wikipedia.org/wiki/Bitcoin).\n\n### Blockchain\n\na distributed ledger of data in the form of a chain of blocks recording transaction information for every event on the network.\n\n### Bag of Cells (BoC)\n\nserialization format for cells. Commonly used in code. [Article](/foundations/serialization/boc).\n\n### Bot\n\na program written for two ecosystems to interact with each other — e.g., The Open Network and the Telegram messenger. On Telegram, bots are accounts in the messenger operated by software.\n\n### Bridge\n\na program connecting various blockchains to transfer tokens and data from one network to another. [Article](/ecosystem/oracles/overview).\n\n### Bullish\n\nthe term “bullish” is used to describe an asset whose value is appreciating. (“Bullish” is the opposite of “bearish” — i.e., when the market's overall value is increasing.)\n\n### Burning\n\nthe act of permanently removing tokens from circulating and total supply.\n\n---\n\n## C\n\n### Centralized exchange (CEX)\n\na centralized cryptocurrency exchange to trade tokens.\n\n### CoinMarketCap (CMC)\n\na crypto information aggregator that closely follows changes in token prices and market capitalization. [Website](https://coinmarketcap.com/).\n\n### Coinbase\n\na major cryptocurrency exchange based in the United States. [Website](https://www.coinbase.com/).\n\n### Cryptobot\n\na peer-to-peer (P2P) bot service for buying, trading, and selling Toncoin and other cryptocurrencies.\n\n### Custodial\n\na type of crypto wallet where a third party stores cryptocurrencies, and not their true owner.\n\n---\n\n## D\n\n### Decentralized application (dApp)\n\napplications run on-chain and rely on smart contracts for computation, storage, and communication.\n\n### Dollar-cost averaging (DCA)\n\nan investment strategy whereby investors buy a fixed amount at regular intervals regardless of price to reduce timing risk.\n\n### Decentralization\n\none of the main tenets behind TON and other blockchains. Without decentralization, Web3 would be impossible to achieve; therefore, every element of the TON ecosystem revolves around maximizing decentralization.\n\n### DeFi\n\nthe decentralized analog to traditional finance; it includes accessible financial services and applications based on smart contracts.\n\n### Decentralized exchange (DEX)\n\nan exchange where users can trade cryptocurrencies without any intermediaries. The online entity needed to guarantee safe transactions is the blockchain itself.\n\n### Diamond hands\n\na colloquial term describing an investor who has no intention of selling their assets regardless of the state of the market — even if there's a crash or the market is bearish.\n\n### Domain Name System (DNS)\n\na technology that translates human-readable domain names (e.g. ton.org) to machine-readable IP addresses (e.g. 192.0.2.44).\n\n### Dolphin\n\nan investor who has relatively small capital but has an influence on the community.\n\n### Donate\n\na bot service on Telegram through which people can donate money, and content creators can monetize their channels and services in Toncoin.\n\n### Dump\n\nrapidly selling a cryptocurrency or asset, often causing a price decline.\n\n### Durov\n\nPavel Durov, a Russian entrepreneur who is famous for having founded the VK social network and Telegram messenger.\n\nNikolai Durov is Pavel's brother, who helped develop VK, Telegram, and TON.\n\n### Do Your Own Research (DYOR)\n\nthe process by which you do research on a project, company or cryptocurrency before deciding to invest.\n\n---\n\n## E\n\n### Ethereum Virtual Machine (EVM)\n\na machine behaving like a decentralized computer, it computes the state of the Ethereum blockchain after each new block and executes smart contracts.\n\n### Exchange\n\na place for trading and using other market instruments.\n\n---\n\n## F\n\n### Farming\n\nlending your crypto assets to receive rewards.\n\n### Fiat\n\nregular money issued by central banks or financial authorities.\n\n### Fear of missing out (FOMO)\n\na psychological state that consumes some investors when the idea of losing potential gains from an opportunity is present. It usually appears during a bull market and when traders don't do their due diligence analyzing a particular project.\n\n### Fungible tokens\n\ncryptocurrencies that carry the same value as any other token of the same kind at any given moment.\n\n### FUD\n\n“fear, uncertainty, and doubt,” market sentiments based on many factors.\n\n### Full node\n\na computer on blockchain that synchronizes and copies the entire blockchain.\n\n### FunC\n\nthe smart contract language on TON.\n\n---\n\n## G\n\n### Gas\n\nthe fee paid for transactions on the blockchain.\n\n### GitHub\n\na platform for hosting code and collaborating via Git repositories.\n\n---\n\n## H\n\n### Hackathon\n\na collaborative event where programmers and builders develop software projects.\n\n### Hash\n\na fixed-size digest computed from data using a hashing algorithm.\n\n### Hash rate\n\nthe indication of how much computational power is being used on a network for crypto mining.\n\n### Hold\n\nsaving — i.e., not selling — an asset or assets from your portfolio.\n\n---\n\n## I\n\n### Initial Coin Offering (ICO)\n\na method for crypto projects to attract capital in the early stages.\n\n### Initial Decentralized exchange Offering (IDO)\n\na method of attracting capital when launching a cryptocurrency or token on a decentralized exchange.\n\n### Inflation\n\nthe process when the value of a currency — e.g., U.S. dollar or the euro — decreases. Toncoin has predictable issuance and a low inflation rate.\n\n---\n\n## K\n\n### Know Your Customer (KYC)\n\nthe process by which a user verifies their identity when creating an account for a crypto service.\n\n---\n\n## L\n\n### Launchpad\n\na platform for crypto startups that brings investors and projects together.\n\n### Liquidity pool\n\ngrouping together crypto assets and freezing them in a smart contract. Liquidity pools are used for decentralized trading, loans, and other endeavors.\n\n---\n\n## M\n\n### Mainnet\n\nthe main network of a blockchain.\n\n### Market capitalization (market cap)\n\nthe total market value of a cryptocurrency's circulating supply.\n\n### Masterchain\n\nthe main chain that references shard and workchain blocks; a shard block is finalized once a Masterchain block references it.\n\n### Metaverse\n\na digital universe similar to a video game where users create avatars and interact with the digital representations of other people or users.\n\n### Moon\n\na crypto term that describes a crypto asset's vertical trajectory on a price chart — i.e., it quickly gains value.\n\n---\n\n## N\n\n### \"Not financial advice\" (NFA)\n\nacronym used as a disclaimer to avoid liability or responsibility when investors discuss cryptocurrencies or projects with other people.\n\n### Non-fungible token (NFT)\n\na unique digital token on a blockchain that cannot be duplicated or minted more than once.\n\n### Nominator\n\nthose who provide financial resources to validators so the latter can confirm blocks on TON blockchain.\n\n### Non-custodial\n\na kind of crypto wallet that gives full control over assets to the owner/user.\n\n---\n\n## O\n\n### Off-ramp\n\nways to convert cryptocurrencies into fiat money.\n\n### On-ramp\n\nways to convert (buy) cryptocurrency by spending fiat money.\n\n### Onion routing\n\na technology similar to Tor that allows anonymous interactions on a network. All messages are encrypted in various layers akin to an onion. TON Proxy applies such a technique.\n\n---\n\n## P\n\n### Paper hands\n\nan investor who's inclined to panic-sell — an inexperienced investor.\n\n### Proof-of-stake\n\na consensus mechanism to process transactions in new blocks on the blockchain.\n\n### Proof-of-work\n\na consensus algorithm where one party proves to another that a specific amount of computational work was spent. By expending a little energy, a party can verify this.\n\n### Proxy\n\na service on a computer network that allows clients to establish indirect network connections with other network services.\n\n### Pump\n\nartificially inflating the price of a cryptocurrency or asset.\n\n### Peer-to-peer (P2P)\n\ntransactions among users without the help of a third party or intermediary.\n\n---\n\n## R\n\n### Roadmap\n\na project's strategic plan that displays when its products, services, updates, etc. will be released.\n\n### Return on investment (ROI)\n\nthe profits made from investments.\n\n---\n\n## S\n\n### Soulbound token (SBT)\n\nan NFT that can never be transferred because it contains information about its owner and their accomplishments.\n\n### Scalability\n\nthe ability of a blockchain network to process complex transactions as well as a large number of them.\n\n### Securities and Exchange Commission (SEC)\n\na financial regulator in the United States. [Website](https://www.sec.gov/).\n\n### Shard\n\na mechanism that helps a blockchain network to scale by breaking into smaller blockchains to relieve network congestion — something which TON blockchain does.\n\n### Smart contract\n\nself-executing code that oversees and enables operations with the help of mathematical algorithms and without human intervention.\n\n### Spot trading\n\ntrading a financial asset for money.\n\n### Stablecoin\n\na cryptocurrency that aims to maintain a stable value (often pegged to a fiat currency).\n\n### Staking\n\na way for users to earn a passive income by storing coins or tokens in a proof-of-stake algorithm, which, in turn, ensures the blockchain runs smoothly. For this, they earn rewards as an incentive.\n\n### Swap\n\nthe exchange of two financial assets — e.g., Toncoin for USDT.\n\n---\n\n## T\n\n### TON Enhancement Proposals (TEPs)\n\na [standard set](https://github.com/ton-blockchain/TEPs) of ways to interact with various parts of the TON ecosystem.\n\n### TON Pay\n\na payment integration for TON that provides APIs, UI components, and webhooks for creating and tracking transfers.\n\n### Testnet\n\na network for testing projects or services before launching on the mainnet.\n\n### Ticker\n\nthe short form of a cryptocurrency, asset, or token on exchanges, trading services, or other DeFi solutions — e.g. TON for Toncoin.\n\n### The Merge\n\nthe transition process of Ethereum switching from proof-of-work to proof-of-stake.\n\n### Token\n\na form of digital asset; it can have multiple functions.\n\n### Tokenomics\n\nthe economic plan and distribution strategy of a cryptocurrency (or token).\n\n### To the moon\n\na colloquial phrase used when people create FOMO. It refers to hopefuls wanting the value of a cryptocurrency rapidly gaining a lot of value — hence its trajectory to the moon.\n\n### Toncoin\n\nthe native cryptocurrency of the TON ecosystem, which is used to develop services and pay for fees and services. It can be bought, sold, and traded.\n\n### Trading\n\nbuying and selling cryptocurrencies with the goal of making a profit.\n\n### Total Value Locked (TVL)\n\nthe total value of assets currently locked (e.g. staked) in a specific protocol.\n\n### TON Virtual Machine (TVM)\n\na machine that behaves like a decentralized computer; it computes the state of the TON blockchain after each new block and executes smart contracts.\n\n---\n\n## V\n\n### Validator\n\nthose who verify new blocks on TON blockchain.\n\n---\n\n## W\n\n### “We're all gonna make it” (WAGMI)\n\na sentence often used in the crypto community to express the aspirations of becoming rich one day by investing in cryptocurrencies.\n\n### Wallet\n\nan application that manages private keys and assets for sending, receiving, and storing cryptocurrencies. A Telegram bot (e.g., @wallet) also provides wallet functions within the TON ecosystem.\n\n### Web3\n\na new generation of the internet based on blockchain technology that includes decentralization and tokenomics.\n\n### Whale\n\nan investor who owns a large number of cryptocurrencies and tokens.\n\n### White paper\n\nthe main document of a project written by its developers. It explains the technology and the project's goals.\n\n### Watchlist\n\na customizable list of cryptocurrencies whose price action an investor wishes to follow.\n\n### Workchain\n\nsecondary chains that connect to the masterchain. They can contain a massive number of different connected chains that have their own consensus rules. They can also contain address and transaction information and virtual machines for smart contracts. Additionally, they can be compatible with the masterchain and interact with one another.\n\n---\n\n## Y\n\n### Yield farming\n\nlending or placing cryptocurrencies or tokens in a smart contract to earn rewards in the form of transaction fees.\n"
  },
  {
    "path": "foundations/limits.mdx",
    "content": "---\ntitle: \"Blockchain limits\"\nsidebarTitle: \"Limits\"\n---\n\nimport { Aside } from '/snippets/aside.jsx'\n\nThis document contains the current limits and configuration parameters used in the TON blockchain.\n\nThere are two sources of network parameter definitions: <br />\n\n1. Blockchain config\n1. Node source code\n\n<Aside>\n  You can check all the blockchain parameters live in the explorers: [Tonviewer](https://tonviewer.com/config) or [Tonscan](https://tonscan.org/config).\n\n  Parameters defined in the code can be found in the [source code repository](https://github.com/ton-blockchain/ton).\n</Aside>\n\n## Message and transaction limits\n\n| Name                       | Description                                                | Value    | Units  | Type   | Defined in                                                                                                                             |\n| -------------------------- | ---------------------------------------------------------- | -------- | ------ | ------ | -------------------------------------------------------------------------------------------------------------------------------------- |\n| `max_size`                 | Maximum external message size in bytes                     | 65535    | bytes  | uint32 | [`mc-config.h`:392](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/mc-config.h#L392) |\n| `max_depth`                | Maximum external message depth                             | 512      | levels | uint16 | [`mc-config.h`:393](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/mc-config.h#L393) |\n| `max_msg_bits`             | Maximum message size in bits                               | 2097152  | bits   | uint32 | [`mc-config.h`:395](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/mc-config.h#L395) |\n| `max_msg_cells`            | Maximum number of cells a message can occupy               | 8192     | cells  | uint32 | [`mc-config.h`:396](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/mc-config.h#L396) |\n| `max_vm_data_depth`        | Maximum cell depth in messages and `c4` and `c5` registers | 512      | levels | uint16 | [`mc-config.h`:398](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/mc-config.h#L398) |\n| `max_actions`              | Maximum number of actions                                  | 256      | count  | uint32 | [`transaction.h`](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/transaction.h)      |\n| `max_library_cells`        | Maximum number of library cells                            | 1000     | cells  | uint32 | [`mc-config.h`:397](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/mc-config.h#L397) |\n| `max_acc_state_cells`      | Maximum number of cells that an account state can occupy   | 65536    | cells  | uint32 | [`mc-config.h`:400](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/mc-config.h#L400) |\n| `max_acc_state_bits`       | Maximum account state size in bits                         | 67043328 | bits   | uint32 | [`mc-config.h`:401](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/mc-config.h#L401) |\n| `max_acc_public_libraries` | Maximum number of public libraries per account             | 256      | count  | uint32 | [`mc-config.h`:402](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/mc-config.h#L402) |\n\n## Gas and fee parameters\n\n| Name                | Description                                                             | Value    | Units         | Type        | Defined in                                                                                                          |\n| ------------------- | ----------------------------------------------------------------------- | -------- | ------------- | ----------- | ------------------------------------------------------------------------------------------------------------------- |\n| `free_stack_depth`  | Stack depth without gas consumption                                     | 32       | stack entries | enum\\_value | [vm.h:120](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/vm/vm.h#L120) |\n| `runvm_gas_price`   | VM start gas consumption                                                | 40       | gas units     | enum\\_value | [vm.h:122](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/vm/vm.h#L122) |\n| `flat_gas_limit`    | Gas below `flat_gas_limit` is provided at the price of `flat_gas_price` | 100      | gas units     | uint64      | [config21](/foundations/config#param-20-and-21)                                                                     |\n| `flat_gas_price`    | Costs of launching the TON Virtual Machine                              | 40000    | nanotons      | uint64      | [config21](/foundations/config#param-20-and-21)                                                                     |\n| `gas_price`         | Price of gas in the network in nanotons per 65536 gas units             | 26214400 | nanotons      | uint64      | [config21](/foundations/config#param-20-and-21)                                                                     |\n| `special_gas_limit` | Limit on gas for special (system) contract transactions                 | 1000000  | gas units     | uint64      | [config21](/foundations/config#param-20-and-21)                                                                     |\n| `gas_limit`         | Maximum amount of gas per transaction                                   | 1000000  | gas units     | uint64      | [config21](/foundations/config#param-20-and-21)                                                                     |\n| `gas_credit`        | Gas credit for checking external messages                               | 10000    | gas units     | uint64      | [config21](/foundations/config#param-20-and-21)                                                                     |\n| `block_gas_limit`   | Maximum gas per block                                                   | 10000000 | gas units     | uint64      | [config21](/foundations/config#param-20-and-21)                                                                     |\n\n## Storage fees and limits\n\n| Name               | Description                                   | Value      | Units         | Type   | Defined in                                      |\n| ------------------ | --------------------------------------------- | ---------- | ------------- | ------ | ----------------------------------------------- |\n| `freeze_due_limit` | Storage fees (nanotons) for contract freezing | 100000000  | nanotons      | uint64 | [config21](/foundations/config#param-20-and-21) |\n| `delete_due_limit` | Storage fees (nanotons) for contract deletion | 1000000000 | nanotons      | uint64 | [config21](/foundations/config#param-20-and-21) |\n| `bit_price_ps`     | Storage price for one bit for 65536 seconds   | 1          | nanotons/bit  | uint64 | [config18](/foundations/config#param-18)        |\n| `cell_price_ps`    | Storage price for one cell for 65536 seconds  | 500        | nanotons/cell | uint64 | [config18](/foundations/config#param-18)        |\n\n## Block size limits\n\n| Name                  | Description                                  | Value    | Units     | Type   | Defined in                                      |\n| --------------------- | -------------------------------------------- | -------- | --------- | ------ | ----------------------------------------------- |\n| `bytes_underload`     | Block size limit for underload state         | 131072   | bytes     | uint32 | [config23](/foundations/config#param-22-and-23) |\n| `bytes_soft_limit`    | Block size soft limit                        | 524288   | bytes     | uint32 | [config23](/foundations/config#param-22-and-23) |\n| `bytes_hard_limit`    | Absolute maximum block size in bytes         | 1048576  | bytes     | uint32 | [config23](/foundations/config#param-22-and-23) |\n| `gas_underload`       | Block gas limit for underload state          | 2000000  | gas units | uint32 | [config23](/foundations/config#param-22-and-23) |\n| `gas_soft_limit`      | Block gas soft limit                         | 10000000 | gas units | uint32 | [config23](/foundations/config#param-22-and-23) |\n| `gas_hard_limit`      | Absolute maximum block gas                   | 20000000 | gas units | uint32 | [config23](/foundations/config#param-22-and-23) |\n| `lt_delta_underload`  | Logical time delta limit for underload state | 1000     | lt units  | uint32 | [config23](/foundations/config#param-22-and-23) |\n| `lt_delta_soft_limit` | Logical time delta soft limit                | 5000     | lt units  | uint32 | [config23](/foundations/config#param-22-and-23) |\n| `lt_delta_hard_limit` | Absolute maximum logical time delta          | 10000    | lt units  | uint32 | [config23](/foundations/config#param-22-and-23) |\n\n## Message forwarding costs\n\n| Name         | Description                                          | Value      | Units         | Type   | Defined in                                      |\n| ------------ | ---------------------------------------------------- | ---------- | ------------- | ------ | ----------------------------------------------- |\n| `lump_price` | Base price for message forwarding                    | 400000     | nanotons      | uint64 | [config25](/foundations/config#param-24-and-25) |\n| `bit_price`  | Cost per 65536 bits of message forwarding            | 26214400   | nanotons/bit  | uint64 | [config25](/foundations/config#param-24-and-25) |\n| `cell_price` | Cost per 65536 cells for message forwarding          | 2621440000 | nanotons/cell | uint64 | [config25](/foundations/config#param-24-and-25) |\n| `ihr_factor` | Factor for immediate hypercube routing cost          | 98304      | factor        | uint32 | [config25](/foundations/config#param-24-and-25) |\n| `first_frac` | Fraction for first transition in message route       | 21845      | fraction      | uint32 | [config25](/foundations/config#param-24-and-25) |\n| `next_frac`  | Fraction for subsequent transitions in message route | 21845      | fraction      | uint32 | [config25](/foundations/config#param-24-and-25) |\n\n## Masterchain specific parameters\n\n| Name                     | Description                                     | Value       | Units         | Type   | Defined in                                      |\n| ------------------------ | ----------------------------------------------- | ----------- | ------------- | ------ | ----------------------------------------------- |\n| `mc_bit_price_ps`        | Storage price for one bit for 65536 seconds     | 1000        | nanotons/bit  | uint64 | [config18](/foundations/config#param-18)        |\n| `mc_cell_price_ps`       | Storage price for one cell for 65536 seconds    | 500000      | nanotons/cell | uint64 | [config18](/foundations/config#param-18)        |\n| `mc_flat_gas_limit`      | Gas below `flat_gas_limit` on masterchain       | 100         | gas units     | uint64 | [config20](/foundations/config#param-20-and-21) |\n| `mc_flat_gas_price`      | VM launch cost on masterchain                   | 1000000     | nanotons      | uint64 | [config20](/foundations/config#param-20-and-21) |\n| `mc_gas_price`           | Gas price on masterchain                        | 655360000   | nanotons      | uint64 | [config20](/foundations/config#param-20-and-21) |\n| `mc_special_gas_limit`   | Special contract gas limit on masterchain       | 70000000    | gas units     | uint64 | [config20](/foundations/config#param-20-and-21) |\n| `mc_gas_limit`           | Maximum gas per transaction on masterchain      | 1000000     | gas units     | uint64 | [config20](/foundations/config#param-20-and-21) |\n| `mc_gas_credit`          | Gas credit for checking external messages       | 10000       | gas units     | uint64 | [config20](/foundations/config#param-20-and-21) |\n| `mc_block_gas_limit`     | Maximum gas per masterchain block               | 2500000     | gas units     | uint64 | [config20](/foundations/config#param-20-and-21) |\n| `mc_freeze_due_limit`    | Storage fees for contract freezing              | 100000000   | nanotons      | uint64 | [config20](/foundations/config#param-20-and-21) |\n| `mc_delete_due_limit`    | Storage fees for contract deletion              | 1000000000  | nanotons      | uint64 | [config20](/foundations/config#param-20-and-21) |\n| `mc_bytes_underload`     | Block size limit for underload state            | 131072      | bytes         | uint32 | [config22](/foundations/config#param-22-and-23) |\n| `mc_bytes_soft_limit`    | Block size soft limit                           | 524288      | bytes         | uint32 | [config22](/foundations/config#param-22-and-23) |\n| `mc_bytes_hard_limit`    | Absolute maximum block size in bytes            | 1048576     | bytes         | uint32 | [config22](/foundations/config#param-22-and-23) |\n| `mc_gas_underload`       | Block gas limit for underload state             | 200000      | gas units     | uint32 | [config22](/foundations/config#param-22-and-23) |\n| `mc_gas_soft_limit`      | Block gas soft limit                            | 1000000     | gas units     | uint32 | [config22](/foundations/config#param-22-and-23) |\n| `mc_gas_hard_limit`      | Absolute maximum block gas                      | 2500000     | gas units     | uint32 | [config22](/foundations/config#param-22-and-23) |\n| `mc_lump_price`          | Base price for message forwarding               | 10000000    | nanotons      | uint64 | [config24](/foundations/config#param-24-and-25) |\n| `mc_bit_price`           | Cost per 65536 bits of message forwarding       | 655360000   | nanotons/bit  | uint64 | [config24](/foundations/config#param-24-and-25) |\n| `mc_cell_price`          | Cost per 65536 cells for message forwarding     | 65536000000 | nanotons/cell | uint64 | [config24](/foundations/config#param-24-and-25) |\n| `mc_ihr_factor`          | Factor for immediate hypercube routing cost     | 98304       | factor        | uint32 | [config24](/foundations/config#param-24-and-25) |\n| `mc_first_frac`          | Fraction for first transition in message route  | 21845       | fraction      | uint32 | [config24](/foundations/config#param-24-and-25) |\n| `mc_next_frac`           | Fraction for subsequent transitions in route    | 21845       | fraction      | uint32 | [config24](/foundations/config#param-24-and-25) |\n| `mc_lt_delta_underload`  | Logical time delta limit for underload state    | 1000        | lt units      | uint32 | [config22](/foundations/config#param-22-and-23) |\n| `mc_lt_delta_soft_limit` | Logical time delta soft limit                   | 5000        | lt units      | uint32 | [config22](/foundations/config#param-22-and-23) |\n| `mc_lt_delta_hard_limit` | Absolute maximum logical time delta             | 10000       | lt units      | uint32 | [config22](/foundations/config#param-22-and-23) |\n| `mc_catchain_lifetime`   | masterchain catchain groups lifetime in seconds | 250         | seconds       | uint32 | [config28](/foundations/config#param-28)        |\n\n## Validator parameters\n\n| Name                        | Description                                         | Value      | Units    | Type   | Defined in                               |\n| --------------------------- | --------------------------------------------------- | ---------- | -------- | ------ | ---------------------------------------- |\n| `shard_catchain_lifetime`   | shardchain catchain groups lifetime in seconds      | 250        | seconds  | uint32 | [config28](/foundations/config#param-28) |\n| `shard_validators_lifetime` | shardchain validators group lifetime in seconds     | 1000       | seconds  | uint32 | [config28](/foundations/config#param-28) |\n| `shard_validators_num`      | Number of validators in shardchain validation group | 23         | count    | uint32 | [config28](/foundations/config#param-28) |\n| `masterchain_block_fee`     | Reward for block creation                           | 1700000000 | nanotons | Grams  | [config14](/foundations/config#param-14) |\n| `basechain_block_fee`       | Basechain block fee                                 | 1000000000 | nanotons | Grams  | [config14](/foundations/config#param-14) |\n\n## Time parameters\n\n| Name          | Description                                  | Value | Units   | Type     | Defined in                               |\n| ------------- | -------------------------------------------- | ----- | ------- | -------- | ---------------------------------------- |\n| `utime_since` | Initial Unix timestamp for price application | 0     | seconds | UnixTime | [config18](/foundations/config#param-18) |\n"
  },
  {
    "path": "foundations/messages/deploy.mdx",
    "content": "---\ntitle: \"Deploy message\"\n---\n\n`StateInit` is a data structure sent as part of a message, either internal or incoming external, used to\n\n- deploy a smart contract, for which it stores the initial code and data of a contract;\n- [unfreeze](/foundations/status#status-transitions) a contract, where its last committed code and data are used.\n\nThis structure can be appended in-place or as a referenced cell to every message:\n\n```tlb\nmessage$_\n    {X:Type}\n    info:CommonMsgInfo\n    init:(Maybe (Either StateInit ^StateInit))\n    body:(Either X ^X)\n= Message X;\n```\n\nThe `StateInit` structure is defined as follows:\n\n```tlb\n_\n    fixed_prefix_length:(Maybe (## 5))\n    special:(Maybe TickTock)\n    code:(Maybe ^Cell)\n    data:(Maybe ^Cell)\n    library:(Maybe ^Cell)\n= StateInit;\n```\n\nwhere the fields are:\n\n- `special`: was meant to register a smart contract for tick-tock events; now is deprecated.\n- `code`: the initial code of the contract.\n- `data`: the initial data of the contract.\n- `library`: the initial library of the contract.\n- `fixed_prefix_length`: number of most significant address bits that may differ between the deploy message destination and the address derived from `StateInit`; the remaining bits must match.\n\n## Deploying to specific shard\n\nDue to [the way](/foundations/shards) messages are sent between blockchain shards, the number of hops and, hence, latency depends on the distance between the shards of a source and a destination. The optimal performance is achieved when both addresses are in the same shard.\n\nUsually, a new contract has to be deployed by a message to the exactly same address as computed out of `StateInit`'s hash, i.e. the content of `StateInit` uniquely determines the address. Any discrepancy between the address [computed](/foundations/addresses/derive) from `StateInit` and destination address of a deploy message [will result](/foundations/phases#when-the-compute-phase-is-skipped) in a failed transaction.\n\nTo deploy a contract to the desired shard, there is a `fixed_prefix_length` field in `StateInit`. It allows to specify the destination address that would slightly differ from the computed address. Only all the bits except for the first `fixed_prefix_length` have to match.\n\nTo put it more formally,\n\n```\ndrop(fixed_prefix_length, addressFrom(stateInit)) = drop(fixed_prefix_length, destination)\n```\n\nwhere\n\n- `drop(n, x)` drops the `n` most significant bits from a 256-bit number `x`,\n- `addressFrom(s)` computes contract's address from a hash of `StateInit s`.\n\nWhen `fixed_prefix_length` is zero or not set, the condition simplifies to\n\n```\naddressFrom(stateInit) = destination\n```\n\n### Example\n\nAssume an address `D` starts with `0x5ABC...`. If there are 256 active shardchains, the first 8 bits of the address (i.e., `5A`) correspond to shard IDs.\n\nNow, if some other contract `S` is deployed that intends to exchange messages with `D`, and computing an address from its `StateInit` results in `0x2623...`, it will be deployed by default into a shard `26`. Messages from `26` to `5A` will take 2 hops and 2 blocks to arrive at the destination.\n\nTo put `S` into the same shard as `D`, set `fixed_prefix_length` to 8 and send the deploy message to the address `0x5A23...`. Then TVM will ignore the discrepancy in the first 8 bits between the computed address (`0x2623...`) and the passed destination (`0x5A23...`), because their remaining 248 bits coincide, and `S` will be deployed into shard `5A`.\n\n### Limits\n\nThe largest value for `fixed_prefix_length` is set in the blockchain config ([param 43](/foundations/config#param-43%3A-account-and-message-limits)), and at the moment is `8`, i.e. discrepancy in only eight bits of address can be ignored.\n"
  },
  {
    "path": "foundations/messages/external-in.mdx",
    "content": "---\ntitle: \"Incoming external messages\"\n---\n\nExternal messages are sent from outside the blockchain, and as such only have an optional [external sender address](/foundations/addresses/overview#external-addresses). In cases where it is necessary to verify the sender, the public key is usually stored in the contract, and the message is [signed](/contract-dev/signing) before sending, so the contract can verify this signature with the public key. This approach is used by [wallet contracts](/standard/wallets/comparison).\n\n## Contents of external messages\n\n```tlb\next_in_msg_info$10\n    src:MsgAddressExt\n    dest:MsgAddressInt\n    import_fee:Grams\n= CommonMsgInfo;\n\nmessage$_\n    {X:Type}\n    info:CommonMsgInfo\n    init:(Maybe (Either StateInit ^StateInit))\n    body:(Either X ^X)\n= Message X;\n```\n\nwhere\n\n- `src` — the external address of the sender of the message.\n- `dest` — the [internal address](/foundations/addresses/overview#internal-addresses) of the contract that will receive the message.\n- `import_fee` — the amount of Toncoin that the contract will pay for this message.\n\nThe value of these fields can be manipulated by [nodes](/ecosystem/nodes/overview) or [API providers](/ecosystem/api/overview) that deliver the message unless they are included in the signed payload. However, wallet contracts usually do not include these fields in the signed payload, and only the contents of the `body` field are signed.\n\nThe `import_fee` field will be overwritten by validators processing the messages with a predetermined price, based on a number of cells and bits in the message.\n\n## Deploying via external message\n\nA contract can be deployed via an external message only if the newly deployed contract will accept that message after its creation. As usual, the address of the contract [must match](/foundations/messages/deploy) the hash of the `StateInit`.\n\n## Accepting message\n\nIncoming external messages are sent to the contract from outside the blockchain, so the sender can't pay for them, and these messages must be paid by the contract that receives them. However, if the contract paid for all incoming external messages it received, it [would drain](/contract-dev/security#unconditional-accepting-of-external-messages) its balance. This is why the [`gas_credit`](/tvm/gas) parameter exists. It defines how much gas the contract can consume without paying for it, giving the contract a chance to decide whether it wants to accept the message and pay for it. A contract can't modify its state without accepting the message. If a contract accepts a message, it will pay for all gas consumed, even the gas that was previously deducted from `gas_credit`. Accepting a message can be done using the [`ACCEPT`](/tvm/instructions#f800-accept) TVM instruction, or via the [`SETGASLIMIT`](/tvm/instructions#f801-setgaslimit) instruction with an argument greater than or equal to 2<sup>63</sup>-1.\n\n## Multiple delivery\n\nWhen an incoming external message is sent to the blockchain, validators share them with each other, and might accidentally (or intentionally) deliver it several times. As it's usually preferred to process a unique incoming external message only once, some measures need to be taken to ensure duplicate messages are not accepted. Some of these techniques can be found in [wallet](/standard/wallets/comparison) contracts.\n"
  },
  {
    "path": "foundations/messages/external-out.mdx",
    "content": "---\ntitle: \"Outbound external messages\"\n---\n\nOutbound external messages are the messages that a contract can send to the outer world. They are primarily used for logging purposes. They can't change any contract state or trigger a transaction. These messages are visible to anyone, and there is no guarantee that anyone outside the blockchain will process them.\n\nThe structure is as follows:\n\n```tlb\next_out_msg_info$11\n    src:MsgAddressInt\n    dest:MsgAddressExt\n    created_lt:uint64\n    created_at:uint32\n= CommonMsgInfo;\n\nmessage$_\n    {X:Type}\n    info:CommonMsgInfo\n    init:(Maybe (Either StateInit ^StateInit))\n    body:(Either X ^X)\n= Message X;\n```\n\nUnlike [incoming](/foundations/messages/external-in) external messages, a third party can't manipulate the contents of outgoing external messages, so there is no need to sign them.\n\n- `src` — an [internal address](/foundations/addresses/overview#internal-addresses) of the contract that sends the message. It has to be a valid address, but is not important, as it will be overwritten by the address of sender after the message is sent.\n- `dest` — any valid [external address](/foundations/addresses/overview#external-addresses).\n- `created_at` — arbitrary value, overwritten with the `created_at` field of the transaction in which the contract sent this message.\n- `created_lt` — arbitrary value, overwritten with the `created_lt` field of the transaction, incremented by one.\n\nWhen sending this kind of message, the contract may fill all of these fields with any values. `src`, `created_lt`, and `created_at` will be overwritten by the validator processing this message.\n\nFor an outbound external message, `init` field also can store arbitrary data, as outbound external messages can't initialize any contract.\n\n## Message modes\n\nAs outbound external messages do not carry any Toncoin value, the price of their handling is paid similarly to [`SendPayFwdFeesSeparately`](/foundations/messages/modes) mode. However, using any mode other than [`SendIgnoreErrors`](/foundations/messages/modes), [`SendBounceIfActionFail`](/foundations/messages/modes), or [`SendPayFwdFeesSeparately`](/foundations/messages/modes) for outbound external messages results in [exit code `34`](/tvm/exit-codes#34:-invalid-or-unsupported-action). In this case, regardless of whether the [`SendIgnoreErrors`](/foundations/messages/modes) mode was used, the action phase will fail. Mode [`SendPayFwdFeesSeparately`](/foundations/messages/modes) does not change the message behavior.\n\n## Example in Tolk\n\nIn Tolk, outbound external messages may be composed using the `createExternalLogMessage` function.\n\n```tolk title=\"Tolk\"\ntolk 1.2\n\nstruct(0x10) ValueWasDeposited {\n    value: int64\n}\n\nfun main(in: InMessage) {\n    val msg = createExternalLogMessage({\n        dest: createAddressNone(),\n        body: ValueWasDeposited {\n            value: 1000,\n        },\n    });\n    msg.send(SEND_MODE_PAY_FEES_SEPARATELY);\n}\n```\n"
  },
  {
    "path": "foundations/messages/internal.mdx",
    "content": "---\ntitle: \"Internal messages\"\n---\n\nInternal messages are the messages sent from a contract to an arbitrary account. They are the most common type of a message.\n\n## After processing\n\nThe contents of an internal message after it was processed are as follows:\n\n```tlb\nint_msg_info$0\n    ihr_disabled:Bool\n    bounce:Bool\n    bounced:Bool\n    src:MsgAddressInt\n    dest:MsgAddressInt\n    value:CurrencyCollection\n    extra_flags:(VarUInteger 16)\n    fwd_fee:Grams\n    created_lt:uint64\n    created_at:uint32\n= CommonMsgInfo;\n\nmessage$_\n    {X:Type}\n    info:CommonMsgInfo\n    init:(Maybe (Either StateInit ^StateInit))\n    body:(Either X ^X)\n= Message X;\n```\n\n- `ihr_disabled` — unused, always set to `true`.\n- `bounce` — whether the message is [bounceable](#bounces).\n- `bounced` — whether the message has been [bounced](#bounces).\n- `src` — address of the contract that sent the message.\n- `dest` — address of the account that received the message.\n- `value` — amount of Toncoin and extra-currency attached to the message.\n- `extra_flags` — used with the [new bounce format](#new-bounce-format).\n- `fwd_fee` — fee charged for forwarding the message.\n- `created_lt` — logical time when the message was created.\n- `created_at` — unix time when the message was created.\n\n## Before processing\n\nWhen a contract sends a message, the requirements for the structure above are relaxed.\n\n```tlb\nint_msg_info$0\n    ihr_disabled:Bool\n    bounce:Bool\n    bounced:Bool\n    // NB! different type\n    src:MsgAddress\n    dest:MsgAddressInt\n    value:CurrencyCollection\n    extra_flags:(VarUInteger 16)\n    fwd_fee:Grams\n    created_lt:uint64\n    created_at:uint32\n= CommonMsgInfoRelaxed;\n\nmessage$_\n    {X:Type}\n    info:CommonMsgInfoRelaxed\n    // NB! actually StateInitWithLibs\n    init:(Maybe (Either StateInit ^StateInit))\n    body:(Either X ^X)\n= MessageRelaxed X;\n_\n    fixed_prefix_length:(Maybe (## 5))\n    special:(Maybe TickTock)\n    code:(Maybe ^Cell)\n    data:(Maybe ^Cell)\n    library:(HashmapE 256 SimpleLib)\n= StateInitWithLibs;\n```\n\nThe process of transforming the relaxed version of the structure into the strict version occurs in the action phase and is performed by the handler of [send message actions](/foundations/actions/send). This action rewrites [some fields](/foundations/actions/send#message-normalization) of the structure with correct values and validates the `StateInit` field against the `StateInitWithLibs` type.\n\n## Deploy\n\nIt is possible to simultaneously send both the payload in the `body` field and the `StateInit` in the `init` field to [initialized the contract](/foundations/messages/deploy) and process the payload in the same transaction.\n\n## Message value\n\nThe message may set `value` field that tells to transfer Toncoin and extra-currency to the recipient of the message. The actually transferred amount depends on the value of this field and a [send mode](/foundations/messages/modes).\n\n## Bounces\n\nA bounce message is used to inform the sender that handling of their message failed. It is sent automatically to a sender when\n\n- there is enough Toncoin to send it left from handling the failed message,\n- and the message is bounceable,\n- and when either\n  - a message throws an error from the [compute phase](/foundations/phases#compute-phase) during message processing and state was not committed by [`COMMIT`](/tvm/instructions#f80f-commit) TVM instruction,\n  - or a message throws an error in the [action phase](/foundations/phases#action-phase) and mode [`SendBounceIfActionFail`](/foundations/messages/modes) is used.\n\n### Default bounce\n\nIf the `bounce` flag is set to `true`, the message is bounceable. If the bounce conditions are met, the bounce message is produced from the failed message with the following transformation:\n\n- `src` and `dest` fields are swapped.\n- The `bounced` flag is set to `true` to tell it's the bounce message.\n- The `bounce` flag is set to `false` to prevent infinite loop of bouncing messages until no Toncoin is left to spend.\n- `body` is replaced with the concatenation of 32 bits equal to one (`0xffffffff`) and the first 256 bits of the old `body`. The new `body` is stored in the message in-place, with [`left`](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb#L10) of the `Either`.\n\nThis message is then sent to the `src` address of the original message.\n\n### New bounce format\n\nThe default bounce format has a flaw, that its `body` is too small to store even an internal address, and thus has limited usability for real-world applications. A new bounce format was introduced to address this issue.\n\nUsing the `extra_flags` field, it is possible to change how the new `body` will be constructed. All other transformations remain the same.\n\n- If `(extra_flags & 1) = 1` the new bounce format is enabled. The bounced message now contains the root cell of the `body` of the failed message, with all the refs removed from it.\n  - If `(extra_flags & 2) = 2` is _also_ set, the bounced message contains the entire `body` of the original message, without removing any refs.\n\nAll other bits in `extra_flags` are reserved for future use.\n\nWhen a message in new bounce format is bounced, the bounce message body has the following format (`new_bounce_body`):\n\n```tlb\n_\n    value:CurrencyCollection\n    created_lt:uint64\n    created_at:uint32\n= NewBounceOriginalInfo;\n\n_\n    gas_used:uint32\n    vm_steps:uint32\n= NewBounceComputePhaseInfo;\n\n// NB! 0xfffffffe is different from the old 0xffffffff\nnew_bounce_body#fffffffe\n    original_body:^Cell\n    original_info:^NewBounceOriginalInfo\n    bounced_by_phase:uint8\n    exit_code:int32\n    compute_phase:(Maybe NewBounceComputePhaseInfo)\n= NewBounceBody;\n```\n\n- `original_body` — the cell that contains the body of the original message. If `extra_flags & 2` then the whole body is returned; otherwise only the root without refs is included.\n- `original_info` — the value, lt, and Unix time of the original message.\n- `bounced_by_phase`:\n  - `0` - compute phase was skipped. `exit_code` denotes the skip reason:\n    - `exit_code = -1` — no state (an account is uninit or frozen, and no `StateInit` is present in the message).\n    - `exit_code = -2` — bad state (an account is uninit or frozen, and `StateInit` in the message has the wrong hash).\n    - `exit_code = -3` — no gas.\n    - `exit_code = -4` — account is suspended.\n  - `1` — compute phase failed. `exit_code` is the value from the compute phase.\n  - `2` — action phase failed. `exit_code` is the value from the action phase.\n- `exit_code` — 32-bit exit code, see above.\n- `compute_phase` — exists if it was not skipped, i.e., when `bounced_by_phase` is not 0.\n- `gas_used` — same as `gas_used` of `TrComputePhase` of the transaction.\n- `vm_steps` — same as `vm_steps` of `TrComputePhase` of the transaction.\n\nThe bounced message has the same 0th and 1st bits in `extra_flags` as the original message. The rest of the bits are set to zero.\n"
  },
  {
    "path": "foundations/messages/modes.mdx",
    "content": "---\ntitle: \"Sending modes\"\n---\n\nBy default, message sending process has the following properties:\n\n- the forward fees are paid from the indicated message value, so it is decreased by the amount of forward fees before sending;\n- if sending fails, the transaction is rolled back and a bounce message is not sent.\n\nThe purpose of _send modes_ is to modify the above logic by specifying:\n\n- what exactly value should be in the outgoing message (will it be increased by something or even reset to some value);\n- whether to pay forward fees from the account balance or from the message value;\n- whether to rollback the transaction and send a bounce message if sending fails, etc.\n\nThe send modes are specified via an 8-bit bitmask `mode` parameter of the [`SENDRAWMSG`](/tvm/instructions#fb00-sendrawmsg) instruction. The resulting mode value can have the following base modes:\n\n| Mode value | Convenient name        | Description                                |\n| ---------: | :--------------------- | ------------------------------------------ |\n|        `0` | `SendDefaultMode`      | Default mode.                              |\n|       `64` | `SendRemainingValue`   | Complex logic. Will be described below.    |\n|      `128` | `SendRemainingBalance` | Send all remaining balance of the account. |\n\nAdditionally, the resulting `mode` can have the following optional flags added:\n\n| Flag value | Convenient name            | Description                                                                                                                                              |\n| ---------: | :------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |\n|       `+1` | `SendPayFwdFeesSeparately` | Pay forward fees separately from the message value.                                                                                                      |\n|       `+2` | `SendIgnoreErrors`         | Ignore errors during sending. No bounce message will be sent on failure.                                                                                 |\n|      `+16` | `SendBounceIfActionFail`   | Bounce the transaction in case of any errors during the action phase.                                                                                    |\n|      `+32` | `SendDestroyIfZero`        | The current account (contract) will be destroyed if its resulting balance is zero. This flag has effect only if mode 128, SendRemainingBalance, is used. |\n\n## Behavior\n\nNotation:\n\n- `value` – the amount of Toncoin indicated in the outgoing message.\n- `mode` – the bitmask passed to the `SENDRAWMSG` instruction.\n- `msg_balance_remaining` – the remaining value of the incoming message. At the start of the action phase it equals either the incoming message value or account's balance before compute phase if it was less than the value of incoming message with bounce flag set to `false`. At the start of sending message process, it is zero if there was the previous sending message action with modes `SendRemainingBalance` or `SendRemainingValue`, otherwise it equals the value described above.\n- `remaining_balance` – the remaining balance of the account at the start of the action.\n- `fwd_fees` – the amount of forward fees for sending the message.\n- `gas_fees` – the fees paid for gas used during the computation phase.\n- `action_fine` – the accumulated fine for the previous failed and skipped send message actions.\n- `final_value` – the final value of the outgoing message.\n- `req` – value that will be deducted from the account balance.\n\nThe algorithm for the resulting value of outgoing internal message and amount of nanotoncoins that will be deducted from account's balance is as follows:\n\n1. Check that `mode` has flag `SendBounceIfActionFail`:\n   - if so, then in case of any failure the action phase will be interrupted, the bounce phase will be initiated;\n   - if not, then in case of any failure the action phase will be interrupted but no bounce message will be sent.\n1. Check that `mode` has flag `SendIgnoreErrors`:\n   - if so, then in case of almost all failure (errors on which this mode is not work are described in [Errors subsection](/foundations/messages/modes##erros).) during sending the message an error will be ignored and the action phase will continue;\n1. Set `final_value` to the `value`.\n1. Check that `mode` has base mode `SendRemainingBalance`:\n   - if so, then set `final_value` to `remaining_balance` and remove `+1` flag from `mode` if it is presented.\n1. Otherwise, check that `mode` has base mode `SendRemainingValue`:\n   1. Check that `mode` has flag `SendPayFwdFeesSeparately`:\n      - if so, then increase `final_value` by `msg_balance_remaining`;\n      - otherwise, increase `final_value` by `msg_balance_remaining - gas_fees - action_fine`.\n1. Set `req` to `final_value`.\n1. Check that `mode` has flag `SendPayFwdFeesSeparately`:\n   - if so, then increase `req` by `fwd_fees`.\n   - otherwise, decrease `final_value` by `fwd_fees`.\n1. Set `msg_balance_remaining` to zero if `mode` has base modes `SendRemainingValue` or `SendRemainingBalance`.\n1. Decrease `remaining_balance` by `req`.\n1. Check that `mode` has flag `SendDestroyIfZero` and base mode `SendRemainingBalance`:\n   - if so, then destroy the current account (contract) if `remaining_balance` is zero.\n\n### Example\n\nAssume that\n\n- `value = 0.1 TON`;\n- `mode = 80 = 10010000` (that is, `SendRemainingValue + SendBounceIfActionFail`);\n- `msg_balance_remaining = 0 TON` (for instance, there was previous sending message action with mode `SendRemainingValue`);\n- `remaining_balance = 2 TON`;\n- `fwd_fees = 0.01 TON`;\n- `gas_fees = 0.005 TON`;\n- `action_fine = 0 TON`.\n\nThen the sending proceeds as follows:\n\n- `mode` has flag `SendBounceIfActionFail`? Yes.\n- `mode` has flag `SendIgnoreErrors`? No.\n- Set `final_value = 0.1 TON`.\n- `mode` has base mode `SendRemainingBalance`? No.\n- `mode` has base mode `SendRemainingValue`? Yes.\n  - `mode` has flag `SendPayFwdFeesSeparately`? No.\n  - Increase `final_value` by `msg_balance_remaining - gas_fees - action_fine = 0 TON - 0.005 TON - 0 TON = -0.005 TON`.\n  - Now, `final_value = 0.1 TON - 0.005 TON = 0.095 TON`.\n- Set `req = final_value = 0.095 TON`.\n- `mode` has flag `SendPayFwdFeesSeparately`? No.\n  - Decrease `final_value` by `fwd_fees = 0.01 TON`.\n  - Now, `final_value = 0.095 TON - 0.01 TON = 0.085 TON`.\n- Set `msg_balance_remaining` to zero (it is already zero).\n- Decrease `remaining_balance` by `req = 0.095 TON`.\n  - Now, `remaining_balance = 2 TON - 0.095 TON = 1.905 TON`.\n\n### Outgoing external messages\n\nThe algorithm above describes the sending process only for outgoing internal messages. However, outgoing external message can have only the following three modes:  `SendBounceIfActionFail`, `SendIgnoreErrors`, and `SendPayFwdFeesSeparately` (use of any other leads to an error). `SendPayFwdFeesSeparately` can be used, but have no effect. `SendBounceIfActionFail` and `SendIgnoreErrors` have the same behavior, i.e. send bounce message in a case of any error and ignore almost all errors during the processing.\n\nThere is no `value` field in external messages, so the forward fees are always deducted from account's balance.\n\n## Errors\n\nThe following errors can occur during the sending message flow:\n\n- Simultaneous use of modes `SendRemainingBalance` and `SendRemainingValue`, `34` exit code.\n- Modes except `SendIgnoreErrors`, `SendBounceIfActionFail`, and `SendPayFwdFeesSeparately` used for outbound external messages, `34` exit code.\n- Source address in the outbound message is not equal to `addr_none` or the contract address, `35` exit code.\n- Some problems with repacking the message body and [`StateInit`](/foundations/messages/deploy) into references if the message body or `StateInit` is too big to be located in place, `34` exit code.\n- Malformed message structure, `34` exit code.\n- Invalid destination address in the outbound message, `36` exit code.\n- Not enough value to transfer with the message: all of the inbound message value has been consumed, `37` exit code.\n- Not enough funds for processing all message references, `40` exit code.\n- The number of bits or references in `StateInit` and message body is too large, `40` exit code.\n- Message has Merkle depth more than two, `40` exit code.\n- If a message has only one `SendRemainingValue` base mode and `final_value` after the step `5` is negative, then an error with `37` exit code is thrown.\n- If `final_value` after step `7` is negative, then an error with `37` exit code is thrown.\n- If `remaining_balance` after step `9` is negative, then an error with `37` exit code is thrown.\n- If `remaining_balance` after pay forward fees step is negative in a case of outgoing external message, then an error with `37` exit code is thrown.\n- Problems related to extra-currency, exit codes `37`, `44`, `38`.\n\nThe `SendIgnoreErrors` mode ignore all the above errors except the four first ones (simultaneous use of modes, invalid modes for external messages, source address problems, and problems with repacking).\n"
  },
  {
    "path": "foundations/messages/ordinary-tx.mdx",
    "content": "---\ntitle: \"Ordinary transactions\"\n---\n\nOrdinary [transactions](/foundations/messages/overview#transactions) are the most common type of transaction because they result from processing [incoming external](/foundations/messages/external-in) and [internal](/foundations/messages/internal) messages. They can be produced only while processing such messages. The phases of a transaction are described in detail on the [dedicated page](/foundations/phases).\n\nThe structure of an ordinary transaction is as follows:\n\n```tlb\ntrans_ord$0000\n    credit_first:Bool\n    storage_ph:(Maybe TrStoragePhase)\n    credit_ph:(Maybe TrCreditPhase)\n    compute_ph:TrComputePhase\n    action:(Maybe ^TrActionPhase)\n    aborted:Bool\n    bounce:(Maybe TrBouncePhase)\n    destroyed:Bool\n= TransactionDescr;\n```\n\nThe fields of an ordinary transaction are:\n\n- `credit_first` indicates whether the transaction started with the credit phase or the storage phase. This flag matches the `bounce` flag of the message that triggered the transaction and is `true` for incoming external messages.\n- `storage_ph` indicates the result of the storage phase: the number of storage fees collected and any resulting contract state change. This field is never equal to `Nothing` in the current implementation.\n- `credit_ph` indicates the result of the credit phase: the number of credits collected and the state update of the contract, if any. This field is `Nothing` when the transaction was triggered by an incoming external message.\n- `compute_ph` holds the result of TVM execution on the contract. If this phase is [skipped](/foundations/phases#when-the-compute-phase-is-skipped), for example, because there are no funds or no state on the destination account, the field stores the skip reason instead.\n- `action` holds the result of the action phase. This field is `Nothing` if the compute phase failed and is populated otherwise.\n- `aborted` indicates whether the action phase was unsuccessful.\n- `bounce` holds the result of the bounce phase and is `Nothing` if the bounce phase was not executed.\n- `destroyed` indicates whether the account was deleted in the action phase by using [`SendDestroyIfZero`](/foundations/messages/modes). If the contract was deleted in the action phase, this flag is `true`.\n"
  },
  {
    "path": "foundations/messages/overview.mdx",
    "content": "---\ntitle: \"Overview\"\n---\n\n## Messages\n\nMessages are objects of the following structure:\n\n```tlb\nmessage$_\n    {X:Type}\n    info:CommonMsgInfo\n    init:(Maybe (Either StateInit ^StateInit))\n    body:(Either X ^X)\n= Message X;\n```\n\n- `init` is an optional field of [`StateInit`](/foundations/messages/deploy) type used to initialize the contract state, stored either in-place or in a ref of the cell with a message.\n- `body` is the actual message content that can be stored either in-place or in a reference. Typically, it is the payload of the message that will be read by the receiver.\n- `info` describes the type of the message, and fields specific to messages of this type:\n  - [Internal messages](/foundations/messages/internal) are messages from one contract to another.\n  - [Incoming external](/foundations/messages/external-in) messages are messages from the outside world to the contract.\n  - [Outbound external](/foundations/messages/external-out) messages are messages from the contract to the outside world. They can be interpreted as logs.\n\n## Transactions\n\nA transaction is a record that stores the state changes of a contract. A contract's state cannot be changed without a transaction. When a contract processes a message, a transaction may occur as the result of its processing.\n\n- When an internal message is processed, a transaction is always created.\n- When an incoming external message is processed, a transaction will be created only if the contract [accepts](/foundations/messages/external-in#accept-message) the message.\n- When an outbound external message is processed, a transaction is never created, because outbound external messages can't change contract state.\n\nHowever, a transaction may be created independently of message processing by\n\n- tick-tock transactions,\n- split-prepare transactions,\n- split-install transactions,\n- storage-tx transactions.\n\nEach transaction has the following structure:\n\n```tlb\n    transaction$0111\n    account_addr:bits256\n    lt:uint64\n    prev_trans_hash:bits256\n    prev_trans_lt:uint64\n    now:uint32\n    outmsg_cnt:uint15\n    orig_status:AccountStatus\n    end_status:AccountStatus\n    ^[\n        in_msg:(Maybe ^(Message Any))\n        out_msgs:(HashmapE 15 ^(Message Any))\n    ]\n    total_fees:CurrencyCollection\n    state_update:^(HASH_UPDATE Account)\n    description:^TransactionDescr\n= Transaction;\n```\n\nTransactions implement the concept of `AccountChain` described in the [TON Blockchain whitepaper](/foundations/whitepapers/tblkch#1-2-1-the-infinite-sharding-paradigm-isp-applied-to-blockchain-block-and-state). Each account state can be interpreted as a separate blockchain, so transactions follow a strict order defined by the `prev_trans_hash` field. Thanks to the TON consensus protocol, a transaction becomes final when the first masterchain block references it by storing the hash of the corresponding `ShardChain` state, which in turn stores the hash of the `AccountChain` state.\n\nBecause transactions form the `AccountChain`, each one carries a logical timestamp, `lt`, that strictly increases with every new transaction of the account. The `now` field stores the Unix time when the transaction was created.\n\nThe `state_update` field is a [Merkle update](/foundations/serialization/merkle-update) that captures the difference between the previous and current state of the account. The [contract status](/foundations/status) before and after the transaction is duplicated for convenience.\n\nOther fields, such as `in_msg`, `out_msgs`, and `outmsg_cnt`, relate to the [messages](/foundations/messages/overview) processed and emitted during the transaction. A trace may start from a transaction rather than a message, in which case `in_msg` is `Nothing`. However, a trace cannot continue without messages: if it contains `n` transactions it must contain at least `n-1` messages. Consequently, a trace can include at most one non-ordinary transaction, because messages can trigger only an [ordinary transaction](/foundations/messages/ordinary-tx).\n\nThe `total_fees` field stores the total number of [fees](/foundations/fees) paid by the transaction. These fees may eventually be paid in extra currencies, but that feature is not implemented yet.\n"
  },
  {
    "path": "foundations/phases.mdx",
    "content": "---\ntitle: \"Execution phases\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nWhen an event occurs on an account in The Open Network (TON) blockchain, it triggers a **transaction**.\nThe most common event is receiving a message, but other events like `tick-tock`, `merge`, and `split` can also initiate transactions.\n\nEach transaction consists of up to five phases:\n\n1. **Storage phase**: calculates storage fees for the contract based on the space it occupies in the blockchain state.\n1. **Credit phase**: updates the contract balance by accounting for incoming message values and storage fees.\n1. **Compute phase**: executes the contract code on the TON Virtual Machine (TVM). The result includes `exit_code`, `actions`, `gas_details`, `new_storage`, and other data.\n1. **Action phase**: processes actions from the compute phase if it succeeds.\\\n   Actions may include sending messages, updating contract code, or modifying libraries. If an action fails (for example, due to a lack of funds), the transaction may revert or skip the action, depending on its mode. For example, `mode = 0, flag = 2` means that any errors arising while processing this message during the action phase are ignored.\n1. **Bounce phase**: If the compute phase ends with an error and the inbound message has the bounce flag set, this phase generates a bounce message. If the send\\_msg action failed and it had the +16 flag set, then the bounce phase will also be triggered.\n\n> Compute, Action and Bounce phases may be skipped\n\n<Aside\n  type=\"note\"\n  title=\"Execution order notes\"\n>\n  For non-bounceable messages:\n  Credit → Storage → Compute → Action → Bounce\n\n  For bounceable messages:\n  Storage → Credit → Compute → Action → Bounce\n</Aside>\n\n## Fee deduction sequence\n\n1. Import fee (before the first phase)\n1. Storage fee (storage phase)\n1. Gas fee (compute phase)\n1. Action fee + forward fee (action phase)\n1. Additional forward fees (bounce phase)\n\n## Storage phase\n\nCannot be skipped.\n\nIn this phase, the blockchain processes fees related to the account's persistent storage. Let's start by looking at the TL-B schema:\n\n```tlb\ntr_phase_storage$_ storage_fees_collected:Grams\n  storage_fees_due:(Maybe Grams)\n  status_change:AccStatusChange\n  = TrStoragePhase;\n```\n\nThe `storage_fees_due` field is of type `Maybe` because it is only present when the account has **insufficient balance** to cover the storage fees. When the account has enough funds, this field is omitted.\n\n> Note: Grams are unsigned integers, so account balances cannot be negative.\n\nThe `AccStatusChange` field indicates whether the account's status changed during this phase. For example, see [account status variety](/foundations/status#status-variety).\n\n## Credit phase\n\nCannot be skipped.\n\nThis phase is relatively small and straightforward.\nThe main logic of this phase is to **credit the contract’s balance** with the remaining value from the incoming message.\n\nThe credit phase is serialized in TL-B as follows:\n\n```tlb\ntr_phase_credit$_ due_fees_collected:(Maybe Grams)\n  credit:CurrencyCollection = TrCreditPhase;\n```\n\nThis phase consists of the following two fields:\n\n| Field                | Type                 | Description                                                                                                          |\n| -------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------- |\n| `due_fees_collected` | `Maybe Grams`        | Amount of previously due storage fees collected (present only if storage fees were due and collected in this phase). |\n| `credit`             | `CurrencyCollection` | The amount credited to the account as a result of receiving the incoming message.                                    |\n\n## Compute phase\n\nThe **compute phase** is one of the most complex stages of a transaction. This is where the smart contract code, stored in the account’s state, is executed.\n\nUnlike previous phases, the TL-B definition for the compute phase includes multiple variants.\n\n```tlb\ntr_phase_compute_skipped$0 reason:ComputeSkipReason\n  = TrComputePhase;\ntr_phase_compute_vm$1 success:Bool msg_state_used:Bool\n  account_activated:Bool gas_fees:Grams\n  ^[ gas_used:(VarUInteger 7)\n  gas_limit:(VarUInteger 7) gas_credit:(Maybe (VarUInteger 3))\n  mode:int8 exit_code:int32 exit_arg:(Maybe int32)\n  vm_steps:uint32\n  vm_init_state_hash:bits256 vm_final_state_hash:bits256 ]\n  = TrComputePhase;\ncskip_no_state$00 = ComputeSkipReason;\ncskip_bad_state$01 = ComputeSkipReason;\ncskip_no_gas$10 = ComputeSkipReason;\ncskip_suspended$110 = ComputeSkipReason;\n```\n\n### When the compute phase is skipped\n\nTo start, note that the compute phase can be **skipped** entirely. In that case, the reason for skipping is explicitly recorded and can be one of the following:\n\n| Skip reason       | Description                                                                                                                                                                                                                                         |\n| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `cskip_no_state`  | The smart contract has no [state](/foundations/status#status-variety) and, therefore, no code, so execution is not possible.                                                                                                                        |\n| `cskip_bad_state` | Raised in two cases: when the `fixed_prefix_length` [field has an invalid value][fixed_prefix_length] or when the [`StateInit`](/foundations/messages/deploy) provided in the incoming message [does not match account’s address][account_address]. |\n| `cskip_no_gas`    | The incoming message did not provide enough TON to cover the gas required to execute the smart contract.                                                                                                                                            |\n| `cskip_suspended` | The address is suspended; execution is disabled (used to limit early miner accounts).                                                                                                                                                               |\n\n[fixed_prefix_length]: https://github.com/ton-blockchain/ton/blob/72056a2261cbb11f7cf0f20b389bcbffe018b1a8/crypto/block/transaction.cpp#L1721\n[account_address]: https://github.com/ton-blockchain/ton/blob/72056a2261cbb11f7cf0f20b389bcbffe018b1a8/crypto/block/transaction.cpp#L1726\n\n<Aside\n  type=\"note\"\n  title=\"Bad state\"\n>\n  The `fixed_prefix_length` field can be used to specify a fixed prefix for the account address, ensuring that the account resides in a specific shard.\n  This topic is outside the scope of this guide, but more information is available in [Shards page](/foundations/shards).\n</Aside>\n\n## Action phase\n\nOnce the smart contract code has finished executing, the **Action phase** begins. If any actions were created during the compute phase, they are processed at this stage.\n\nThere are precisely 4 types of actions in TON:\n\n```tlb\naction_send_msg#0ec3c86d mode:(## 8)\n  out_msg:^(MessageRelaxed Any) = OutAction;\naction_set_code#ad4de08e new_code:^Cell = OutAction;\naction_reserve_currency#36e6b809 mode:(## 8)\n  currency:CurrencyCollection = OutAction;\nlibref_hash$0 lib_hash:bits256 = LibRef;\nlibref_ref$1 library:^Cell = LibRef;\naction_change_library#26fa1dd4 mode:(## 7)\n  libref:LibRef = OutAction;\n```\n\n| Type                      | Description                                                                                |\n| ------------------------- | ------------------------------------------------------------------------------------------ |\n| `action_send_msg`         | Sends a message.                                                                           |\n| `action_set_code`         | Updates the smart contract's code.                                                         |\n| `action_reserve_currency` | Reserves a portion of the account's balance. This is especially useful for gas management. |\n| `action_change_library`   | Changes the library used by the smart contract.                                            |\n\nThese actions are executed _in the order in which they were created_ during code execution.\nA total of up to [255 actions](https://github.com/ton-blockchain/ton/blob/cac968f77dfa5a14e63db40190bda549f0eaf746/crypto/block/transaction.h#L164) can be made.\n\nHere is the TL-B schema, which defines the structure of the action phase:\n\n```tlb\ntr_phase_action$_ success:Bool valid:Bool no_funds:Bool\n  status_change:AccStatusChange\n  total_fwd_fees:(Maybe Grams) total_action_fees:(Maybe Grams)\n  result_code:int32 result_arg:(Maybe int32) tot_actions:uint16\n  spec_actions:uint16 skipped_actions:uint16 msgs_created:uint16\n  action_list_hash:bits256 tot_msg_size:StorageUsed\n  = TrActionPhase;\n```\n\n## Bounce phase\n\nIf the **Compute phase** or **Action phase** ends with an error, and the incoming message has the `bounce` flag set, the system triggers the **Bounce phase**.\n\n<Aside\n  type=\"note\"\n  title=\"Bounce on error\"\n>\n  For the bounce phase to trigger due to an error in the action phase, the failed action must have **flag 16** set, which enables bounce on error.\n</Aside>\n\n```tlb\ntr_phase_bounce_negfunds$00 = TrBouncePhase;\ntr_phase_bounce_nofunds$01 msg_size:StorageUsed\n  req_fwd_fees:Grams = TrBouncePhase;\ntr_phase_bounce_ok$1 msg_size:StorageUsed\n  msg_fees:Grams fwd_fees:Grams = TrBouncePhase;\n```\n\nThe `tr_phase_bounce_negfunds` type is not used in the current version of the blockchain. The other two types function as follows:\n\n| Type                      | Description                                                                                                             |\n| ------------------------- | ----------------------------------------------------------------------------------------------------------------------- |\n| `tr_phase_bounce_nofunds` | Indicates that the account does not have enough funds to process the message that should be bounced back to the sender. |\n| `tr_phase_bounce_ok`      | Indicates that the system successfully processes the bounce and sends the message back to the sender.                   |\n\nIn this phase, `msg_fees` and `fwd_fees` are calculated from the `total_fwd_fees`:\\\napproximately $\\frac{1}{3}$ goes to `msg_fees` and $\\frac{2}{3}$ go to `fwd_fees`.\n\n> See [Fees → Forward fee](/foundations/fees#forward-fee) for more info.\n\n### Key points\n\n- If the receiver cannot parse the message and terminates with a non-zero exit code, the message bounces back automatically.\n- The bounced message has its `bounce` flag cleared and `bounced` flag set, and contains `0xffffffff` (32-bit) opcode followed by the original message body.\n- Always check the `bounced` flag before parsing `op` to avoid treating a bounce as a new query.\n"
  },
  {
    "path": "foundations/precompiled.mdx",
    "content": "---\ntitle: \"Precompiled contracts\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nA precompiled smart contract is a contract with a native C++ implementation in the validator node. When a validator processes a transaction for such a contract, it can execute this native implementation instead of TVM. This improves performance and reduces computation fees.\n\n## Config\n\nThe list of precompiled contracts is stored in the blockchain configuration:\n\n```tlb\nprecompiled_smc#b0 gas_usage:uint64 = PrecompiledSmc;\nprecompiled_contracts_config#c0 list:(HashmapE 256 PrecompiledSmc) = PrecompiledContractsConfig;\n_ PrecompiledContractsConfig = ConfigParam 45;\n```\n\nThe `list:(HashmapE 256 PrecompiledSmc)` represents a mapping of contract code hash to constant gas amount. A contract is considered precompiled if its code hash exists in this map.\n\n<Aside>\n  View current values on mainnet at [ConfigParam 45 on Tonviewer](https://tonviewer.com/config#45).\n</Aside>\n\n## Accessing precompiled gas value\n\nContracts can check their precompiled gas value using the [`GETPRECOMPILEDGAS`](/tvm/instructions#f839-getprecompiledgas) opcode:\n\n- Returns the configured `gas_usage` value if the contract code hash is in `ConfigParam 45`\n- Returns `null` if the contract code hash is not in `ConfigParam 45`\n\nThe value is also available in the [`c7`](/tvm/registers#c7--environment-information-and-global-variables) register environment tuple.\n\n## Execution modes\n\nWhen a validator processes a transaction, the execution mode depends on whether the contract code hash is listed in `ConfigParam 45`.\n\n### 1. Contract is not precompiled\n\nThe contract code hash is not in `ConfigParam 45`. TVM executes normally with standard gas accounting.\n\n[`GETPRECOMPILEDGAS`](#accessing-precompiled-gas-value) returns `null`. Transaction result: `gas_used` reflects actual TVM consumption.\n\n### 2. Contract is precompiled\n\nThe contract code hash exists in `ConfigParam 45`. The validator checks the contract balance against the configured `gas_usage`. If insufficient, the compute phase fails with `cskip_no_gas`.\n\nOtherwise, execution proceeds via one of two paths.\n\n#### Contract has native C++ implementation\n\nThe native C++ implementation is available and enabled in the validator node. The validator executes the C++ code directly without invoking TVM.\n\nTransaction [result](/foundations/phases#compute-phase):\n\n- `gas_used` set to the value from `ConfigParam 45`\n- `vm_steps`, `vm_init_state_hash`, `vm_final_state_hash` set to zero\n\n#### Contract has no native C++ implementation\n\nThe native C++ implementation is disabled or unavailable in the validator node. TVM executes the contract code normally.\n\n[`GETPRECOMPILEDGAS`](#accessing-precompiled-gas-value) returns the configured gas value during execution.\n\nAfter execution completes, the validator overrides the compute phase values.\n\nTransaction result:\n\n- `gas_used` set to the value from `ConfigParam 45`\n- `vm_steps`, `vm_init_state_hash`, `vm_final_state_hash` set to zero\n\n<Aside type=\"note\">\n  The override ensures that both execution paths produce identical transaction results. This allows validators with and without native C++ implementations to coexist in the network and enables gradual adoption when adding new entries to `ConfigParam 45`.\n</Aside>\n\n## Example: Stablecoin jetton wallet\n\nThe jetton wallet from the [stablecoin-contract](https://github.com/ton-blockchain/stablecoin-contract) project is the first contract code hash added to `ConfigParam 45` on mainnet. This jetton wallet is optimized as a precompiled contract to reduce computation fees for stablecoin transfers.\n\nThe contract implements standard jetton wallet functionality with additional governance features. The precompiled gas logic is implemented in [`gas.fc`](https://github.com/ton-blockchain/stablecoin-contract/blob/5e1d79f4009430f2f7f255c5093a59d9a1628d75/contracts/gas.fc).\n"
  },
  {
    "path": "foundations/proofs/overview.mdx",
    "content": "---\ntitle: \"Overview\"\n---\n\nimport {Aside} from \"/snippets/aside.jsx\";\n\nA **proof** is a tree-based structure that contains the necessary data and can be verified by a proof requester.\nTo prove something means to construct such a structure. The exact structure may differ depending on the use case. For example, suppose a proof is to be validated off-chain and requires multiple cell trees; the native TON approach is to construct a Bag of Cells (BoC) containing all the necessary cells. This is precisely what a liteserver does when data is requested from the blockchain.\n\n<Aside>\n  It is highly recommended to familiarize yourself with [Exotic cells](/foundations/serialization/merkle) first. This article primarily covers situations where you want to verify a proof in a smart contract. However, the same techniques can be used to validate proofs off-chain.\n</Aside>\n\nThere are several key points to consider when proving anything on-chain.\n\n- The only trusted information available in a smart contract is a few recent masterchain blocks.\n- Some data is stored directly within **blocks**.\n- Additional information is maintained within the workchain **state**.\n- **Blocks** serve as diffs that reflect changes to the **state** over time. Think of **blocks** as Git commits and the **state** as your repository.\n- Latest TL-B schemas can be found in the [TON Monorepo](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb). They may evolve, typically in backward-compatible ways.\n\n## More about blocks\n\nWe need to examine the block layout to determine what we can prove and how to do it.\n\nEach block (shardchain block, masterchain block) has a unique block ID:\n\n```tlb\nblock_id_ext$_ shard_id:ShardIdent seq_no:uint32\n  root_hash:bits256 file_hash:bits256 = BlockIdExt;\n```\n\n- `ShardIdent` contains information about the workchain and the shard the block belongs to.\n- `seq_no` is the sequence number of the current block.\n- `root_hash` is the hash of the block data (block header).\n- `file_hash` helps validators optimize processes; typically, you don’t need it.\n\nA full block structure is as follows:\n\n```tlb\nblock#11ef55aa global_id:int32\n  info:^BlockInfo value_flow:^ValueFlow\n  state_update:^(MERKLE_UPDATE ShardState)\n  extra:^BlockExtra = Block;\n```\n\nThe most relevant field here is `state_update`. This `MERKLE_UPDATE` cell stores the old and new hashes of the shardchain state. Note that the masterchain always consists of a single shard, so inspecting a masterchain block reveals the masterchain state hash.\n\nAnother relevant field is `extra`:\n\n```tlb\nblock_extra in_msg_descr:^InMsgDescr\n  out_msg_descr:^OutMsgDescr\n  account_blocks:^ShardAccountBlocks\n  rand_seed:bits256\n  created_by:bits256\n  custom:(Maybe ^McBlockExtra) = BlockExtra;\n```\n\nInspecting a masterchain block reveals the `McBlockExtra` field:\n\n```tlb\nmasterchain_block_extra#cca5\n  key_block:(## 1)\n  shard_hashes:ShardHashes\n  shard_fees:ShardFees\n  ^[ prev_blk_signatures:(HashmapE 16 CryptoSignaturePair)\n     recover_create_msg:(Maybe ^InMsg)\n     mint_msg:(Maybe ^InMsg) ]\n  config:key_block?ConfigParams\n= McBlockExtra;\n```\n\nThe `shard_hashes` field is essential, as it holds the latest known shardchain blocks, which are critical for basechain proofs.\n\nFor detailed inspections, it is convenient to use the [official explorer](https://explorer.toncoin.org/).\n\n## High-level overview of proofs\n\n### Prove a transaction in masterchain\n\nTo prove a transaction's existence in the **masterchain**:\n\n1. Obtain a trusted masterchain block `root_hash` using TVM instructions (`PREVMCBLOCKS`, `PREVMCBLOCKS_100`, `PREVKEYBLOCKS`).\n1. The user provides a complete masterchain block that should be validated against the trusted hash.\n1. Parse the block to extract the transaction.\n\n### Prove a transaction in basechain\n\nFor **basechain** transactions:\n\n1. Follow _steps 1-2_ above to get a trusted `masterchain` block.\n1. Extract the `shard_hashes` field from the masterchain block.\n1. User provides the full shardchain block that should be validated against the trusted hash.\n1. Parse the shardchain block to find the transaction.\n\n### Prove account states\n\nSometimes, data is not in block diffs but within the `ShardState` itself. To prove an account's state in the **basechain**:\n\n1. Parse the shardchain block’s `state_update` field. This exotic cell contains two `ShardState` hashes (before and after the block).\n1. The user provides a `ShardState` that must be validated against the hash obtained in _step 1_.\n\n<Aside>\n  You can only prove the state at block boundaries (not intermediate states).\n</Aside>\n\n## Understanding pruned branch cells\n\nFamiliarize yourself with pruned branch cells and the concept of **hash0(cell)**.\n\n```mermaid\ngraph TD\n    subgraph \"v2\"\n        B1((\"c0\")) --> B2((\"c1\"))\n        B2 -.-> B3((\"c2\"))\n    end\n\n    subgraph \"v1\"\n        A1((\"c0\")) --> A2((\"c1\"))\n        A2 --> A3((\"c2\"))\n    end\n```\n\n_v1_ is a regular cell tree; in _v2_, the cell _c1_ becomes a pruned branch, removing its content and references. However, if you only need _c0_, there’s no practical difference, as `$hash_0(v1) == hash_0(v2)$`.\n\n- `hash0(cell)` ignores pruned branches, returning the original tree’s hash.\n- `reprHash(cell)` accounts for everything. Matching `reprHashes` ensures cell path equivalency.\n\n<Aside>\n  Use `HASHCU` for representation hash and `CHASHI`/`CHASHIX` for different-level hashes.\n</Aside>\n\n## Composing proofs\n\nIf you have two cell trees:\n\n```mermaid\ngraph TD\n    subgraph \"v1\"\n        A1((\"c0\")) --> A2((\"pruned(c1)\"))\n        A2 -.-> A3((\"c2\"))\n    end\n    subgraph \"v2\"\n        B1((\"c1\")) --> B2((\"c2\"))\n    end\n```\n\nApproaches:\n\n- Parse **v1** to get `$hash_0(c1) = x$` and verify the provided **v2**.\n- Concatenate **v2** with **v1** to reconstruct the original tree.\n\n```mermaid\ngraph TD\n    subgraph \"v1\"\n        A1((\"c0\")) --> A2((\"c1\"))\n        A2 ---> A3((\"c2\"))\n    end\n```\n\n<Aside>\n  - Trusted data hashes may be separated from cells (e.g., `PREVMCBLOCKS`).\n  - Replacing pruned cells with actual cells changes the `MERKLE_UPDATE` cell hash.\n    Always manually validate proofs against trusted hashes in these cases.\n</Aside>\n\n## Real-world example\n\nLet's consider a scenario where we want to prove that a particular account has a specific state. This is useful because having a state allows you to call a get-method on it or even emulate a transaction.\nIn this particular example, we want to prove the state of a JettonMaster and then call the `get_wallet_address` method on it. This way, even if a particular JettonMaster does not support [TEP-89](https://github.com/ton-blockchain/TEPs/blob/master/text/0089-jetton-wallet-discovery.md), it is still possible to obtain the wallet address for a specific account.\n\nThe [full example](https://github.com/tact-lang/dex/blob/main/sources/contracts/vaults/proofs/block-proof.tact) is too large for this article, but let's cover some key points.\n\nThis is an example of the proof composition technique described above. It is convenient because for `getRawAccountState`, the [liteserver](/ecosystem/nodes/overview) returns two items:\n\n- the account state itself\n- a BoC containing two proofs\n\nThe first is a shardchain block proof, and the second is a shard state proof.\n\nWe will save gas and improve parsing convenience by concatenating the `AccountState` with the `ShardState` proof, which is a cell tree where all branches are pruned except for the path from the root to the `AccountState`. The `AccountState` itself is also pruned so that we will substitute the pruned `AccountState` with the actual one.\n\n```ts\nconst accountStateAndProof = await client.liteServer.getRawAccountState(\n            jettonMinterToProofStateFor,\n            {\n                target_block: blockToProofToStrId,\n            },\n        )\n\nconst proofs = Cell.fromBoc(Buffer.from(accountStateAndProof.proof, \"hex\"))\n\nconst scBlockProof = proofs[0]\nconst newShardStateProof = proofs[1]\nconst newShardState = newShardStateProof.refs[0]\nconst accountState = Cell.fromHex(accountStateAndProof.state)\n\nconst {path} = walk(newShardState, 0, [], null) // Find the deepest pruned branch cell\nconst patchedShardState = rebuild(newShardState, path, accountState) // And replace it with the actual account state\n```\n\nAnother interesting point is how we access the hash of the last known `ShardBlock`.\n\n```tact title=\"Tact\"\ninline fun findShardInBinTree(root: Cell, address: Address, shardBitLen: Int): ShardDescr {\n    let curCs = root.beginParse();\n    // It's std address, but we parse it as VarAddress to get hash part as Slice, not as Int\n    let accountId = myParseVarAddress(address.asSlice()).address;\n    repeat (shardBitLen) {\n        if (accountId.loadBool()) {\n            // If the bit is 1, we go to the right child\n            curCs = curCs.preloadIthRef(1).beginParse();\n        } else {\n            // If the bit is 0, we go to the left child\n            curCs = curCs.preloadIthRef(0).beginParse();\n        }\n    }\n    curCs.skipBits(1); // We need to skip 1 bit - leaf tag of the tree node\n    return ShardDescr.fromSlice(curCs);\n}\n\n// ...\n\nlet mcBlockExtra = McBlockExtra.fromCell(blockHeader.extra.loadRef().beginParse().preloadIthRef(3));\n// shardHashes is a hashmap (workchain -> ShardDescr)\n// Therefore, we only need to retrieve the ShardDescr for workchain 0, as we are working in basechain.\n// We can use a non-null assertion, as we already proved that it is a valid block, and a valid masterchain block must have a ShardDescr for workchain 0.\nlet binTreeWithShardDescr: Cell = mcBlockExtra.shardHashes.get(0)!!;\nlet shardDescr = findShardInBinTree(binTreeWithShardDescr, jettonMaster, shardBitLen);\n```\n\n```tlb\n_ (HashmapE 32 ^(BinTree ShardDescr)) = ShardHashes;\n```\n\nA `BinTree` is a TL-B structure that operates straightforwardly. It stores a single bit to indicate whether the current cell is a leaf. If it is a leaf, it stores the **`ShardDescr`**. Otherwise, the cell holds two references: a left child and a right child.\n\nSince a shard identifier is a binary prefix of an address, we can traverse the tree by following the path of bits in the address.\n"
  },
  {
    "path": "foundations/proofs/verifying-liteserver-proofs.mdx",
    "content": "---\ntitle: Liteserver proof verification\n---\n\nimport {Aside} from \"/snippets/aside.jsx\";\n\n<Aside>\n  This article assumes you are familiar with [Merkle proof cells](/foundations/serialization/merkle).\n</Aside>\n\nThis article presents advanced examples of proof verification using liteservers.\n\nVerifying any data received from a node is essential for trustless interaction with the blockchain.\nHowever, this article covers only a portion of the trustless communication process with a liteserver.\nIt assumes you have verified the block hash received from a liteserver or any other source.\nBlock hash verification is a more advanced topic.\nIt requires syncing key blocks, validating block signatures, or both. This topic will be covered in a future article.\nNonetheless, even using only the examples provided here can significantly reduce the probability of accepting incorrect data from a liteserver.\n\n## Block header\n\nSuppose we have a known block ID:\n\n```d not runnable\n<TL BlockIdExt [wc=-1, shard=-9223372036854775808, seqno=31220993, root_hash=51ed3b9e728e7c548b15a5e5ce988b4a74984c3f8374f3f1a52c7b1f46c26406, file_hash=d4fcdc692de1a252deb379cd25774842b733e6a96525adf82b8ffc41da667bf5] >\n```\n\nRequest the corresponding block header from a liteserver.\nThe liteserver's [response](https://github.com/ton-blockchain/ton/blob/v2025.03/tl/generate/scheme/lite_api.tl#L36) includes a `header_proof` BoC.\n\n<details>\n  <summary><b>Show BoC</b></summary>\n\n  ```boc\n\n  b5ee9c72010207010001470009460351ed3b9e728e7c548b15a5e5ce988b4a74984c3f8374f3f1a52c7b1f46c26406001601241011ef55aaffffff110204050601a09bc7a98700000000040101dc65010000000100ffffffff000000000000000064b6c356000023d38ba64000000023d38ba64004886d00960007028101dc64fd01dc42bec400000003000000000000002e030098000023d38b96fdc401dc650048a3971c46472b85c8d761060a6e7ae9f13a90cdda815915a89597cfecb393a6b568807adfb3c1c5efc920907225175db61ca384e4f8b313799e3cbb8b7b4085284801018c6053c1185700c0fe4311d5cf8fa533ea0382e361a7b76d0cf299b75ac0356c000328480101741100d622b0d5264bcdb86a14e36fc8c349b82ae49e037002eb07079ead8b060015284801015720b6aefcbf406209522895faa6c0d10cc3315d90bcaf09791b19f595e86f8f0007\n\n  ```\n</details>\n\nAfter deserializing the BoC, we obtain the following cell:\n\n```d not runnable\n280[0351ED3B9E728E7C548B15A5E5CE988B4A74984C3F8374F3F1A52C7B1F46C264060016] -> {\n\t64[11EF55AAFFFFFF11] -> {\n\t\t640[9BC7A98700000000040101DC65010000000100FFFFFFFF000000000000000064B6C356000023D38BA64000000023D38BA64004886D00960007028101DC64FD01DC42BEC400000003000000000000002E] -> {\n\t\t\t608[000023D38B96FDC401DC650048A3971C46472B85C8D761060A6E7AE9F13A90CDDA815915A89597CFECB393A6B568807ADFB3C1C5EFC920907225175DB61CA384E4F8B313799E3CBB8B7B4085]\n\t\t},\n\t\t288[01018C6053C1185700C0FE4311D5CF8FA533EA0382E361A7B76D0CF299B75AC0356C0003],\n\t\t288[0101741100D622B0D5264BCDB86A14E36FC8C349B82AE49E037002EB07079EAD8B060015],\n\t\t288[01015720B6AEFCBF406209522895FAA6C0D10CC3315D90BCAF09791B19F595E86F8F0007]\n\t}\n}\n```\n\nDeserialize the cell according to the block [TL-B schema](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L442):\n\n```python\n_ = {\n  'global_id': -239,\n  'info':\n    {\n      'version': 0,\n      'not_master': 0,\n      'after_merge': 0,\n      'before_split': 0,\n      'after_split': 0,\n      'want_split': False,\n      'want_merge': True,\n      'key_block': False,\n      'vert_seqno_incr': 0,\n      'flags': 1,\n      'seqno': 31220993,\n      'vert_seqno': 1,\n      'shard': {'shard_pfx_bits': 0, 'workchain_id': -1, 'shard_prefix': 0},\n      'gen_utime': 1689699158,\n      'start_lt': 39391488000000,\n      'end_lt': 39391488000004,\n      'gen_validator_list_hash_short': 2288844950,\n      'gen_catchain_seqno': 459393,\n      'min_ref_mc_seqno': 31220989,\n      'prev_key_block_seqno': 31212222,\n      'gen_software': {'version': 3, 'capabilities': 46},\n      'master_ref': None,\n      'prev_ref': {'type_': 'prev_blk_info', 'prev': {'end_lt': 39391487000004, 'seqno': 31220992, 'root_hash': b'H\\xa3\\x97\\x1cFG+\\x85\\xc8\\xd7a\\x06\\nnz\\xe9\\xf1:\\x90\\xcd\\xda\\x81Y\\x15\\xa8\\x95\\x97\\xcf\\xec\\xb3\\x93\\xa6', 'file_hash': b'\\xb5h\\x80z\\xdf\\xb3\\xc1\\xc5\\xef\\xc9 \\x90r%\\x17]\\xb6\\x1c\\xa3\\x84\\xe4\\xf8\\xb3\\x13y\\x9e<\\xbb\\x8b{@\\x85'}},\n      'prev_vert_ref': None\n    },\n  'value_flow': None,\n  'state_update': None,\n  'extra': None\n}\n```\n\nNext, we need to verify that the `seqno` in the deserialized block matches the `seqno` of the block we know. After that, we compute `hash_1` for the single Merkle proof reference and compare it to our block hash.\n\n```python\nassert h_proof.refs[0].get_hash(0) == block_id.root_hash\n```\n\nNow, we can trust all other data in the cell.\n\n_Checking proof examples:_ [Python](https://github.com/yungwine/pytoniq-core/blob/873a96aa2256db33b8f35fbe2ab8fe8cf8ae49c7/pytoniq_core/proof/check_proof.py#L19), [Kotlin](https://github.com/andreypfau/ton-kotlin/blob/b1edc4b134e89ccf252149f27c85fd530377cebe/ton-kotlin-liteclient/src/commonMain/kotlin/CheckProofUtils.kt#L15), [C++](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/check-proof.cpp#L34)\n\n## Full block\n\nIn the `liteserver.getBlock` method, proof verification is performed in [Block header](#block-header). However, it includes full cells instead of pruned branches for the [value flow](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L464), [state update](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L412-L413), and [block extra](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L452) schemas.\n\n## Shard block\n\nShard proofs verify that a shard reference is stored in the masterchain block provided to the liteserver. These proofs are necessary when calling the following methods:\n\n- `liteServer.getShardInfo`\n- `liteServer.getAccountState`\n- `liteServer.runSmcMethod`\n\nTo request shard info from the liteserver for the masterchain block mentioned above, we can execute the following code:\n\n```python\nawait client.raw_get_shard_info(master, wc=0)\n```\n\nThe liteserver response contains the `BlockIdExt` of the shard block:\n\n```d not runnable\n<TL BlockIdExt [wc=0, shard=-9223372036854775808, seqno=36908135, root_hash=39e5cbca5bf69750b5d9897872c3a0d7a3e614e521c53e4de728fafed38dce27, file_hash=f1f0e5cdc4b8a12cf2438dcab60f4712d1dc04f3792b1d72f2500cbf640948b7] >\n```\n\nShard proof BoC:\n\n<details>\n  <summary><b>Show BoC</b></summary>\n\n  ```boc\n\n  b5ee9c72010219020004b9010009460332bf3592969931ca4fbc7715494b50597f1884c0d847456029d8cf0e526e6046016f0209460351ed3b9e728e7c548b15a5e5ce988b4a74984c3f8374f3f1a52c7b1f46c26406001611245b9023afe2ffffff1100ffffffff000000000000000001dc65010000000164b6c356000023d38ba6400401dc64fd600304050628480101affe84cdd73951bce07eeaad120d00400295220d6f66f1163b5fa8668202d72b000128480101faed0dd3ca110ada3d22980e3795d2bdf15450e9159892bbf330cdfd13a3b880016e22330000000000000000ffffffffffffffff820ce9d9c3929379c82807082455cc26aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac23519b11eddc69b7e090a0b0c28480101a5a7d24057d8643b2527709d986cda3846adcb3eddc32d28ec21f69e17dbaaef000128480101deab5a5aaf79c5e24f8dcbbe51747d6804104f75f58ed5bed4702c353545c6ac00110103d0400d284801015394592e3a3f1e3bc2d4249e993d0ec1e33ca18f49533991274ebc65276cd9a5001122bf0001aaa0161d000702816000047a7172dfb88800011e8b625908200ee215f71061846393a08c682e87bc3a12aff2d246eb97a09164f5657f96f9a252ef71580fe5309a823f73f3c4c3f8ab73f5a85bbf204bfd22e68d36d0efab1818e7b428be0f1028480101b20e36a3b36a4cdee601106c642e90718b0a58daf200753dbb3189f956b494b6000101db50119963380ee3280800011e9c5cb7ee0000011e9c5cb7ee29cf2e5e52dfb4ba85aecc4bc3961d06bd1f30a7290e29f26f3947d7f69c6e713f8f872e6e25c50967921c6e55b07a38968ee0279bc958eb97928065fb204a45b88000381abc00000000000000000ee327eb25b61a8a0e001343c9b67a721dcd6500202848010150fcc05bd9723571b83316a5f650be31edb131d05fdc78d271486e5d4ef077e1001928480101e5be728200b172cf7e2356cba2ae1c6e2c790be7c03cd7814c6e6fe3080b944b0011241011ef55aaffffff111213141501a09bc7a98700000000040101dc65010000000100ffffffff000000000000000064b6c356000023d38ba64000000023d38ba64004886d00960007028101dc64fd01dc42bec400000003000000000000002e16284801018c6053c1185700c0fe4311d5cf8fa533ea0382e361a7b76d0cf299b75ac0356c00032a8a0478e0f0e601ba1161ecc1395e9a0475c4f80aadbd6c483f210e96e29cf36789e432bf3592969931ca4fbc7715494b50597f1884c0d847456029d8cf0e526e6046016f016f1718284801015720b6aefcbf406209522895faa6c0d10cc3315d90bcaf09791b19f595e86f8f00070098000023d38b96fdc401dc650048a3971c46472b85c8d761060a6e7ae9f13a90cdda815915a89597cfecb393a6b568807adfb3c1c5efc920907225175db61ca384e4f8b313799e3cbb8b7b4085688c010378e0f0e601ba1161ecc1395e9a0475c4f80aadbd6c483f210e96e29cf36789e46492304dfb6ef9149781871464af686056a9627f882f60e3b24f8c944a75ebaf016f0014688c010332bf3592969931ca4fbc7715494b50597f1884c0d847456029d8cf0e526e6046da58493ccb5da3876129b0190f3c375e69e59c3ad9ff550be708999dad1f6f39016f0014\n\n  ```\n</details>\n\nThe `shard_descr` BoC can be used if the liteserver is trusted.\n\n<details>\n  <summary><b>Show BoC</b></summary>\n\n  ```boc\n\n  b5ee9c7201010201007d0001db50119963380ee3280800011e9c5cb7ee0000011e9c5cb7ee29cf2e5e52dfb4ba85aecc4bc3961d06bd1f30a7290e29f26f3947d7f69c6e713f8f872e6e25c50967921c6e55b07a38968ee0279bc958eb97928065fb204a45b88000381abc00000000000000000ee327eb25b61a8a01001343c9b67a721dcd650020\n\n  ```\n</details>\n\nAfter deserializing the shard proof BoC, two root cells are obtained:\n\n```d not runnable\n[<Cell 280[0351ED3B9E728E7C548B15A5E5CE988B4A74984C3F8374F3F1A52C7B1F46C264060016] -> 1 refs>, <Cell 280[0332BF3592969931CA4FBC7715494B50597F1884C0D847456029D8CF0E526E6046016F] -> 1 refs>]\n```\n\nThe first root is a masterchain block Merkle proof, which must be verified using the `check_block_header` function:\n\n```d not runnable\n280[0351ED3B9E728E7C548B15A5E5CE988B4A74984C3F8374F3F1A52C7B1F46C264060016] -> {\n\t64[11EF55AAFFFFFF11] -> {\n\t\t640[9BC7A98700000000040101DC65010000000100FFFFFFFF000000000000000064B6C356000023D38BA64000000023D38BA64004886D00960007028101DC64FD01DC42BEC400000003000000000000002E] -> {\n\t\t\t608[000023D38B96FDC401DC650048A3971C46472B85C8D761060A6E7AE9F13A90CDDA815915A89597CFECB393A6B568807ADFB3C1C5EFC920907225175DB61CA384E4F8B313799E3CBB8B7B4085]\n\t\t},\n\t\t288[01018C6053C1185700C0FE4311D5CF8FA533EA0382E361A7B76D0CF299B75AC0356C0003],\n\t\t552[0478E0F0E601BA1161ECC1395E9A0475C4F80AADBD6C483F210E96E29CF36789E432BF3592969931CA4FBC7715494B50597F1884C0D847456029D8CF0E526E6046016F016F] -> {\n\t\t\t560[010378E0F0E601BA1161ECC1395E9A0475C4F80AADBD6C483F210E96E29CF36789E46492304DFB6EF9149781871464AF686056A9627F882F60E3B24F8C944A75EBAF016F0014],\n\t\t\t560[010332BF3592969931CA4FBC7715494B50597F1884C0D847456029D8CF0E526E6046DA58493CCB5DA3876129B0190F3C375E69E59C3AD9FF550BE708999DAD1F6F39016F0014]\n\t\t},\n\t\t288[01015720B6AEFCBF406209522895FAA6C0D10CC3315D90BCAF09791B19F595E86F8F0007]\n\t}\n}\n```\n\nThe cell\n\n```d not runnable\n552[0478E0F0E601BA1161ECC1395E9A0475C4F80AADBD6C483F210E96E29CF36789E432BF3592969931CA4FBC7715494B50597F1884C0D847456029D8CF0E526E6046016F016F] -> {\n    560[010378E0F0E601BA1161ECC1395E9A0475C4F80AADBD6C483F210E96E29CF36789E46492304DFB6EF9149781871464AF686056A9627F882F60E3B24F8C944A75EBAF016F0014],\n    560[010332BF3592969931CA4FBC7715494B50597F1884C0D847456029D8CF0E526E6046DA58493CCB5DA3876129B0190F3C375E69E59C3AD9FF550BE708999DAD1F6F39016F0014]\n}\n```\n\nIt is a Merkle update of the [ShardState](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L412-L413) TL-B schema. The resulting new hash should be stored.\n\nAfter verifying that the only Merkle proof cell reference `Hash_1` matches the known block hash and storing the new ShardState hash, proceed to validate the second `shard proof` cell:\n\n```d not runnable\n280[0332BF3592969931CA4FBC7715494B50597F1884C0D847456029D8CF0E526E6046016F] -> {\n\t362[9023AFE2FFFFFF1100FFFFFFFF000000000000000001DC65010000000164B6C356000023D38BA6400401DC64FD40] -> {\n\t\t288[0101AFFE84CDD73951BCE07EEAAD120D00400295220D6F66F1163B5FA8668202D72B0001],\n\t\t288[0101FAED0DD3CA110ADA3D22980E3795D2BDF15450E9159892BBF330CDFD13A3B880016E],\n\t\t204[0000000000000000FFFFFFFFFFFFFFFF820CE9D9C3929379C820] -> {\n\t\t\t288[0101A5A7D24057D8643B2527709D986CDA3846ADCB3EDDC32D28EC21F69E17DBAAEF0001],\n\t\t\t288[0101DEAB5A5AAF79C5E24F8DCBBE51747D6804104F75F58ED5BED4702C353545C6AC0011]\n\t\t},\n\t\t342[CC26AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC23519B11EDDC69B7C] -> {\n\t\t\t9[D000] -> {\n\t\t\t\t878[50119963380EE3280800011E9C5CB7EE0000011E9C5CB7EE29CF2E5E52DFB4BA85AECC4BC3961D06BD1F30A7290E29F26F3947D7F69C6E713F8F872E6E25C50967921C6E55B07A38968EE0279BC958EB97928065FB204A45B88000381ABC00000000000000000EE327EB25B61A88] -> {\n\t\t\t\t\t74[43C9B67A721DCD650000]\n\t\t\t\t}\n\t\t\t},\n\t\t\t288[01015394592E3A3F1E3BC2D4249E993D0EC1E33CA18F49533991274EBC65276CD9A50011],\n\t\t\t766[0001AAA0161D000702816000047A7172DFB88800011E8B625908200EE215F71061846393A08C682E87BC3A12AFF2D246EB97A09164F5657F96F9A252EF71580FE5309A823F73F3C4C3F8AB73F5A85BBF204BFD22E68D36D0EFAB1818E7B428BC] -> {\n\t\t\t\t288[010150FCC05BD9723571B83316A5F650BE31EDB131D05FDC78D271486E5D4EF077E10019],\n\t\t\t\t288[0101E5BE728200B172CF7E2356CBA2AE1C6E2C790BE7C03CD7814C6E6FE3080B944B0011]\n\t\t\t},\n\t\t\t288[0101B20E36A3B36A4CDEE601106C642E90718B0A58DAF200753DBB3189F956B494B60001]\n\t\t}\n\t}\n}\n```\n\nThe Merkle proof reference in this cell has the prefix `9023AFE2`, corresponding to the [ShardStateUnsplit](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L410) TL-B schema. This reference's `Hash_1` must match the hash stored in the previous step:\n\n```python\n\"\"\"\nHere, mc_block_cell is the first shard proof root, and mc_state_root is the second one.\nThe check_block_header_proof function returns a new hash of the ShardState Merkle Update.\n\"\"\"\n\nmc_state_hash = mc_state_root[0].get_hash(0)\nstate_hash = check_block_header_proof(mc_block_cell[0], blk.root_hash, True)\n\nif mc_state_hash != state_hash:\n    raise ProofError('mc state hashes mismatch')\n```\n\n- _Why?_ — We can trust the associated cell data because the block header proof is verified. Therefore, the new hash from the ShardState Merkle update is considered trusted. We must confirm the hashes match to validate the second cell’s data.\n\nNow, proceed to deserialize the second cell:\n\n```python\n_ = {\n    'global_id': -239,\n    'shard_id': {'shard_pfx_bits': 0, 'workchain_id': -1, 'shard_prefix': 0},\n    'seq_no': 31220993,\n    'vert_seq_no': 1,\n    'gen_utime': 1689699158,\n    'gen_lt': 39391488000004,\n    'min_ref_mc_seqno': 31220989,\n    'out_msg_queue_info': <Cell 288[0101AFFE84CDD73951BCE07EEAAD120D00400295220D6F66F1163B5FA8668202D72B0001] -> 0 refs>,\n    'before_split': 0,\n    'accounts': <Cell 288[0101FAED0DD3CA110ADA3D22980E3795D2BDF15450E9159892BBF330CDFD13A3B880016E] -> 0 refs>,\n    'overload_history': 0,\n    'underload_history': 18446744073709551615,\n    'total_balance': {'grams': 2364000148715550620, 'other': None},\n    'total_validator_fees': {'grams': 0, 'other': None},\n    'libraries': None,\n    'master_ref': None,\n    'custom': {\n        'shard_hashes': {\n            0: {'list': [{\n                    'seq_no': 36908135,\n                    'reg_mc_seqno': 31220993,\n                    'start_lt': 39391487000000,\n                    'end_lt': 39391487000005,\n                    'root_hash': b\"9\\xe5\\xcb\\xca[\\xf6\\x97P\\xb5\\xd9\\x89xr\\xc3\\xa0\\xd7\\xa3\\xe6\\x14\\xe5!\\xc5>M\\xe7(\\xfa\\xfe\\xd3\\x8d\\xce'\",\n                    'file_hash': b'\\xf1\\xf0\\xe5\\xcd\\xc4\\xb8\\xa1,\\xf2C\\x8d\\xca\\xb6\\x0fG\\x12\\xd1\\xdc\\x04\\xf3y+\\x1dr\\xf2P\\x0c\\xbfd\\tH\\xb7',\n                    'before_split': False,\n                    'before_merge': False,\n                    'want_split': False,\n                    'want_merge': True,\n                    'nx_cc_updated': False,\n                    'flags': 0,\n                    'next_catchain_seqno': 459607,\n                    'next_validator_shard': 9223372036854775808,\n                    'min_ref_mc_seqno': 31220989,\n                    'gen_utime': 1689699153,\n                    'split_merge_at': None,\n                    'fees_collected': {'grams': 1016817575, 'other': None}, 'funds_created': {'grams': 1000000000, 'other': None}\n                }]\n            }\n        },\n        'config': {'config_addr': '5555555555555555555555555555555555555555555555555555555555555555', 'config': None},\n        'flags': 1,\n        'validator_info': {'validator_list_hash_short': 2862618141, 'catchain_seqno': 459393, 'nx_cc_updated': False},\n        'prev_blocks': None,\n        'after_key_block': True,\n        'last_key_block': {'end_lt': 39382372000004, 'seqno': 31212222, 'root_hash': b'\\xe2\\x0c0\\x8crt\\x11\\x8d\\x05\\xd0\\xf7\\x87BU\\xfeZH\\xddr\\xf4\\x12,\\x9e\\xac\\xaf\\xf2\\xdf4J]\\xee+', 'file_hash': b'\\x01\\xfc\\xa6\\x13PG\\xee~x\\x98\\x7f\\x15n~\\xb5\\x0bw\\xe4\\t\\x7f\\xa4\\\\\\xd1\\xa6\\xda\\x1d\\xf5c\\x03\\x1c\\xf6\\x85'},\n        'block_create_stats': {'type_': 'block_create_stats', 'counters': None},\n        'global_balance': {'grams': 5089971531496870767, 'other': None}\n    }\n}\n```\n\nSince this cell is trusted, we can also trust the shard block data  (`ShardStateUnsplit` -> `custom` -> `shard_hashes` -> `0 (shrdblk wc)` -> `leaf`).\n\n## Account state\n\nNext, let's prove the state of account `EQBvW8Z5huBkMJYdnfAEM5JqTNkuWX3diqYENkWsIL0XggGG` for the same masterchain block referenced at the beginning of this article.\n\nThe liteserver [response](https://github.com/ton-blockchain/ton/blob/v2025.03/tl/generate/scheme/lite_api.tl#L38) includes the masterchain block ID, which must match the one sent to the liteserver, the shard block ID, and a `shard_proof` BoC, which must be verified as described above, along with a `proof` BoC and a `state` BoC.\n\n<details>\n  <summary><b>Show BoCs</b></summary>\n\n  ```boc\n  Proof BoC:\n      b5ee9c7201023d020008480100094603f93fe5eda41a6ce9ecb353fd589842bd3f5d5e73b846cb898525293fc742fd6902190209460339e5cbca5bf69750b5d9897872c3a0d7a3e614e521c53e4de728fafed38dce27001d34235b9023afe2ffffff110000000000000000000000000002332c670000000164b6c351000023d38b96fdc501dc64fd200304052848010138f8d1c6e9f798a477d13aa26cb4d6cfe1a17949ac276b2f1e0ce037a521b9bc0001221382097522af06ffaff1f0063321d90000000000000000ffffffffffffffff825d48abc1bfebfc7bc2df8993c189361000023d38b69370401dc64fd2fa78ec529bcf9931e14f9d8b27ec1469290c0baef8256d657ce573b9679c5997431fcda6bf2d0be39344a9336cfe0ae9c844a88d2bd8022102e4012a760d4db83323130104ba9157837fd7f8f8070833231301032030fdc45f2d3838090a0b284801013e38e2548c5236a9652c45e553ced677f76550097b94138a4576f122443944d400692848010159e1a18ee4e5670306b5203912c87dffc17898f0999bd128a6965027d53b6fa40215231301013fa38088aaea2b780c0d10284801016f315f25b4a39ac12c85fea4ecfe7a83e5e59d1f059783fa0c3ef2797308806100002848010188d5f8a73382aea73dede03fc3bcda2634a717ef50e7428d5a4a44c771b014b90066231301005ecd9e51e5d22a380e0f1023130100303b3b607d7ffc781112132848010182eb0e24c842092ec2705486cbbe98de8016d55f5cff4ea910471a4c3a7a1cf1003b28480101ed7e26bd36efa6d5d9b4f6aaab9813af0742a84244977f74fd4074c9c98908be000028480101ca85960e3fc3dfb6d26e83ae87a837ae5c2faf7c8d43ea177393c602fadaa0300039221100e0f41ada252e2f08141528480101d7acbb602338c86d610f35cfb362fd76fc18b1812476b6fca99a0678e665fcf50000284801014fae109c41f3d5e2be0a3ff00a007f2e50a796797700d18a7aa663e531c37180002d221100e05c33225b78bce8161728480101545b5925b3ab2a8df2470fe22a5a3c9cc64e3cb24407c26167e0fbb476e05309002c221100e03480847f372168181928480101844a14c99695506e920635d18e76d9e685adee74e5fba6f6d3b371ca77e348130029220f00d0b1cce62aecc81a1b220f00c625c7e90dfc681c1d284801019ca2157c92d49b9d051388de45d07072c78a3aa65a5b05547d94e0369aa6bdee002a284801010326812b62712345473070d679bc38cdbbce58b7a2bf6c5c6f091fc8d36e81cd001f220f00c279d628dbf2081e1f220f00c0b8f29f9d04e82021284801019143abf2a72662054eda4f4949d010c897aff4383b514b387cff790408231c6c001a28480101de5072f46a0e0ecab2bbfc2cfc62a3fe200f12d5d457df833a46eb747fa004e30059220f00c03fa2ec9ad848222328480101baee90fd11a130d6d2e2ded21ae4a7b86553116015b7e7ebfc52369534d298b20017220f00c02e722bded7282425220d00ab138e7f18482627284801017f1df311101e472b1d443334d2426fd339539f558694c60e3428221dcb1a5478001628480101e1fc242c29e519f9740ca2570d85779aed0c593cc36b59119852945988e186960015220d00a21324d3ff2828292848010199fe288fdce2606d39f9b6af72f9c2643ef06e6bacc15dd72cfa84d63c9e44a40013220d00a1e877ec8ba82a2b284801019e019e92be76a5ae7aee239299f561682afbe445dc42ee57ccc31ecb427fdf42000e220d00a1db848431a82c2d284801012345b80e66c025fb62c41261b5d230616303ec47f3bb7a255872fada62a1e8bf0010220d00a1d633bc10682e2f220d00a02ca3ddc468303128480101654781e5d466ec4ca50cb2983b20170bb5d90e2e6ab83ed7d42a829651a5eec1000a219abb19e61b8190c2587677c010ce49a93364b965f7762a9810d916b082f45e080a02bc35ebaa649b46ac72e6e4d4c1293b66d58d9ed7a54902beefd97f5bff7977dd85998b3d000023c5643934413228480101edced2278013ea497dd2e286f495b4f7f8df6ea73e08e85414fc43a611c17797000b284801018282d13bf66b9ace1fbf5d3abd1c59cc46d61af1d47af1665d3013d8f9e47488000828480101b3e9649d10ccb379368e81a3a7e8e49c8eb53f6acc69b0ba2ffa80082f70ee390001241011ef55aaffffff113536373802a09bc7a98700000000840102332c67000000010000000000000000000000000064b6c351000023d38b96fdc0000023d38b96fdc5d41c6e3c0007035701dc64fd01dc42bec400000003000000000000002e393a28480101cb54530ac857df730e82ee239b2150528c6e5f6ed3678eab6e1e789f0e3c7a5300032a8a04f2ad1ede336a68623ddabf36cb8fa405dbe70a38c453f711000f9a9f92592db0f93fe5eda41a6ce9ecb353fd589842bd3f5d5e73b846cb898525293fc742fd69021902193b3c28480101d0cf03a1058c2fd6029288951051a0d82733953c1e9181a67c502ce59b180200000b0098000023d38b69370401dc64fd2fa78ec529bcf9931e14f9d8b27ec1469290c0baef8256d657ce573b9679c5997431fcda6bf2d0be39344a9336cfe0ae9c844a88d2bd8022102e4012a760d4db0098000023d38b87bb8402332c662b4e96320f9d0afb02e5d55b6b42c3349e33540620ecc07b399211fd56e4de3e2555617cdde457cd65a0ad033aafc0c6c25df716b04e455f49179668a46300db688c0103f2ad1ede336a68623ddabf36cb8fa405dbe70a38c453f711000f9a9f92592db04a4ff9713b206e420baaee4dd21febbeb426fcd9ce158db2a56dce9188fc313e0219001b688c0103f93fe5eda41a6ce9ecb353fd589842bd3f5d5e73b846cb898525293fc742fd6987d796744ca386906016c56921370d01f72cb004a1d7c294752afe4446da07bb0219001b\n  State BoC:\n      b5ee9c720102160100033c000271c006f5bc67986e06430961d9df00433926a4cd92e597ddd8aa6043645ac20bd178222c859043259e0d9000008f1590e4d10d405786bd75534001020114ff00f4a413f4bcf2c80b030051000000e929a9a317c1b3226ce226d6d818bafe82d3633aa0f06a6c677272d1f9b760ff0d0dcf56d8400201200405020148060704f8f28308d71820d31fd31fd31f02f823bbf264ed44d0d31fd31fd3fff404d15143baf2a15151baf2a205f901541064f910f2a3f80024a4c8cb1f5240cb1f5230cbff5210f400c9ed54f80f01d30721c0009f6c519320d74a96d307d402fb00e830e021c001e30021c002e30001c0039130e30d03a4c8cb1f12cb1fcbff1213141502e6d001d0d3032171b0925f04e022d749c120925f04e002d31f218210706c7567bd22821064737472bdb0925f05e003fa403020fa4401c8ca07cbffc9d0ed44d0810140d721f404305c810108f40a6fa131b3925f07e005d33fc8258210706c7567ba923830e30d03821064737472ba925f06e30d08090201200a0b007801fa00f40430f8276f2230500aa121bef2e0508210706c7567831eb17080185004cb0526cf1658fa0219f400cb6917cb1f5260cb3f20c98040fb0006008a5004810108f45930ed44d0810140d720c801cf16f400c9ed540172b08e23821064737472831eb17080185005cb055003cf1623fa0213cb6acb1fcb3fc98040fb00925f03e20201200c0d0059bd242b6f6a2684080a06b90fa0218470d4080847a4937d29910ce6903e9ff9837812801b7810148987159f31840201580e0f0011b8c97ed44d0d70b1f8003db29dfb513420405035c87d010c00b23281f2fff274006040423d029be84c6002012010110019adce76a26840206b90eb85ffc00019af1df6a26840106b90eb858fc0006ed207fa00d4d422f90005c8ca0715cbffc9d077748018c8cb05cb0222cf165005fa0214cb6b12ccccc973fb00c84014810108f451f2a7020070810108d718fa00d33fc8542047810108f451f2a782106e6f746570748018c8cb05cb025006cf165004fa0214cb6a12cb1fcb3fc973fb0002006c810108d718fa00d33f305224810108f459f2a782106473747270748018c8cb05cb025005cf165003fa0213cb6acb1f12cb3fc973fb00000af400c9ed54\n  ```\n</details>\n\nAfter verifying the `shard_proof`, the `proof` and `state` cells must be deserialized. The `proof` cell must contain exactly two root cells:\n\n```d not runnable\n\n[<Cell 280[0339E5CBCA5BF69750B5D9897872C3A0D7A3E614E521C53E4DE728FAFED38DCE27001D] -> 1 refs>, <Cell 280[03F93FE5EDA41A6CE9ECB353FD589842BD3F5D5E73B846CB898525293FC742FD690219] -> 1 refs>]\n\n```\n\nThe first `root` is a Merkle proof for the shard block, whose hash we have already verified and trusted.\n\n```d not runnable\n280[0339E5CBCA5BF69750B5D9897872C3A0D7A3E614E521C53E4DE728FAFED38DCE27001D] -> {\n\t64[11EF55AAFFFFFF11] -> {\n\t\t640[9BC7A98700000000840102332C67000000010000000000000000000000000064B6C351000023D38B96FDC0000023D38B96FDC5D41C6E3C0007035701DC64FD01DC42BEC400000003000000000000002E] -> {\n\t\t\t608[000023D38B69370401DC64FD2FA78EC529BCF9931E14F9D8B27EC1469290C0BAEF8256D657CE573B9679C5997431FCDA6BF2D0BE39344A9336CFE0AE9C844A88D2BD8022102E4012A760D4DB],\n\t\t\t608[000023D38B87BB8402332C662B4E96320F9D0AFB02E5D55B6B42C3349E33540620ECC07B399211FD56E4DE3E2555617CDDE457CD65A0AD033AAFC0C6C25DF716B04E455F49179668A46300DB]\n\t\t},\n\t\t288[0101CB54530AC857DF730E82EE239B2150528C6E5F6ED3678EAB6E1E789F0E3C7A530003],\n\t\t552[04F2AD1EDE336A68623DDABF36CB8FA405DBE70A38C453F711000F9A9F92592DB0F93FE5EDA41A6CE9ECB353FD589842BD3F5D5E73B846CB898525293FC742FD6902190219] -> {\n\t\t\t560[0103F2AD1EDE336A68623DDABF36CB8FA405DBE70A38C453F711000F9A9F92592DB04A4FF9713B206E420BAAEE4DD21FEBBEB426FCD9CE158DB2A56DCE9188FC313E0219001B],\n\t\t\t560[0103F93FE5EDA41A6CE9ECB353FD589842BD3F5D5E73B846CB898525293FC742FD6987D796744CA386906016C56921370D01F72CB004A1D7C294752AFE4446DA07BB0219001B]\n\t\t},\n\t\t288[0101D0CF03A1058C2FD6029288951051A0D82733953C1E9181A67C502CE59B180200000B]\n\t}\n}\n```\n\nAs in the `shard_proof` verification, the `check_block_header` function must validate the block cell and record the new `StateUpdate` hash.\n\nNext, deserialize the second root (`state_cell`) and verify that its `Hash_1` matches the previously recorded hash:\n\n```python\nproof_cells = Cell.from_boc(proof)\nif len(proof_cells) != 2:\n    raise ProofError('expected 2 root cells in account state proof')\n\nstate_cell = proof_cells[1]\n\nstate_hash = check_block_header_proof(proof_cells[0][0], shrd_blk.root_hash, True)\n\nif state_cell[0].get_hash(0) != state_hash:\n    raise ProofError('state hashes mismatch')\n```\n\nOnce the hash matches, the `state_cell` can be trusted. Its structure is as follows:\n\n<details>\n  <summary><b>Show cell</b></summary>\n\n  ```d not runnable\n  280[03F93FE5EDA41A6CE9ECB353FD589842BD3F5D5E73B846CB898525293FC742FD690219] -> {\n  \t362[9023AFE2FFFFFF110000000000000000000000000002332C670000000164B6C351000023D38B96FDC501DC64FD00] -> {\n  \t\t288[010138F8D1C6E9F798A477D13AA26CB4D6CFE1A17949AC276B2F1E0CE037A521B9BC0001],\n  \t\t75[82097522AF06FFAFF1E0] -> {\n  \t\t\t76[0104BA9157837FD7F8F0] -> {\n  \t\t\t\t76[01032030FDC45F2D3830] -> {\n  \t\t\t\t\t288[010159E1A18EE4E5670306B5203912C87DFFC17898F0999BD128A6965027D53B6FA40215],\n  \t\t\t\t\t76[01013FA38088AAEA2B70] -> {\n  \t\t\t\t\t\t288[010188D5F8A73382AEA73DEDE03FC3BCDA2634A717EF50E7428D5A4A44C771B014B90066],\n  \t\t\t\t\t\t76[01005ECD9E51E5D22A30] -> {\n  \t\t\t\t\t\t\t76[0100303B3B607D7FFC70] -> {\n  \t\t\t\t\t\t\t\t288[0101CA85960E3FC3DFB6D26E83AE87A837AE5C2FAF7C8D43EA177393C602FADAA0300039],\n  \t\t\t\t\t\t\t\t68[00E0F41ADA252E2F00] -> {\n  \t\t\t\t\t\t\t\t\t288[01014FAE109C41F3D5E2BE0A3FF00A007F2E50A796797700D18A7AA663E531C37180002D],\n  \t\t\t\t\t\t\t\t\t68[00E05C33225B78BCE0] -> {\n  \t\t\t\t\t\t\t\t\t\t288[0101545B5925B3AB2A8DF2470FE22A5A3C9CC64E3CB24407C26167E0FBB476E05309002C],\n  \t\t\t\t\t\t\t\t\t\t68[00E03480847F372160] -> {\n  \t\t\t\t\t\t\t\t\t\t\t288[0101844A14C99695506E920635D18E76D9E685ADEE74E5FBA6F6D3B371CA77E348130029],\n  \t\t\t\t\t\t\t\t\t\t\t60[00D0B1CCE62AECC0] -> {\n  \t\t\t\t\t\t\t\t\t\t\t\t60[00C625C7E90DFC60] -> {\n  \t\t\t\t\t\t\t\t\t\t\t\t\t288[01010326812B62712345473070D679BC38CDBBCE58B7A2BF6C5C6F091FC8D36E81CD001F],\n  \t\t\t\t\t\t\t\t\t\t\t\t\t60[00C279D628DBF200] -> {\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t60[00C0B8F29F9D04E0] -> {\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t288[0101DE5072F46A0E0ECAB2BBFC2CFC62A3FE200F12D5D457DF833A46EB747FA004E30059],\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t60[00C03FA2EC9AD840] -> {\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t288[0101BAEE90FD11A130D6D2E2DED21AE4A7B86553116015B7E7EBFC52369534D298B20017],\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t60[00C02E722BDED720] -> {\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t52[00AB138E7F1840] -> {\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t288[0101E1FC242C29E519F9740CA2570D85779AED0C593CC36B59119852945988E186960015],\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t52[00A21324D3FF20] -> {\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t288[010199FE288FDCE2606D39F9B6AF72F9C2643EF06E6BACC15DD72CFA84D63C9E44A40013],\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t52[00A1E877EC8BA0] -> {\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t288[01019E019E92BE76A5AE7AEE239299F561682AFBE445DC42EE57CCC31ECB427FDF42000E],\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t52[00A1DB848431A0] -> {\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t288[01012345B80E66C025FB62C41261B5D230616303EC47F3BB7A255872FADA62A1E8BF0010],\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t52[00A1D633BC1060] -> {\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t52[00A02CA3DDC460] -> {\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t616[BB19E61B8190C2587677C010CE49A93364B965F7762A9810D916B082F45E080A02BC35EBAA649B46AC72E6E4D4C1293B66D58D9ED7A54902BEEFD97F5BFF7977DD85998B3D000023C564393441] -> {\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t288[01018282D13BF66B9ACE1FBF5D3ABD1C59CC46D61AF1D47AF1665D3013D8F9E474880008]\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t288[0101EDCED2278013EA497DD2E286F495B4F7F8DF6EA73E08E85414FC43A611C17797000B]\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t288[0101654781E5D466EC4CA50CB2983B20170BB5D90E2E6AB83ED7D42A829651A5EEC1000A]\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t288[01017F1DF311101E472B1D443334D2426FD339539F558694C60E3428221DCB1A54780016]\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n  \t\t\t\t\t\t\t\t\t\t\t\t\t\t288[01019143ABF2A72662054EDA4F4949D010C897AFF4383B514B387CFF790408231C6C001A]\n  \t\t\t\t\t\t\t\t\t\t\t\t\t}\n  \t\t\t\t\t\t\t\t\t\t\t\t},\n  \t\t\t\t\t\t\t\t\t\t\t\t288[01019CA2157C92D49B9D051388DE45D07072C78A3AA65A5B05547D94E0369AA6BDEE002A]\n  \t\t\t\t\t\t\t\t\t\t\t}\n  \t\t\t\t\t\t\t\t\t\t}\n  \t\t\t\t\t\t\t\t\t}\n  \t\t\t\t\t\t\t\t},\n  \t\t\t\t\t\t\t\t288[0101D7ACBB602338C86D610F35CFB362FD76FC18B1812476B6FCA99A0678E665FCF50000]\n  \t\t\t\t\t\t\t},\n  \t\t\t\t\t\t\t288[010182EB0E24C842092EC2705486CBBE98DE8016D55F5CFF4EA910471A4C3A7A1CF1003B],\n  \t\t\t\t\t\t\t288[0101ED7E26BD36EFA6D5D9B4F6AAAB9813AF0742A84244977F74FD4074C9C98908BE0000]\n  \t\t\t\t\t\t},\n  \t\t\t\t\t\t288[0101ED7E26BD36EFA6D5D9B4F6AAAB9813AF0742A84244977F74FD4074C9C98908BE0000]\n  \t\t\t\t\t},\n  \t\t\t\t\t288[01016F315F25B4A39AC12C85FEA4ECFE7A83E5E59D1F059783FA0C3EF279730880610000]\n  \t\t\t\t},\n  \t\t\t\t288[01013E38E2548C5236A9652C45E553CED677F76550097B94138A4576F122443944D40069],\n  \t\t\t\t288[0101B3E9649D10CCB379368E81A3A7E8E49C8EB53F6ACC69B0BA2FFA80082F70EE390001]\n  \t\t\t},\n  \t\t\t288[0101B3E9649D10CCB379368E81A3A7E8E49C8EB53F6ACC69B0BA2FFA80082F70EE390001]\n  \t\t},\n  \t\t868[0000000000000000FFFFFFFFFFFFFFFF825D48ABC1BFEBFC7BC2DF8993C189361000023D38B69370401DC64FD2FA78EC529BCF9931E14F9D8B27EC1469290C0BAEF8256D657CE573B9679C5997431FCDA6BF2D0BE39344A9336CFE0AE9C844A88D2BD8022102E4012A760D4DB0] -> {\n  \t\t\t288[0101B3E9649D10CCB379368E81A3A7E8E49C8EB53F6ACC69B0BA2FFA80082F70EE390001]\n  \t\t}\n  \t}\n  }\n  ```\n</details>\n\nThe only Merkle proof reference has the prefix `9023AFE2`, which corresponds to the [ShardStateUnsplit](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L410) TL-B schema.\nTherefore, it must be deserialized accordingly.\n\n```python\n_ = {\n    'global_id': -239,\n    'shard_id': {'shard_pfx_bits': 0, 'workchain_id': 0, 'shard_prefix': 0},\n    'seq_no': 36908135,\n    'vert_seq_no': 1,\n    'gen_utime': 1689699153,\n    'gen_lt': 39391487000005,\n    'min_ref_mc_seqno': 31220989,\n    'out_msg_queue_info': <Cell 288[010138F8D1C6E9F798A477D13AA26CB4D6CFE1A17949AC276B2F1E0CE037A521B9BC0001] -> 0 refs>,\n    'before_split': 0,\n    'accounts': (\n        {\n            50368879097771769677871174881221998657607998794347754829932074327482686052226: {\n                'account': None,\n                'last_trans_hash': b'd\\x9bF\\xacr\\xe6\\xe4\\xd4\\xc1);f\\xd5\\x8d\\x9e\\xd7\\xa5I\\x02\\xbe\\xef\\xd9\\x7f[\\xffyw\\xdd\\x85\\x99\\x8b=',\n                'last_trans_lt': 39330697000001,\n                'cell': <Cell 320[649B46AC72E6E4D4C1293B66D58D9ED7A54902BEEFD97F5BFF7977DD85998B3D000023C564393441] -> 1 refs>\n            }\n        },\n        [\n            {'split_depth': 0, 'balance': {'grams': 5873792469, 'other': None}},\n            {'split_depth': 0, 'balance': {'grams': 5991493155, 'other': None}},\n            {'split_depth': 0, 'balance': {'grams': 63109456003, 'other': None}},\n            {'split_depth': 0, 'balance': {'grams': 63822897549, 'other': None}},\n            # ...\n            {'split_depth': 0, 'balance': {'grams': 21778458402704, 'other': None}},\n            {'split_depth': 0, 'balance': {'grams': 54074699968483, 'other': None}},\n            {'split_depth': 0, 'balance': {'grams': 2725956214994157511, 'other': None}}\n        ]\n    ),\n    'overload_history': 0,\n    'underload_history': 18446744073709551615,\n    'total_balance': {'grams': 2725956214994157511, 'other': None},\n    'total_validator_fees': {'grams': 37646260890702444, 'other': None},\n    'libraries': None,\n    'master_ref': {'master': {'end_lt': 39391484000004, 'seqno': 31220989, 'root_hash': b'/\\xa7\\x8e\\xc5)\\xbc\\xf9\\x93\\x1e\\x14\\xf9\\xd8\\xb2~\\xc1F\\x92\\x90\\xc0\\xba\\xef\\x82V\\xd6W\\xceW;\\x96y\\xc5\\x99', 'file_hash': b't1\\xfc\\xdak\\xf2\\xd0\\xbe94J\\x936\\xcf\\xe0\\xae\\x9c\\x84J\\x88\\xd2\\xbd\\x80\"\\x10.@\\x12\\xa7`\\xd4\\xdb'}},\n    'custom': None\n}\n```\n\nWe now need the `account` field, which is of type [ShardAccounts](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L261).\n`ShardAccounts` is a HashmapAugE, where the key is the address `hash_part`, the value is type `ShardAccount`, and the extra field is type `DeepBalanceInfo`.\n\nParsing the address `EQBvW8Z5huBkMJYdnfAEM5JqTNkuWX3diqYENkWsIL0XggGG`, we obtain the `hash_part` equal to:\n\n`50368879097771769677871174881221998657607998794347754829932074327482686052226`\n\nWe then use this key to retrieve the corresponding value from the Hashmap.\n\n```python\n_ = {\n    50368879097771769677871174881221998657607998794347754829932074327482686052226: {\n        'account': None,\n        'last_trans_hash': b'd\\x9bF\\xacr\\xe6\\xe4\\xd4\\xc1);f\\xd5\\x8d\\x9e\\xd7\\xa5I\\x02\\xbe\\xef\\xd9\\x7f[\\xffyw\\xdd\\x85\\x99\\x8b=',\n        'last_trans_lt': 39330697000001,\n        'cell': <Cell 320[649B46AC72E6E4D4C1293B66D58D9ED7A54902BEEFD97F5BFF7977DD85998B3D000023C564393441] -> 1 refs>\n    }\n}\n```\n\nWe need to store the values of `last_trans_hash` and `last_trans_lt`, as they can be used later to retrieve the account's transactions. Let's examine the entire cell containing this data.\n\n```d not runnable\n320[649B46AC72E6E4D4C1293B66D58D9ED7A54902BEEFD97F5BFF7977DD85998B3D000023C564393441] -> {\n\t288[01018282D13BF66B9ACE1FBF5D3ABD1C59CC46D61AF1D47AF1665D3013D8F9E474880008]\n}\n```\n\nThis is a regular cell with level 1, containing a single reference — the pruned account data. We compute the `Hash_1` of this pruned branch, which serves as the trusted account state hash:\n\n`8282d13bf66b9ace1fbf5d3abd1c59cc46d61af1d47af1665d3013d8f9e47488`.\n\nThe next step is to deserialize the `state` BoC:\n\n```d not runnable\n449[C006F5BC67986E06430961D9DF00433926A4CD92E597DDD8AA6043645AC20BD178222C859043259E0D9000008F1590E4D10D405786BD755300] -> {\n\t80[FF00F4A413F4BCF2C80B] -> {\n\t\t2[00] -> {\n\t\t\t4[40] -> {\n\t\t\t\t920[D001D0D3032171B0925F04E022D749C120925F04E002D31F218210706C7567BD22821064737472BDB0925F05E003FA403020FA4401C8CA07CBFFC9D0ED44D0810140D721F404305C810108F40A6FA131B3925F07E005D33FC8258210706C7567BA923830E30D03821064737472BA925F06E30D] -> {\n\t\t\t\t\t480[01FA00F40430F8276F2230500AA121BEF2E0508210706C7567831EB17080185004CB0526CF1658FA0219F400CB6917CB1F5260CB3F20C98040FB0006],\n\t\t\t\t\t552[5004810108F45930ED44D0810140D720C801CF16F400C9ED540172B08E23821064737472831EB17080185005CB055003CF1623FA0213CB6ACB1FCB3FC98040FB00925F03E2]\n\t\t\t\t},\n\t\t\t\t2[00] -> {\n\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t4[50] -> {\n\t\t\t\t\t\t\t242[B29DFB513420405035C87D010C00B23281F2FFF274006040423D029BE84C40],\n\t\t\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t\t\t97[ADCE76A26840206B90EB85FF80],\n\t\t\t\t\t\t\t\t97[AF1DF6A26840106B90EB858F80]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t68[B8C97ED44D0D70B1F0]\n\t\t\t\t\t},\n\t\t\t\t\t357[BD242B6F6A2684080A06B90FA0218470D4080847A4937D29910CE6903E9FF9837812801B7810148987159F3180]\n\t\t\t\t}\n\t\t\t},\n\t\t\t992[F28308D71820D31FD31FD31F02F823BBF264ED44D0D31FD31FD3FFF404D15143BAF2A15151BAF2A205F901541064F910F2A3F80024A4C8CB1F5240CB1F5230CBFF5210F400C9ED54F80F01D30721C0009F6C519320D74A96D307D402FB00E830E021C001E30021C002E30001C0039130E30D03A4C8CB1F12CB1FCBFF] -> {\n\t\t\t\t440[D207FA00D4D422F90005C8CA0715CBFFC9D077748018C8CB05CB0222CF165005FA0214CB6B12CCCCC973FB00C84014810108F451F2A702],\n\t\t\t\t448[810108D718FA00D33FC8542047810108F451F2A782106E6F746570748018C8CB05CB025006CF165004FA0214CB6A12CB1FCB3FC973FB0002],\n\t\t\t\t432[810108D718FA00D33F305224810108F459F2A782106473747270748018C8CB05CB025005CF165003FA0213CB6ACB1F12CB3FC973FB00],\n\t\t\t\t40[F400C9ED54]\n\t\t\t}\n\t\t}\n\t},\n\t321[000000E929A9A317C1B3226CE226D6D818BAFE82D3633AA0F06A6C677272D1F9B760FF0D0DCF56D800]\n}\n```\n\nCompute its representation hash, and verify that it matches the trusted hash obtained from the pruned data:\n\n`8282d13bf66b9ace1fbf5d3abd1c59cc46d61af1d47af1665d3013d8f9e47488`.\n\nFinally, the BoC is deserialized using the [account](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L231-L233) TL-B schema.\n\n```python\n_ = {\n    'addr': Address<EQBvW8Z5huBkMJYdnfAEM5JqTNkuWX3diqYENkWsIL0XggGG>,\n    'storage_stat': {'used': {'cells': 22, 'bits': 5697, 'public_cells': None}, 'last_paid': 1689502130, 'due_payment': None},\n    'storage': {\n        'last_trans_lt': 39330697000003,\n        'balance': {'grams': 5873792469, 'other': None},\n        'state': {\n            'type_': 'account_active',\n            'state_init': {'split_depth': None, 'special': None, 'code': <Cell 80[FF00F4A413F4BCF2C80B] -> 1 refs>, 'data': <Cell 321[000000E929A9A317C1B3226CE226D6D818BAFE82D3633AA0F06A6C677272D1F9B760FF0D0DCF56D800] -> 0 refs>, 'library': None}\n        }\n    }\n}\n```\n\nAt this point, the account state data is verified and trusted.\n\n## Account transactions\n\nFor the [liteServer.getTransactions](https://github.com/ton-blockchain/ton/blob/v2025.03/tl/generate/scheme/lite_api.tl#L94) request, we must provide the `lt` and `hash` of the transaction to start from.\nIf we want to retrieve an account's latest transactions, we can extract the `lt` and `hash` from the trusted `ShardAccount`, as described above.\n\nWhen the liteserver returns the transactions, it provides a BoC containing the requested number of transaction roots. Each root is a cell that should be deserialized using the [transaction](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L263-L269) TL-B schema.\nFor the first transaction cell, verify that its hash matches the `last_trans_hash` from the account state. Then, store the `prev_trans_hash` field, compare it to the hash of the second transaction root, and continue the verification process in this manner.\n\n## Block transactions\n\nNext, we query the liteserver for the list of transactions belonging to the block we started with at the beginning of this article.\nThe liteserver [response](https://github.com/ton-blockchain/ton/blob/v2025.03/tl/generate/scheme/lite_api.tl#L47) includes `ids` field with the transaction list and a `proof` BoC.\nThe first step is to deserialize the `proof`:\n\n```d not runnable\n280[0351ED3B9E728E7C548B15A5E5CE988B4A74984C3F8374F3F1A52C7B1F46C264060016] -> {\n\t64[11EF55AAFFFFFF11] -> {\n\t\t288[0101F8039FE65901BE422094ED29FA05DD4A9406708D7C54EBF7F6010F2E8A9DCBB10001],\n\t\t288[01018C6053C1185700C0FE4311D5CF8FA533EA0382E361A7B76D0CF299B75AC0356C0003],\n\t\t288[0101741100D622B0D5264BCDB86A14E36FC8C349B82AE49E037002EB07079EAD8B060015],\n\t\t545[4A33F6FD11224E018A0801116DBA929FAA60F8B9DFB39286C07FDE613D4F158E4031612597E23F312DA061732C2DB7C7C7F0BCA6295EF25D04F46FA21A055CF213A1270A80] -> {\n\t\t\t288[0101E057F7AA0545EF9E6BF187542A5141298303A33BA7C9CE26C71FFD9C7D2050600004],\n\t\t\t6[00],\n\t\t\t6[80] -> {\n\t\t\t\t9[4000] -> {\n\t\t\t\t\t605[BFB333333333333333333333333333333333333333333333333333333333333333029999999999999999999999999999999999999999999999999999999999999999CF800008F4E2E9900000] -> {\n\t\t\t\t\t\t9[5000] -> {\n\t\t\t\t\t\t\t288[01015EF0532AF460BCF3BECF1A94597C1EC04879E0F26BF58269D319121376AAD4730002]\n\t\t\t\t\t\t},\n\t\t\t\t\t\t9[4000] -> {\n\t\t\t\t\t\t\t288[0101B1E091FCB9DF53917EAA0CAE05041B3D0956242871E3CA8D6909D0AA31FF36040002]\n\t\t\t\t\t\t},\n\t\t\t\t\t\t520[7239A4AED4308E2E6AC11C880CCB29DFEE407A3E94FC1EDBDD4D29AF3B5DFEEE58A9B07203A0F457150A2BF7972DA7E2A79642DEBE792E919DE5E2FC284D2B158A]\n\t\t\t\t\t},\n\t\t\t\t\t607[BF955555555555555555555555555555555555555555555555555555555555555502AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD0000008F4E2E99000C0] -> {\n\t\t\t\t\t\t288[0101924B5992DF95114196994A6D449D89E1C002CB96C14D11C4A667F843A3FAF4410002],\n\t\t\t\t\t\t520[72899B3A210DDD28D905C583FF8559BCF73D0CF0C05C11210BD7059BAB2AB453E03524184B116C9E39D9D5293179588F4B7D8F5D8192FEFE66B9FE40A71518DBC7]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t288[01010FC5CF36DC84BC46E7175768AB3EC0F94988D454F2C496DC1AC32E638CD3C23D0005]\n\t\t}\n\t}\n}\n```\n\nWe must verify the **block header proof** to trust the cell's contents. Once verified, we can deserialize it using the block TL-B schema.\n\n```python\n_ = {\n    'global_id': -239,\n    'info': None,\n    'value_flow': None,\n    'state_update': None,\n    'extra': {\n        'in_msg_descr': <Cell 288[0101E057F7AA0545EF9E6BF187542A5141298303A33BA7C9CE26C71FFD9C7D2050600004] -> 0 refs>,\n        'out_msg_descr': ({}, [<Slice 5[00] -> 0 refs>]),\n        'account_blocks': (\n            {\n                23158417847463239084714197001737581570653996933128112807891516801582625927987:  {\n                    'account_addr': '3333333333333333333333333333333333333333333333333333333333333333',\n                    'transactions': (\n                        {\n                            39391488000001: <Cell 288[01015EF0532AF460BCF3BECF1A94597C1EC04879E0F26BF58269D319121376AAD4730002] -> 0 refs>,\n                            39391488000002: <Cell 288[0101B1E091FCB9DF53917EAA0CAE05041B3D0956242871E3CA8D6909D0AA31FF36040002] -> 0 refs>\n                        },\n                        [{'grams': 0, 'other': None}, {'grams': 0, 'other': None}, {'grams': 0, 'other': None}]\n                    ),\n                    'state_update': {'old_hash': b'9\\xa4\\xae\\xd40\\x8e.j\\xc1\\x1c\\x88\\x0c\\xcb)\\xdf\\xee@z>\\x94\\xfc\\x1e\\xdb\\xddM)\\xaf;]\\xfe\\xeeX', 'new_hash': b'\\xa9\\xb0r\\x03\\xa0\\xf4W\\x15\\n+\\xf7\\x97-\\xa7\\xe2\\xa7\\x96B\\xde\\xbey.\\x91\\x9d\\xe5\\xe2\\xfc(M+\\x15\\x8a'}\n                },\n                38597363079105398474523661669562635951089994888546854679819194669304376546645: {\n                    'account_addr': '5555555555555555555555555555555555555555555555555555555555555555',\n                    'transactions': (\n                        {\n                            39391488000003: <Cell 288[0101924B5992DF95114196994A6D449D89E1C002CB96C14D11C4A667F843A3FAF4410002] -> 0 refs>\n                        },\n                    [{'grams': 0, 'other': None}]\n                    ),\n                    'state_update': {'old_hash': b'\\x89\\x9b:!\\r\\xdd(\\xd9\\x05\\xc5\\x83\\xff\\x85Y\\xbc\\xf7=\\x0c\\xf0\\xc0\\\\\\x11!\\x0b\\xd7\\x05\\x9b\\xab*\\xb4S\\xe0', 'new_hash': b'5$\\x18K\\x11l\\x9e9\\xd9\\xd5)1yX\\x8fK}\\x8f]\\x81\\x92\\xfe\\xfef\\xb9\\xfe@\\xa7\\x15\\x18\\xdb\\xc7'}\n                }\n            },\n            [{'grams': 0, 'other': None}, {'grams': 0, 'other': None}, {'grams': 0, 'other': None}]\n        ),\n        'rand_seed': b'\\x11\"N\\x01\\x8a\\x08\\x01\\x11m\\xba\\x92\\x9f\\xaa`\\xf8\\xb9\\xdf\\xb3\\x92\\x86\\xc0\\x7f\\xdea=O\\x15\\x8e@1a%',\n        'created_by': b\"\\x97\\xe2?1-\\xa0as,-\\xb7\\xc7\\xc7\\xf0\\xbc\\xa6)^\\xf2]\\x04\\xf4o\\xa2\\x1a\\x05\\\\\\xf2\\x13\\xa1'\\n\",\n        'custom': None\n    }\n}\n```\n\nAfter successful deserialization, we should extract and remember the following field: `block` -> `extra` -> `account_blocks`.\nThis field has the type [ShardAccountBlocks](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L282), which is a `HashmapAugE`, where:\n\n- The key is the address `hash_part`.\n- The value is of type [AccountBlock](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L277-L280).\n- The extra data is a `CurrencyCollection`.\n\n```python\n_ = {\n    23158417847463239084714197001737581570653996933128112807891516801582625927987:  {\n        'account_addr': '3333333333333333333333333333333333333333333333333333333333333333',\n        'transactions': (\n            {\n                39391488000001: <Cell 288[01015EF0532AF460BCF3BECF1A94597C1EC04879E0F26BF58269D319121376AAD4730002] -> 0 refs>,\n                39391488000002: <Cell 288[0101B1E091FCB9DF53917EAA0CAE05041B3D0956242871E3CA8D6909D0AA31FF36040002] -> 0 refs>\n            },\n            [{'grams': 0, 'other': None}, {'grams': 0, 'other': None}, {'grams': 0, 'other': None}]\n        ),\n        'state_update': {'old_hash': b'9\\xa4\\xae\\xd40\\x8e.j\\xc1\\x1c\\x88\\x0c\\xcb)\\xdf\\xee@z>\\x94\\xfc\\x1e\\xdb\\xddM)\\xaf;]\\xfe\\xeeX', 'new_hash': b'\\xa9\\xb0r\\x03\\xa0\\xf4W\\x15\\n+\\xf7\\x97-\\xa7\\xe2\\xa7\\x96B\\xde\\xbey.\\x91\\x9d\\xe5\\xe2\\xfc(M+\\x15\\x8a'}\n    },\n    38597363079105398474523661669562635951089994888546854679819194669304376546645: {\n        'account_addr': '5555555555555555555555555555555555555555555555555555555555555555',\n        'transactions': (\n            {\n                39391488000003: <Cell 288[0101924B5992DF95114196994A6D449D89E1C002CB96C14D11C4A667F843A3FAF4410002] -> 0 refs>\n            },\n        [{'grams': 0, 'other': None}]\n        ),\n        'state_update': {'old_hash': b'\\x89\\x9b:!\\r\\xdd(\\xd9\\x05\\xc5\\x83\\xff\\x85Y\\xbc\\xf7=\\x0c\\xf0\\xc0\\\\\\x11!\\x0b\\xd7\\x05\\x9b\\xab*\\xb4S\\xe0', 'new_hash': b'5$\\x18K\\x11l\\x9e9\\xd9\\xd5)1yX\\x8fK}\\x8f]\\x81\\x92\\xfe\\xfef\\xb9\\xfe@\\xa7\\x15\\x18\\xdb\\xc7'}\n    }\n}\n```\n\nNow, let's check the `ids` field:\n\n```python\n[\n    {'mode': 39, 'account': '3333333333333333333333333333333333333333333333333333333333333333', 'lt': 39391488000001, 'hash': '5ef0532af460bcf3becf1a94597c1ec04879e0f26bf58269d319121376aad473'},\n    {'mode': 39, 'account': '3333333333333333333333333333333333333333333333333333333333333333', 'lt': 39391488000002, 'hash': 'b1e091fcb9df53917eaa0cae05041b3d0956242871e3ca8d6909d0aa31ff3604'},\n    {'mode': 39, 'account': '5555555555555555555555555555555555555555555555555555555555555555', 'lt': 39391488000003, 'hash': '924b5992df95114196994a6d449d89e1c002cb96c14d11c4a667f843a3faf441'}\n]\n```\n\nFor each transaction, we should find its corresponding entry in the `account_blocks` we remembered and verify that their hashes match:\n\n```python\nblock_trs: dict = acc_block.get(int(tr['account'], 16)).transactions[0]\nblock_tr: Cell = block_trs.get(tr['lt'])\nassert block_tr.get_hash(0) == tr['hash']\n```\n\n:::note\nIn this example, checking the `ids` field was optional — we could have retrieved all transactions directly from the account blocks.\nHowever, verifying the transaction proofs becomes essential when using the [liteServer.listBlockTransactionsExt](https://github.com/ton-blockchain/ton/blob/v2025.03/tl/generate/scheme/lite_api.tl#L48) method, and you must compare transaction hashes.\n:::\n\n## Config\n\nRequest the following [config params](https://github.com/ton-blockchain/ton/blob/v2025.03/tl/generate/scheme/lite_api.tl#L101) from the liteserver: 1, 4, 5, 7, 8, and 15 for [liteServer.getConfigAll](https://github.com/ton-blockchain/ton/blob/v2025.03/tl/generate/scheme/lite_api.tl#L100), where all parameters are returned, and the proof verification remains the same.\nThe [response](https://github.com/ton-blockchain/ton/blob/v2025.03/tl/generate/scheme/lite_api.tl#L54) includes `state_proof` and `config_proof`.\n\nFirst, deserialize the `state_proof` cell:\n\n```d not runnable\n280[0351ED3B9E728E7C548B15A5E5CE988B4A74984C3F8374F3F1A52C7B1F46C264060016] -> {\n\t64[11EF55AAFFFFFF11] -> {\n\t\t640[9BC7A98700000000040101DC65010000000100FFFFFFFF000000000000000064B6C356000023D38BA64000000023D38BA64004886D00960007028101DC64FD01DC42BEC400000003000000000000002E] -> {\n\t\t\t608[000023D38B96FDC401DC650048A3971C46472B85C8D761060A6E7AE9F13A90CDDA815915A89597CFECB393A6B568807ADFB3C1C5EFC920907225175DB61CA384E4F8B313799E3CBB8B7B4085]\n\t\t},\n\t\t288[01018C6053C1185700C0FE4311D5CF8FA533EA0382E361A7B76D0CF299B75AC0356C0003],\n\t\t552[0478E0F0E601BA1161ECC1395E9A0475C4F80AADBD6C483F210E96E29CF36789E432BF3592969931CA4FBC7715494B50597F1884C0D847456029D8CF0E526E6046016F016F] -> {\n\t\t\t560[010378E0F0E601BA1161ECC1395E9A0475C4F80AADBD6C483F210E96E29CF36789E46492304DFB6EF9149781871464AF686056A9627F882F60E3B24F8C944A75EBAF016F0014],\n\t\t\t560[010332BF3592969931CA4FBC7715494B50597F1884C0D847456029D8CF0E526E6046DA58493CCB5DA3876129B0190F3C375E69E59C3AD9FF550BE708999DAD1F6F39016F0014]\n\t\t},\n\t\t288[01015720B6AEFCBF406209522895FAA6C0D10CC3315D90BCAF09791B19F595E86F8F0007]\n\t}\n}\n```\n\nTo do this, verify the block header proof and store the new hash from the `StateUpdate`.\n\nNext, deserialize the `config_proof` cell:\n\n```d not runnable expandable\n280[0332BF3592969931CA4FBC7715494B50597F1884C0D847456029D8CF0E526E6046016F] -> {\n\t362[9023AFE2FFFFFF1100FFFFFFFF000000000000000001DC65010000000164B6C356000023D38BA6400401DC64FD40] -> {\n\t\t288[0101AFFE84CDD73951BCE07EEAAD120D00400295220D6F66F1163B5FA8668202D72B0001],\n\t\t288[0101FAED0DD3CA110ADA3D22980E3795D2BDF15450E9159892BBF330CDFD13A3B880016E],\n\t\t204[0000000000000000FFFFFFFFFFFFFFFF820CE9D9C3929379C820] -> {\n\t\t\t288[0101A5A7D24057D8643B2527709D986CDA3846ADCB3EDDC32D28EC21F69E17DBAAEF0001],\n\t\t\t288[0101DEAB5A5AAF79C5E24F8DCBBE51747D6804104F75F58ED5BED4702C353545C6AC0011]\n\t\t},\n\t\t342[CC26AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC23519B11EDDC69B7C] -> {\n\t\t\t288[0101C7DAE90A1FCEAD235CACC318A048986B2E12D0F68C136845669E02C4E28F018D0002],\n\t\t\t2[00] -> {\n\t\t\t\t8[D8] -> {\n\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t\t\t\t\t\t288[0101F89085ED347F5F928A0DF7B1271F906F6E1EF43D89B5912774C8B42D0E24AB120001],\n\t\t\t\t\t\t\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t\t\t\t\t\t\t256[3333333333333333333333333333333333333333333333333333333333333333]\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t4[40] -> {\n\t\t\t\t\t\t\t\t\t\t\t256[0000000000000000000000000000000000000000000000000000000000000000]\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t\t\t\t\t\t\t256[E56754F83426F69B09267BD876AC97C44821345B7E266BD956A7BFBFB98DF35C]\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t\t\t\t\t\t\t329[01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000008000000100]\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t4[50] -> {\n\t\t\t\t\t\t\t\t\t\t\t1[80] -> {\n\t\t\t\t\t\t\t\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t\t\t\t\t\t\t\t83[BE000003BCB3670DC15540],\n\t\t\t\t\t\t\t\t\t\t\t\t\t83[BFFFFFFFBCBD1A94A20000]\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t\t\t\t\t\t\t104[C400000002000000000000002E]\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t288[0101C1F3C2ADA12BD901BBA1552C0C090CC3989649807C2B764D02548C1F664C20890007]\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t288[010187DADFBB3AE954E7F5472C46A729ED80AD087C5D9CEBB8D644D16DD73F88DF390009]\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t\t\t\t\t288[01017CF937AF64AED1AB2CDD1435F8FF79F86E521320CC7B0CB30C9AAE81748124090002],\n\t\t\t\t\t\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t\t\t\t\t\t288[0101BEE8EB75C37500A75962E4FD99AFC62B3C9245948D2AC56061B0E21DDD6E9E840001],\n\t\t\t\t\t\t\t\t\t\t\t2[00] -> {\n\t\t\t\t\t\t\t\t\t\t\t\t128[00010000000080000000200000008000]\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t288[0101289F7704162F68EF3CC5B4865BD72067277E25B21514AB741396C54BD92294FA0009]\n\t\t\t\t\t\t},\n\t\t\t\t\t\t288[0101EF6962F43C1C86B216773B443F61829550DD9E956EE54EA3AC5C60E127DADD51000E]\n\t\t\t\t\t},\n\t\t\t\t\t288[0101112A0556A091DC4F72BD31FF2790783FB3238CE2AA41E1C137424D279664D7E3000A]\n\t\t\t\t},\n\t\t\t\t288[010124D21CF7AE96B1C55A1230E823DB0317CE24EC33E3BF2585C79605684304FAF20007]\n\t\t\t},\n\t\t\t766[0001AAA0161D000702816000047A7172DFB88800011E8B625908200EE215F71061846393A08C682E87BC3A12AFF2D246EB97A09164F5657F96F9A252EF71580FE5309A823F73F3C4C3F8AB73F5A85BBF204BFD22E68D36D0EFAB1818E7B428BC] -> {\n\t\t\t\t288[010150FCC05BD9723571B83316A5F650BE31EDB131D05FDC78D271486E5D4EF077E10019],\n\t\t\t\t288[0101E5BE728200B172CF7E2356CBA2AE1C6E2C790BE7C03CD7814C6E6FE3080B944B0011]\n\t\t\t},\n\t\t\t2[00] -> {\n\t\t\t\t83[BE000003BCB3670DC15540],\n\t\t\t\t83[BFFFFFFFBCBD1A94A20000]\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\nCompare the `Hash_1` from the Merkle proof (reference only) with the hash obtained from the `check_block_header` function above. If they match, the cell can be trusted:\n\n```python\nstate_hash = check_block_header_proof(state_proof[0], block.root_hash, True)\nif config_proof[0].get_hash(0) != state_hash:\n    raise LiteClientError('hashes mismatch')\n```\n\nNext, deserialize the cell using the `ShardStateUnsplit` schema:\n\n```python\n_ = {\n    'global_id': -239,\n    'shard_id': {'shard_pfx_bits': 0, 'workchain_id': -1, 'shard_prefix': 0},\n    'seq_no': 31220993,\n    'vert_seq_no': 1,\n    'gen_utime': 1689699158,\n    'gen_lt': 39391488000004,\n    'min_ref_mc_seqno': 31220989,\n    'out_msg_queue_info': <Cell 288[0101AFFE84CDD73951BCE07EEAAD120D00400295220D6F66F1163B5FA8668202D72B0001] -> 0 refs>,\n    'before_split': 0,\n    'accounts': <Cell 288[0101FAED0DD3CA110ADA3D22980E3795D2BDF15450E9159892BBF330CDFD13A3B880016E] -> 0 refs>,\n    'overload_history': 0,\n    'underload_history': 18446744073709551615,\n    'total_balance': {'grams': 2364000148715550620, 'other': None},\n    'total_validator_fees': {'grams': 0, 'other': None},\n    'libraries': None,\n    'master_ref': None,\n    'custom': {\n        'shard_hashes': None,\n        'config': {\n            'config_addr': '5555555555555555555555555555555555555555555555555555555555555555',\n            'config': {\n                1: <Slice 256[3333333333333333333333333333333333333333333333333333333333333333] -> 0 refs>,\n                4: <Slice 256[E56754F83426F69B09267BD876AC97C44821345B7E266BD956A7BFBFB98DF35C] -> 0 refs>,\n                5: <Slice 329[01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000008000000100] -> 0 refs>,\n                7: <Slice 1[80] -> 1 refs>,\n                8: <Slice 104[C400000002000000000000002E] -> 0 refs>,\n                15: <Slice 128[00010000000080000000200000008000] -> 0 refs>}\n            },\n            'flags': 1,\n            'validator_info': {'validator_list_hash_short': 2862618141, 'catchain_seqno': 459393, 'nx_cc_updated': False},\n            'prev_blocks': None,\n            'after_key_block': True,\n            'last_key_block': {'end_lt': 39382372000004, 'seqno': 31212222, 'root_hash': b'\\xe2\\x0c0\\x8crt\\x11\\x8d\\x05\\xd0\\xf7\\x87BU\\xfeZH\\xddr\\xf4\\x12,\\x9e\\xac\\xaf\\xf2\\xdf4J]\\xee+', 'file_hash': b'\\x01\\xfc\\xa6\\x13PG\\xee~x\\x98\\x7f\\x15n~\\xb5\\x0bw\\xe4\\t\\x7f\\xa4\\\\\\xd1\\xa6\\xda\\x1d\\xf5c\\x03\\x1c\\xf6\\x85'},\n            'block_create_stats': {'type_': 'block_create_stats', 'counters': None},\n            'global_balance': {'grams': 5089971531496870767, 'other': {239: 666666666666, 4294967279: 1000000000000}}\n    }\n}\n```\n\nThen, access the `ShardStateUnsplit` -> `custom` -> `config` -> `config` field, a Hashmap where the key is a `ConfigParam` number and the value is a cell containing the parameter value.\n\nAfter deserializing all parameters, we obtain:\n\n```python\n_ = {\n    1: {\n        'elector_addr': b'33333333333333333333333333333333',\n    },\n    4: {\n        'dns_root_addr': b'\\xe5gT\\xf84&\\xf6\\x9b\\t&{\\xd8v\\xac\\x97\\xc4H!4[~&k\\xd9V\\xa7\\xbf\\xbf\\xb9\\x8d\\xf3\\\\',\n    },\n    5: {\n        'blackhole_addr': b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff',\n        'fee_burn_nom': 1,\n        'fee_burn_denom': 2\n    },\n    7: {\n        'to_mint': {'dict': {239: 666666666666, 4294967279: 1000000000000}}\n    },\n    8: {\n        'version': 2,\n        'capabilities': 46\n    },\n    15: {\n        'validators_elected_for': 65536,\n        'elections_start_before': 32768,\n        'elections_end_before': 8192,\n        'stake_held_for': 32768\n    }\n}\n```\n"
  },
  {
    "path": "foundations/serialization/boc.mdx",
    "content": "---\ntitle: \"Bag of cells\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nArbitrary data are represented in TON Blockchain by trees of cells.\n\n```mermaid\ngraph TD\n  n[\"🔵 0x1111\"] --> 0x2222\n  n[\"🔵 0x1111\"] --> 0x3333\n  0x2222 --> d1[\"0x4444\"]\n  0x3333 --> d2[\"0x4444\"]\n```\n\nSuch a tree of cells is transformed into a [DAG](https://en.wikipedia.org/wiki/Directed_acyclic_graph) of cells by identifying cells in the tree that have the same hash.\n\n```mermaid\ngraph TD\n  n[\"🔵 0x1111\"] --> 0x2222\n  n[\"🔵 0x1111\"] --> 0x3333\n  0x2222 --> 0x4444\n  0x3333 --> 0x4444\n```\n\nAfter that, each of the references of each cell might be replaced by the 32-byte [representation hash](/foundations/serialization/cells#standard-cell-representation-and-its-hash) of the cell referred to. Thus a _bag of cells (BoC)_ is obtained.\n\n```\n🔵 Roots: [0x1111]\n\n0x1111\n  Refs: [0x2222, 0x3333]\n0x2222\n  Refs: [0x4444]\n0x3333\n  Refs: [0x4444]\n0x4444\n  Refs: []\n```\n\nIn general, a BoC can be obtained from several trees of cells, thus forming a forest.\n\n```mermaid\ngraph TD\n  n[\"🔵 0x1111\"] --> 0x3333\n  m[\"🔵 0x2222\"] --> 0x3333\n```\n\nBy convention, the roots of the original trees of cells are marked elements of the resulting bag of cells, so that anybody receiving this bag of cells and knowing the marked elements can reconstruct the original forest. However, this BoC needs to be serialized into a file, suitable for disk storage or network transfer.\n\n```\n🔵 Roots: [0x1111, 0x2222]\n\n0x1111\n  Refs: [0x3333]\n0x2222\n  Refs: [0x3333]\n0x3333\n  Refs: []\n```\n\nThere may be many different ways to serialize such a data structure, each of which has its own goals and is convenient for specific cases. This page provides a general serialization algorithm and specification of the corresponding [TL-B](/languages/tl-b/overview) schemes, followed by the example and specific implementation used in the TON Blockchain.\n\n<Aside type=\"note\">\n  Even though the syntax looks very much like TL-B, it cannot be used in most of the TL-B tooling. Unlike in real TL-B, these schemas serialize to a bitstring with no 1023 bit length limit, and without any refs.\n</Aside>\n\n## General scheme\n\n### Internal references, absent cells, and complete BoCs\n\nFor an arbitrary cell `c` in a given BoC, references to it can be either:\n\n- _internal_ if the cell corresponding to the reference is also represented in BoC,\n- _external_ if it's not in BoC. Such cell `c` is called _absent_ from this BoC.\n\nA BoC is called _complete_ if it does not contain any external references. Most real-world BoCs are complete.\n\n### Outline of serialization process\n\n<Aside type=\"note\">\n  This paragraphs provide a textual description of the BoC serialization process. The specific implementation of the serialization and TL-B schemes is left to the choice of developers.\n\n  For a specific example of TL-B schema and pseudocode of related cell serialization, see [TL-B schema](/foundations/serialization/boc#tl-b-schema).\n</Aside>\n\nThe serialization process of a BoC `B` consisting of `n` cells can be outlined as follows.\n\n- List the cells from B in a [topological order](https://en.wikipedia.org/wiki/Topological_sorting): `c1, ..., cn`(with `c1, ..., ck` as root cells, if `B` is a forest).\n- Choose the smallest number of bytes `s` that can contain the binary representation of `n`. Serialize each cell `ci` in a way similar to [standard representation algorithm](/foundations/serialization/cells#standard-cell-representation-and-its-hash), with exceptions:\n  - `d1 = r + 8s + 16h + 32l` where `h = 1` if the cell's hashes are explicitly included into the serialization; otherwise, `h = 0` (when `r = 7`, `h` must be `1`);\n  - if `h = 1`, after bytes `b1` and `b2` the serialization is continued by `l + 1` 32-byte higher hashes of `c`;\n  - unsigned big-endian s-bit integer `j` used instead of hash `Hash(cj)` to represent internal references to cell `cj`.\n- Concatenate the representations of cells `ci` thus obtained in the increasing order of `i`.\n- Optionally, an _index_ can be constructed that consists of `n` `t`-bytes integer entries $L_{1}, \\ldots, L_{n}$ where:\n  - $L_{i}$ is the total length in bytes of the representations of cells `cj` with `j ≤ i`;\n  - `t` is the smallest number of bytes that can contain the binary representation of $L_{n}$.\n- An optional [CRC32C](https://en.wikipedia.org/wiki/Cyclic_redundancy_check) may be appended to the serialization for integrity verification purposes.\n\nIf the index is included, any cell `ci` the serialized bag of cells may be easily accessed by its index `i` without deserializing all other cells, or even without loading the entire serialized bag of cells in memory.\n\nA final serialization of the bag of cells must include a magic number indicating the precise format of the serialization, followed by integers `s`, `t`, `n`, an optional index consisting of `n * t` bytes, $L_n$ bytes with the cell representations, and an optional `CRC32C` checksum. Each specific implementation of the serialization process must comply with these fields and their order but, for example, may take into account number of roots, number of absent cells, and so one.\n\n## Serialization\n\n<Aside type=\"note\">\n  Beware this is not an actual TL-B schema. TL-B describes serialization to cells, i.e. bits and refs, with the limit of 1023 bits per cell. This serialization describes serialization into a bitstring of arbitrary length without any refs, even though it uses syntax similar to TL-B.\n</Aside>\n\nOnly one [serialization scheme of BoCs](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/tl/boc.tlb#L25) is used in TON Blockchain (there are also two outdated BoC serialization schemes in the file):\n\n```tlb PseudoTL-B\nserialized_boc#b5ee9c72 has_idx:(## 1) has_crc32c:(## 1) \n    has_cache_bits:(## 1) flags:(## 2) { flags = 0 }\n    size:(## 3) { size <= 4 }\n    off_bytes:(## 8) { off_bytes <= 8 } \n    cells:(##(size * 8)) \n    roots:(##(size * 8)) { roots >= 1 }\n    absent:(##(size * 8)) { roots + absent <= cells }\n    tot_cells_size:(##(off_bytes * 8))\n    root_list:(roots * ##(size * 8))\n    index:has_idx?(cells * ##(off_bytes * 8))\n    cell_data:(tot_cells_size * [ uint8 ])\n    crc32c:has_crc32c?uint32\n    = BagOfCells;\n```\n\nFields `size` is `s`, `off_bytes` is `t`, `cells` is `n`, `tot_cells_size` is $L_n$ (the total size of the serialization of all cells in bytes), `index` is the optional index $L_{1}, \\ldots, L_{n}$, `cell_data` is the concatenation of the cells representations, and `crc32c` is the optional 4-bytes CRC32C checksum.\n\nThis schema additionally includes:\n\n- the 1-bit `has_idx` flag that indicates whether the index is included in the serialization;\n- the 1-bit `has_crc32c` flag that indicates whether the CRC32C checksum is included in the serialization;\n- the 1-bit `has_cache_bits` and 2-bit `flags` fields that are reserved for future use (`flags` must be zero);\n- the `roots` field that indicates the number of root cells in the BoC;\n- the `absent` field that indicates the number of absent cells in the BoC;\n- the `root_list` field that is an indices sequence of the root cells in the BoC.\n\n## Example: manual\n\nConsider the following example of a tree of cells:\n\n```json\n01\n  0aaaaa\n  fe\n    0aaaaa\n```\n\nSo, there is a 2-bit root cell that references two other cells:\n\n- The first is a 24-bit cell.\n- The second is a 8-bit cell that itself references a 24-bit cell.\n\nAfter identifying of unique cells, we have the following:\n\n```json\n01\n0aaaaa\nfe\n```\n\nNext, the unique cells are arranged in a topological order:\n\n```json\n01     -> index 0 (root cell)\nfe     -> index 1\n0aaaaa -> index 2\n```\n\nNow, let's calculate the descriptor bytes `b1` and `b2` for each of the three unique cells.\n\nSo, we obtain:\n\n```json\n01     -> 0201\nfe     -> 0102\n0aaaaa -> 0006\n```\n\nThen the data bits are serialized as $\\lceil\\frac{b}{8}\\rceil$ bytes. Remember, if `b` is not a multiple of eight, a binary `1` and up to six binary `0s` are appended to the data bits. After that, the data is split into $\\lceil\\frac{b}{8}\\rceil$ 8-bit groups.\n\n```json\n01     -> 01100000 = 0x60\nfe     -> do not change (full groups)\n0aaaaa -> do not change (full groups)\n```\n\nNext come the depths for the refs in two bytes:\n\n```json\n01     -> 0002\nfe     -> 0001\n0aaaaa -> 0000\n```\n\nNow specify which cells each one references:\n\n```json\n0: 01     -> 0201: refers to 2 cells with such indexes\n1: fe     -> 02: refers to cells with index 2\n2: 0aaaaa -> no refs\n```\n\nFor each cell we have its hexadecimal representation:\n\n```json\n01     -> 02016000020201\nfe     -> 0102fe000102\n0aaaaa -> 00060aaaaa0000\n```\n\nFinally, we concatenate all parts into a single hexadecimal array:\n`0x020160000202010102fe00010200060aaaaa0000`.\n\nNow that we've serialized our cells into a flat 20-byte array, it's time to pack them into a complete BoC format.\n\n```text\n0xb5ee9c72                                 -> TL-B id of the BoC structure\n0b1                                        -> has indexes\n0b0                                        -> does not have CRC32C\n0b0                                        -> does not have cache bits\n0b00                                       -> flags are 0\n0b001                                      -> the number of bytes needed to store the number of cells is 1\n0b00000001                                 -> the number of bytes used to represent offset of a serialization is 1\n0b00000011                                 -> the number of cells is 3\n0b00000001                                 -> the number of roots is 1\n0b00000000                                 -> the number of absent cells is 0\n0b00010100                                 -> tot_cells_size is 20 bytes\n0b00000000                                 -> the root list; we have one root with number 0 after the topological sort\n0b000001110000111000010100                 -> the three 8-bits group of indexes for cells accorging to the topological sort\n0x020160000202010102fe00010200060aaaaa0000 -> the cells data\n_                                          -> CRC32C is not serialized\n```\n\nBy combining everything into a single bit string, we get the result of serialization.\n\n## Example: TypeScript\n\nAccording to the TL-B scheme above there is the [SDK](https://github.com/ton-org/ton-core/blob/4577e94/src/boc/cell/serialization.ts#L1) for serialization and parsing BoC.\n\nOnly serialization of BoCs with one root and no absent cells is supported. There are two main functions:\n\n- `serializeBoc` for serialization. It has two parameters: `root` and options object with two boolean flags: `idx` and `crc32`. They indicate whether indexes and CRC32C will be included in serialization. The output is a Buffer with serialization.\n- `deserializeBoc` for parsing. It has one parameter: `src`, a Buffer that contains a serialized BoC. The output is a roots list of a given BoC.\n\n```ts\nimport { beginCell, serializeBoc, deserializeBoc } from \"@ton/core\";\n\nconst innerCell = beginCell()\n    .storeUint(456, 16)\n    .endCell();\nconst rootCell = beginCell()\n    .storeUint(0, 64)\n    .storeRef(innerCell)\n    .endCell();\n\nconst boc = serializeBoc(\n    rootCell,\n    {\n        // do not include index\n        idx: false,\n        // do not include CRC-32\n        crc32: false,\n    },\n);\nconst decodedRootCell = deserializeBoc(boc)[0];\n```\n\nAlternatively, use methods of `Cell`:\n\n```ts\nimport { Cell } from \"@ton/core\";\n\nconst hex = 'b5ee9c72410106010082000114ff00f4a413f4bcf2c80b01...';\n\n// deserialze\nconst cell = Cell.fromBoc(Buffer.from(hex, 'hex'))[0];\n\n// serialize\nconst hexBack = cell.toBoc().toString('hex');\n```\n"
  },
  {
    "path": "foundations/serialization/cells.mdx",
    "content": "---\ntitle: \"Cells\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n## Basic structure\n\nThe TON Virtual Machine (TVM) memory, persistent storage, and smart contract code consist of cells. In turn, each cell consists of\n\n- up to 1023 bits;\n- up to 4 references to other cells.\n\n<Aside>\n  Circular references are forbidden and cannot be created, because computing [cryptographic hash function](https://en.wikipedia.org/wiki/Cryptographic_hash_function) of data that contains the same hash is impossible.\n</Aside>\n\nIn this way, all cells are kept in TVM memory and persistent storage\nconstitute a [directed acyclic graph (DAG)](https://en.wikipedia.org/wiki/Directed_acyclic_graph).\n\nFrom the perspective of low-level cell operations, these data bits and cell references\nare not intermixed. In other words, a cell essentially is a couple consisting of\na list of up to 1023 bits and a list of up to four cell references, without prescribing an\norder in which the references and the data bits should be deserialized, even though TL-B\nschemes appear to suggest such an order.\n\n## Kinds of cells\n\nThere are two kinds of cells: _ordinary_ and _exotic_. The former are the simplest and most commonly used flavor of cells, which can\nonly contain data and references, while the latter are used for special purposes only. They sometimes appear in actual representations of\nblocks and other data structures on TON Blockchain. Their memory layouts and purposes differ significantly from ordinary cells.\n\nFrom the low-level perspective, ordinary and exotic cells can be distinguished\nby a special 1-bit flag stored outside the main 1,023 bits and read by TVM at runtime. Users cannot read this flag directly.\n\nTVM can support up to 256 different types of exotic cells, each identified by a special 8-bit type identifier stored in the first byte of the cell data.\nTVM supports four types of exotic cells:\n\n| Type ID | Description                                               |\n| ------- | --------------------------------------------------------- |\n| `0x01`  | [Pruned branch](/foundations/serialization/pruned)        |\n| `0x02`  | [Library reference](/foundations/serialization/library)   |\n| `0x03`  | [Merkle proof](/foundations/serialization/merkle)         |\n| `0x04`  | [Merkle update](/foundations/serialization/merkle-update) |\n\n## Level of a cell\n\nEvery cell c has an attribute $Lvl(c)$ called its **level**, which takes integer values in the range `0…3`.\nA cell's level affects the number of higher hashes it has.\nThe level of an ordinary cell $c$ is equal to the maximum of the levels of all its children $c_i$:\n\n$$\nLvl(c) = \\max_i Lvl(c_i).\n$$\n\nFor instance, each cell in a tree of cells that does not contain any exotic cell has level 0.\n\nExotic cells may have different rules for setting their level.\n\n## Standard cell representation and its hash\n\nBefore a cell can be transferred over the network or stored on disk, it must be serialized. A common way to do\nthis is to use the so-called _standard cell representation_, `CellRepr(c)`. The standard representation of a cell `c` is a byte sequence that is constructed as follows:\n\n- Two descriptor bytes $d_1$ and $d_2$ are serialized first. Byte $d_1$ equals `r+8s+32l`, where `0 ≤ r ≤ 4` is the quantity of cell references contained\n  in the cell, `0 ≤ l ≤ 3` is the level of the cell, and `0 ≤ s ≤ 1` is `1` for\n  exotic cells and `0` for ordinary cells. Byte $d_2$ equals $\\lfloor\\frac{b}{8}\\rfloor + \\lceil\\frac{b}{8}\\rceil$, where `0 ≤ b ≤ 1023`\n  is the quantity of data bits in `c`.\n- Then the data bits are serialized as $\\lceil\\frac{b}{8}\\rceil$ bytes. If `b` is not a multiple of eight, a binary `1` and up to six binary `0s` are appended to\n  the data bits. After that, the data is split into $\\lceil\\frac{b}{8}\\rceil$ 8-bit groups, and each group is interpreted as an unsigned big-endian integer 0 … 255\n  and stored into a byte.\n- Next, for every referenced cell, `2` bytes in big-endian format store the depth of the refs, i.e. the number of cells between the root of the\\\n  cell tree (the current cell) and the deepest reference, including it. For example, a cell containing only one reference and no further references\n  would have a depth of `1`, while the referenced cell would have a depth of `0`.\n- Finally, for every referenced cell, the SHA-256 hash of its standard representation is stored, occupying `32` bytes per referenced cell,\n  recursively repeating the said algorithm. Note that cyclic cell references are not allowed, so this algorithm always terminates.\n  If there are no referenced cells, neither depths nor hashes are stored.\n\nIn this way, $2 + \\lceil\\frac{b}{8}\\rceil + 2r + 32r$ bytes of `CellRepr(c)` are obtained. Thus, we got the serialization of `c`.\n\nHowever, the serialization of graphs formed by cells is arranged differently; see [bag of cells](/foundations/serialization/boc) for details.\n\n## Cell manipulation\n\nCells are read-only and immutable, but there are two major sets of ordinary cell manipulation instructions in TVM:\n\n- Cell creation (or serialization) instructions, which are used to construct new cells from previously stored values and cells.\n- Cell parsing (or deserialization) instructions, which are used to extract or load data previously stored into cells via serialization instructions.\n\nAll cell manipulation instructions require transforming values of `Cell` type into either [builder](/tvm/builders-and-slices) or [slice](/tvm/builders-and-slices) types before such cells can be modified or inspected.\n\nLibraries like [`@ton/core`](https://github.com/ton-core/ton) and [`@ton-community/assets-sdk`](https://github.com/ton-community/assets-sdk) provide efficient cell handling.\nBelow are examples of sequential cell creation, populating it with data, and then parsing.\n\n### Create a cell and store data\n\nTo build a cell, you use the `beginCell()` function. While the cell is open, you can store various data types with `store...()` functions.\nWhen you're done, you close the cell with the `endCell()` function.\n\n```typescript\nimport { Address, beginCell } from \"@ton/core\";\n\nconst cell = beginCell()\n  .storeUint(99, 64) // Stores uint 99 in 64 bits\n  .storeAddress(Address.parse(\"EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c\")) // Stores an address\n  .storeCoins(123) // Stores 123 as coins\n  .endCell(); // Closes the cell\n```\n\nEach cell has a 1023-bit limit. If you exceed this, an error occurs:\n\n```typescript\n// This will fail due to overflow\nconst cell = beginCell()\n  .storeUint(1, 256)\n  .storeUint(2, 256)\n  .storeUint(3, 256)\n  .storeUint(4, 256) // Exceeds 1023-bit limit (256 + 256 + 256 + 256 = 1024)\n  .endCell();\n```\n\nTo store more data, cells can reference up to four other cells. You can use the `storeRef()` function to create nested cells:\n\n```typescript\nconst cell = beginCell()\n  .storeUint(1, 256)\n  .storeUint(2, 256)\n  .storeRef(beginCell().storeUint(3, 256).storeUint(4, 256).endCell())\n  .endCell();\n```\n\nYou can store optional (nullable) values in cells by using the `storeMaybe...()` helpers:\n\n```typescript\nconst cell = beginCell()\n  .storeMaybeInt(null, 64) // Optionally stores an int\n  .storeMaybeInt(1, 64)\n  .storeMaybeRef(null) // Optionally stores a reference\n  .storeMaybeRef(beginCell().storeCoins(123).endCell())\n  .endCell();\n```\n\n### Load data from a cell\n\nTo read data from a cell, you first convert it into a slice using the `beginParse()` function.\nThen, you can extract various data types with `load...()` functions. **You read data in the same order it was stored**.\n\n```typescript\nconst slice = cell.beginParse();\nconst uint = slice.loadUint(64);\nconst address = slice.loadAddress();\nconst coins = slice.loadCoins();\n```\n\nTo load a referenced (nested) cell, use `loadRef()`:\n\n```typescript\nconst slice = cell.beginParse();\nconst uint1 = slice.loadUint(256);\nconst uint2 = slice.loadUint(256);\nconst innerSlice = slice.loadRef().beginParse(); // Load and parse nested cell\nconst uint3 = innerSlice.loadUint(256);\nconst uint4 = innerSlice.loadUint(256);\n```\n\nYou can parse optional values using the corresponding `loadMaybe...()` functions. Returned values are nullable, so do not forget to check them for null.\n\n```typescript\nconst slice = cell.beginParse();\nconst maybeInt = slice.loadMaybeInt(64);\nconst maybeInt1 = slice.loadMaybeInt(64);\nconst maybeRef = slice.loadMaybeRef();\nconst maybeRef1 = slice.loadMaybeRef();\nif (maybeRef1) {\n  const coins = maybeRef1.beginParse().loadCoins();\n}\n```\n\n## References\n\n- [Parse and view TON smart contract cells in a human-readable format](https://ton-cell-abi-viewer.vercel.app/).\n"
  },
  {
    "path": "foundations/serialization/library.mdx",
    "content": "---\ntitle: \"Library references\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nWhile cells are deduplicated by hash within each data store on TON, there might be situations where cells with the same hash are required in several stores. For example, if there is a popular contract with a lot of instances, and there's no need to duplicate and store separately part of its code for every instance.\n\nThis is where libraries are needed: they store a single cell that is available to all the contracts. Library reference cells store a hash of such a library, and tell TVM to look up the content of such a library cell. This might reduce the size of serialized data and enable efficient storage of incrementally updated data.\n\nThe library reference has level `0`, so it does not contain any higher hashes.\n\nEach library cell is serialized as follows:\n\n- The 1-byte tag that always equals `0x02`.\n- The 256-bit [representation hash](/foundations/serialization/cells) of the library cell being referred to.\n\n## Introduction\n\nOne of the native features of how TON stores data in cells is deduplication: duplicate cells are stored only once in storage, messages, blocks, transactions, and other elements. This significantly reduces the size of serialized data and enables efficient storage of incrementally updated data.\n\nThe library allows extending the deduplication mechanism on-chain, enabling the incorporation of the same efficiency into custom smart contracts.\n\n<Aside>\n  You can think of a library cell as a const weak C++ pointer: a small cell that references a larger one, which may include many references. The referenced cell must exist and be registered publicly, i.e., “published”.\n</Aside>\n\n### Low-level details\n\nThey always have level 0.\n\nThey store a tag equal to 2 in the first 8 bits.\nThen 256 bits follow, which are the representation hash of the referenced cell.\n\nWhen a library cell is stored in account storage, the account pays storage for this cell equal to the cost of 1 cell and 256 + 8 bits.\n\n### Hierarchical library cells\n\nLibrary cells can reference other library cells. However, they are not automatically dereferenced by the CTOS instruction (`begin_parse` in FunC). Attempting to do so results in exit code 9. Use `XLOAD` or XCTOS to dereference explicitly.\n\nCreating libraries that reference a cell whose tree contains other library cells is fine.\n\n### Smart-contract library environment\n\nWhen a contract tries to load a library cell, the library is looked up in its library environment.\n\nThe library environment of a smart contract is a hashmap mapping 256-bit cell (representation) hashes to the corresponding cells themselves. When an external cell reference is accessed during the execution of a smart contract, the referenced cell is looked up in the library environment, and the external cell reference is transparently replaced by the cell found. The library environment for an invocation of a smart contract is computed as follows:\n\n1. The global library environment for the workchain in question is taken from the current state of the Masterchain.\n\n1. Next, it is augmented by the local library environment of the smart contract, stored in the library field of the smart contract’s state. Only 256-bit keys equal to the hashes of the corresponding value cells are taken into account. If a key is present in both the global and local library environments, the local environment takes precedence while merging the two library environments.\n\n1. Finally, the message library stored in the library field of the init field of the inbound message is similarly taken into account. Note, however, that if the account is frozen or uninitialized, the library field of the message is part of the suggested state of the account and is used instead of the local library environment in the previous step. The message library has lower precedence than both the local and the global library environments.\n\n### Hosting a library cell\n\nLibraries are hosted in the states of accounts. More specifically, they reside in the `library` field in the account.\n\n```tlb\n_ fixed_prefix_length:(Maybe (## 5)) special:(Maybe TickTock)\n  code:(Maybe ^Cell) data:(Maybe ^Cell)\n  library:(HashmapE 256 SimpleLib) = StateInitWithLibs;\n\nsimple_lib$_ public:Bool root:^Cell = SimpleLib;\n```\n\nOne can see the `public` flag in SimpleLib.\nThis flag allows making a library cell private (accessible only from the account hosting it), even if the account hosting it resides in the Masterchain.\n\nAlso, if the account hosting the library becomes frozen, the library becomes inaccessible. So it is crucial to keep in mind that storage costs in the Masterchain are much higher than in the Basechain and to carefully control the balance of the account that hosts the library.\n\n### Other articles\n\nLibrary cells are mainly used to minimize storage costs for accounts with identical code. Read more about this [pattern](/contract-dev/using-on-chain-libraries).\n"
  },
  {
    "path": "foundations/serialization/merkle-update.mdx",
    "content": "---\ntitle: \"Merkle updates\"\n---\n\nMerkle update cells always have two references, `c1`, `c2`, and behave like a Merkle proof for both.\nThe level of a Merkle update cell, `0 <= l < 3`, is determined as `max{Lvl(c1) - 1, Lvl(c2) - 1, 0}`.\n\nEach Merkle update cell serializes as follows:\n\n- one tag byte with value `0x04`;\n- the 256-bit higher hash of the referenced cell `c1` or the [representation hash](/foundations/serialization/cells) of `c` if its level equals zero;\n- the same for the second reference `c2`;\n- 2 bytes that store the depth of the old deleted subtree that was replaced by the reference `c1`;\n- 2 bytes that store the depth of the new deleted subtree that was replaced by the reference `c2`.\n"
  },
  {
    "path": "foundations/serialization/merkle.mdx",
    "content": "---\ntitle: \"Merkle proofs\"\n---\n\nMerkle proof cells verify that some cell tree data belongs to the full tree.\nThis design allows the verifier to avoid storing the entire tree's content while still being able to verify the content using the root hash.\n\nA Merkle proof cell contains exactly one reference `c`. Its level `0 <= l < 3` is `max{Lvl(c) - 1, 0}`.\n\nEach Merkle proof cell serializes as follows:\n\n- one tag byte with value `0x03`;\n- the 256-bit first higher hash of the referenced cell `c` or the [representation hash](/foundations/serialization/cells)\n  of `c` if its level equals zero;\n- 2 bytes that store the depth of the deleted subtree that was replaced by the reference.\n"
  },
  {
    "path": "foundations/serialization/pruned.mdx",
    "content": "---\ntitle: \"Pruned branches\"\n---\n\nPruned branch cells are cells that represent deleted subtrees of the tree of cells.\n\nMay have any level between `1` and `3`, which is equal to the level of a root of the pruned subtree plus one.\nEach of pruned branch cells get serialized as follows.\n\n- The 1-byte tag that always equals `1`.\n- The byte that contains the pruned branch level mask, `1 <= mask <= 7`. The number of hashes stored in the pruned branch cell\n  is equal to the number of `1-bits` in the mask.\n- Next, `h * 32` bytes store [representations hashes](/foundations/serialization/cells) of roots of the pruned subtrees starting\n  from the last one. For example, if the mask equals `3` (binary `011`), then the pruned tree cell contains representation hashes of the second\n  and the first pruned subtrees in sequential order, but not the third one.\n- Finally, `h * 2` bytes store the depths of the pruned subtrees starting from the last one.\n"
  },
  {
    "path": "foundations/services.mdx",
    "content": "---\ntitle: \"Web3 services\"\n---\n\nimport { Image } from '/snippets/image.jsx';\n\nAlthough many people refer to TON only as a blockchain, _The Open Network_ is a combination of the following components:\n\n- A flexible multi-blockchain platform with Turing-complete smart contracts (TON Blockchain)\n- A peer-to-peer network used by Blockchain Nodes (TON Network)\n- A distributed file storage technology (TON Storage)\n- A network proxy/anonymizer layer (TON Proxy)\n- A Kademlia-like distributed hash table (TON DHT)\n- A service for assigning human-readable names to accounts, smart contracts, services, and network nodes (TON DNS)\n- A platform for micro-payments (TON Payments)\n\nThis article provides a general overview of TON Services, beyond the blockchain.\n\n## TON Network\n\nTON Network is a peer-to-peer network used for accessing the TON Blockchain, sending transactions, and receiving updates. Also, it can support arbitrary distributed services, blockchain-related or not. The cornerstone in TON networking is the ADNL protocol, built on top of the TCP/UDP stack.\n\nThe TON Distributed Hash Table (DHT) plays a crucial role in the networking component of the TON Project, as it is used to locate other nodes in the network. You can think of it as a big, persistent key-value data storage. The keys of the TON DHT are simply 256-bit integers. In most cases, they are computed as sha256 hashes of a TL-serialized objects. The values assigned to these 256-bit keys are essentially arbitrary byte strings of limited length.\n\n<Image\n  src=\"/resources/images/open-network/adnl.png\"\n  darkSrc=\"/resources/images/open-network/adnl.png\"\n  alt=\"adnl\"\n/>\n\n## TON Storage\n\nTON Storage allows users to share and store files using _The Open Network_. Since storing files on-chain isn't practical, TON Storage only stores Merkle proofs for file content on-chain. It uses TON DHT to find the nodes that have a copy of a required file (e.g., a snapshot of the state of a shardchain, or an old block). Then, one might essentially create a torrent for this file and use TON DHT as a \"distributed torrent tracker\" for this torrent.\n\n## TON Proxy\n\nTON Proxy provides a protocol where nodes wishing to offer their services (with or without compensation) as tunnels for ADNL network traffic can register. Those needing them can then choose one of these nodes based on the price, latency, and bandwidth offered. Since ADNL traffic is encrypted, Proxy can't access tunneled data, meaning that this protocol is secure.\n\nRunning TON Proxy allows you to visit TON Sites (HTTP over ADNL). This can be combined with TON DNS and other TON Services, forming together what is called \"Open Network\".\n\n## TON DNS\n\nTON DNS is a service that translates human-readable domain names like `test.ton` or `mysite.temp.ton` into TON smart contract addresses, ADNL addresses used by services on the TON Network such as TON Sites, and more. The standard is implemented using smart contracts and config parameters.\n\nTON Domain names are well-established in the ecosystem - various wallet applications and explorers recognize them.\n\nTON Domains can be assigned to any ADNL address, meaning that it is possible to assign names to TON Storage files (bags).\n\n## TON Payments\n\nTON Payments platform enables \"instant payments\" - a way to transfer monetary values without the need to commit all transactions to the blockchain. This protocol is built on top of TON Blockchain, using a system of smart contracts.\n\nThe core idea for such a \"lightning network\" is point-to-point **payment channels**. Two parties create a shared \"money pool\" and then update the balance inside it.\n\nThe overall overhead of such instant payments is so small that one can use them for micro-payments. For example, a TON file-storing service might charge the user for every 128 KiB of downloaded data, or a paid TON Proxy might require some tiny micro-payment for every 128 KiB of traffic relayed.\n"
  },
  {
    "path": "foundations/shards.mdx",
    "content": "---\ntitle: \"Blockchain sharding\"\n---\n\nimport { Image } from '/snippets/image.jsx';\n\nTON Blockchain is a collection of blockchains that are called _workchains_. Each workchain might have different formats of [account addresses](/foundations/addresses/overview), formats of [transactions](/foundations/messages/ordinary-tx), and different virtual machines for smart contracts.\n\nTON Blockchain dynamically splits workchains into halves when the transaction rate is above the threshold, and merges them when it decreases below the threshold. This is called _Infinite Sharding Paradigm_. [Sharding](https://en.wikipedia.org/wiki/Shard_\\(database_architecture\\)) is the general concept used to split the load into several parts, to ease requirements on a single computing element of some system.\n\nEach account is the sole citizen of its corresponding blockchain, _accountchain_. Each accountchain describes the state and state transitions of only one account. An accountchain is a virtual concept used in explanations.\n\nRegularly creating empty blocks for rarely updated accountchains would be too expensive. To reduce the cost, accountchains are grouped into _shardchains_, where each block is a collection of blocks of accountchains that have been assigned to this shard.\n\n<Image\n  src=\"/resources/images/blockchain_sharding.png\"\n  alt=\"Blockchain hierarchy\"\n/>\n\n## Sharding process\n\nThere might be up to `2^32` workchains, identified with `workchain_id`. Each workchain might use its own format for [`account_id`](/foundations/addresses/overview#account-id), but every such ID must be at least 64-bit long. A pair of `workchain_id` and `account_id` uniquely identifies an account.\n\nEach shardchain is identified by a pair `(workchain_id, shard_prefix)`, where `shard_prefix` is a bit string of length at most `60`. Accounts that have `account_id` starting with `shard_prefix` (have `shard_prefix` as the most significant bits) will be assigned to this shardchain.\n\nWhen the volume of transactions per block exceeds the threshold, validators decide to split shards into halves.\n\nAssume a workchain initially has one shardchain with an empty `shard_prefix`, i.e., it contains all accounts of that workchain. Then the load exceeded the threshold and the validators decide to split this shardchain into two with `shard_prefix` equal to `0` and `1`, respectively. After that, all accounts with an `account_id` starting with bit `0` will be assigned to the first shardchain, and all accounts with `account_id` starting with bit `1` will be assigned to the second shardchain.\n\nIf some shardchain with `shard_prefix` equal to `p` needs to be split, then two new shardchains with `shard_prefix` equal to `p0` and `p1` will be created.\n\nWhen a merge is needed, two shardchains with `shard_prefix` equal to `p0` and `p1` merge into one shardchain with `shard_prefix` equal to `p`. After the merge, all accounts with `account_id` starting with `p` will be assigned to this new single shardchain.\n\nAs a result of sharding process, the number of shardchains in each workchain is a power of two, and can vary dynamically from `1` to `2^60`.\n\n## Messages between shardchains\n\nShardchains can exchange messages with each other. It works both for shardchains of the same and different workchains.\n\nSize of the block sets a limit to how many transactions a shardchain can process in a single block. Every shardchain can do computations asynchronously and in isolation from each other, so due to mismatch in the rate of message processing there might be an congestion: one shard sends messages to another, and it cannot process them at the moment.\n\nDuring congestion, handling of messages that do not fit into current block is delayed to next blocks. Unprocessed messages are still stored only in blocks of sending shardchains, and receiving shardchain would have to check for all the possible sending shardchains for possible unprocessed messages. In the case of a large number of shardchains, the inspection time for all sending shardchains may be too long. In addition, if a shardchain can receive messages from all other shardchains, then its blocks can fill up very quickly, which will lead to a large delay in outgoing messages in the remaining shardchains.\n\nMinimizing the time it takes to transfer data between different shardchains is crucial for complex protocols, such as token processing and decentralized exchanges (DEX). In these scenarios, different participants may be located in different shardchains, making it essential to optimize the communication process.\n\nTo reduce the number of possible sending shardchains to only `16 * 15` _neighboring shardchains_, a _hypercube routing_ mechanism is used.\n\n### Hypercube routing\n\nThe set of all shardchains of a given workchain and their connection to neighboring shardchains can be represented as a hypercube. Each vertex of the hypercube corresponds to a shardchain, and two shardchains are connected by an edge if they are neighbors. Omitting the technical details, the neighborhood relation is determined using the differences in the `shard_prefix` of the two shardchains. Finally, messages are routed between shardchains by moving them along the edges of such hypercube.\n\nAs a simple example, consider a workchain that has eight shardchains with `shard_prefix` equal to `000`, `001`, `010`, `011`, `100`, `101`, `110`, and `111`. These shardchains can be represented as vertices of a three-dimensional cube, where two shardchains are connected by an edge if their `shard_prefix` differ by exactly one bit. Thus, a message from `001` shardchain to `110` shardchain will be routed along the edges of the cube following the path `001 -> 101 -> 111 -> 110`. Hence, there are three hops between `001` and `110` shardchains.\n\n<Image\n  src=\"/resources/images/hypercube_routing.png\"\n  alt=\"Hypercube routing\"\n/>\n\nTON Blockchain uses a more complex version. The hypercube has `15` dimensions, and each shardchain has up to `16` neighboring shardchains (include itself) along each dimension. Hence, each shardchain has up to `16 * 15 = 240` neighboring shardchains in total and the maximum number of hops between any two shardchains in the same workchain is `15`. If the source and destination shardchains belong to different workchains, then an additional hop between workchains is needed.\n\nThe hypercube routing mechanism also has some additional features to ensure reliability and efficiency of message delivery, such as preventing double delivery of messages, processing messages in order of their logical time creation, and so on. For a detailed acquaintance with these processes, the reader can refer to the [TON Blockchain whitepaper](/foundations/whitepapers/tblkch#2-2-hypercube-routing-protocol).\n"
  },
  {
    "path": "foundations/status.mdx",
    "content": "---\ntitle: \"Account status\"\n---\n\nimport { Image } from '/snippets/image.jsx';\n\nThis article describes the four possible states of an account on TON Blockchain.\nUnderstanding these states is crucial for accurately predicting transaction outcomes and ensuring the correct deployment.\n\n## What is the account status?\n\nThe account status is a formal indicator of what actions can occur with an account, what it can store, and whether it contains a contract code. In other words, it is one of the main factors determining the behavior of a given account during a transaction. The account status at the beginning and end of a transaction is recorded in [the corresponding TL-B block](https://github.com/ton-blockchain/ton/blob/cac968f77dfa5a14e63db40190bda549f0eaf746/crypto/block/block.tlb#L285) in the fields `orig_status` and `end_status`. Thus, it allows developers to always view the current status of an account before sending it a message and restore the history of its status changes.\n\n## Status variety\n\nEach account exists in one of the following statuses:\n\n- **nonexist**: the default status for accounts with no transaction history or that were deleted. Contains no code, data, or balance. All 2<sup>256</sup> accounts start in this status.\n- **uninit**: holds a balance and metadata, but no code and persistent data. It cannot execute logic but retains funds (and accumulates the storage fee) until the contract code is deployed.\n- **active**: contains code, data, and a balance. Fully deployed and operational, capable of processing messages.\n- **frozen**: occurs when the storage debt of an active account exceeds 0.1 TON. Only the hashes of the previous code and data cells are preserved. While frozen, the contract cannot be executed. To unfreeze, send a message with the valid [`StateInit`](/foundations/messages/deploy) and sufficient funds for storage fees. Recovery is complex; avoid reaching this state. A project to unfreeze accounts is available [here](https://unfreezer.ton.org/).\n\n### Why exactly these four statuses?\n\nAlthough the need for the `active` and `nonexist` statuses is obvious, the purpose of the `uninit` and `frozen` statuses is not immediately clear.\n\n**`nonexist` vs `uninit`**:\n\nAs was mentioned above, each account starts in the `nonexist` status. Besides code and persistent data, in this status, an account also has no [metadata](https://github.com/ton-blockchain/ton/blob/cac968f77dfa5a14e63db40190bda549f0eaf746/crypto/block/block.tlb#L258), so it does not accumulate the storage fee. At the same time, the `uninit` status of an account indicates that some actions were performed with it and, possibly, it is prepared for deployment. So, the `uninit` account always has a [positive balance and some additional information](https://github.com/ton-blockchain/ton/blob/cac968f77dfa5a14e63db40190bda549f0eaf746/crypto/block/block.tlb#L259-L260) for which it must pay a storage fee.\n\nSending an internal message with a valid `state_init` and proper `value` to `nonexist` account results in its deployment and the status changes to `active`. The key point is that the deployment occurs during the compute phase, which requires a suitable number of nanotons to run. But often you want to be able to deploy an account through an **external message**, to which you can also attach `state_init`, but it is impossible to attach `value`! This is also the purpose for which `uninit` exists. You can initially transfer the balance to the account via an internal message, notifying the rest of the blockchain participants of your intention to deploy an account in the future. And only then, including through an external message, to deploy.\n\n**`frozen` vs `uninit`**:\n\nWhen the active account's storage debt exceeds 0.1 TON, it becomes `frozen` or `uninit`. It is possible to restore the account from these statuses by paying off the debt and attaching `state_init`. If the account code and its persistent data have not changed during the lifetime of the account, then there is no problem restoring it from `uninit`. But what if they have changed? Since the `uninit` status does not allow you to store any information about the account's history, its last state will be lost forever. To prevent such situations, the `frozen` status exists.\n\nThe main difference between the `uninit` and `frozen` statuses is that in addition to metadata, the `frozen` account contains hash of the [last account state](https://github.com/ton-blockchain/ton/blob/cac968f77dfa5a14e63db40190bda549f0eaf746/crypto/block/block.tlb#L268). Thus, it becomes possible to restore the last state of an account before it was frozen by sending a `state_nint` to it, whose hash matches the one recorded on the account.\n\n## Status transitions\n\nWe present here a diagram that describes all potential changes in the account status during the receipt of internal or external messages.\n\n### Diagram\n\nIn the diagram below, there are four nodes representing the four different account statuses. Each arrow and loop corresponds to a change in the account status at the end of a given transaction. The parameters in the blocks above the arrows (and loops) briefly describe what caused the transaction and also contain some fields that affect the change in the account status.\n\n<Image\n  src=\"/resources/images/statuses-light.svg\"\n  darkSrc=\"/resources/images/statuses-dark.svg\"\n  alt=\"Status changes diagram\"\n/>\n\nSo, let's look at what changes can occur to a `nonexist` account depending on the messages that come to it.\n\n- **Receiving external messages**: no changes.\n- **Receiving internal messages**:\n  - **With a valid `state_init` and sufficient value**: the contract is deployed on its address that becomes `active` before processing the message.\n  - **Without/with invalid `state_init` or with insufficient value**: if the message is **bounceable**, then it returns to the sender, and the account status isn't changed. Otherwise, with no `value` in the message, the account status isn't changed. Finally, it becomes `uninit` if it received a valid `state_init` but insufficient nanotons or if `state_init` is absent or invalid.\n\nWith the diagram **Legend** below, you can inspect all possible changes in the account status when receiving messages with different parameters.\n\n### Legend\n\n- `type`: message type.\n  - any;\n  - internal;\n  - external;\n- `bounce`: `bounce` flag of an internal message.\n  - any;\n  - true;\n  - false;\n- `value`: an amount of nanotons in a message.\n  - any;\n  - 0;\n  - \\> 0.\n- `state_init`: [`StateInit`](/foundations/messages/deploy) structure.\n  - any;\n  - none;\n  - invalid: the address computed from a given `state_init` does not match the recipient address;\n  - valid: the computed address matches a recipient address;\n  - valid last state: must be `state_init` of the last successful transaction before the account becomes frozen.\n- `balance`: The account balance in nanotons after **Storage phase** of the transaction.\n  - 0;\n  - \\> 0;\n  - \\< 40000;\n  - \\>= 40000;\n  - (0, 40000).\n- `storage_fees_due`: the number of storage fees that were charged but could not be collected. In the diagram, this field indicates `storage_fees_due` after the **Storage phase**.\n  - 0;\n  - \\< 0.1;\n  - \\< 1;\n  - \\>= 0.1;\n  - \\>= 1.\n- `send_dest_if_zero`: is there any outgoing message with flag 32 in **Action phase**?\n  - any;\n  - false;\n  - true;\n  - invalid: there was no **Action phase**.\n- `zero_bal_after_dest_act`: Whether the account balance became zero when sending some of the messages with the flag 32. This field is meaningful only if there's at least one such message during **Action phase**.\n  - any;\n  - false;\n  - true.\n- `action_phase_is_successful`: was **Action phase** successful?\n  - false;\n  - true.\n- `account_state_changed`: has the account's state changed during its lifetime?\n  - false;\n  - true.\n\n### Key points\n\nWe additionally review some important points regarding the statuses except `nonexist`.\n\n**Sending to `uninit` account**:\n\n- **Messages of any type without `state_init`**: changes to `nonexist` if its balance becomes zero.\n- **Messages of any type with valid `state_init`**: changes to `active` if the balance is at least 40000 nanotons.\n\n**Sending to `frozen` account**:\n\n- **Messages of any type**: Changes to `nonexist` if its `storage_fees_due` exceeds 1 TON and the balance is zero.\n- **Internal message with valid `state_init` (non-bounceable)**: changes to `active` if its `storage_fees_due` becomes zero.\n- **Internal message with valid `state_init` (bounceable)**: changes to `active` with the same debt, and the account balance equals the message's balance minus compute and action fees.\n\n**Sending to `active` account**:\n\n- **Messages of any type**: changes to `frozen` if its `storage_fees_due` exceeds 0.1 TON and the account's state has ever changed.\n- **Messages of any type**: changes to `uninit` if its `storage_fees_due` exceeds 0.1 TON and the account's state has never changed.\n- **Messages of any type**: if in the action list there is an outgoing message with the flag 32 but **Action phase** was unsuccessful or the balance after this action is positive, the account status doesn't change.\n- **Messages of any type with any `state_init`**: new `state_init` will be ignored and therefore doesn't change the account status.\n\n**Deployment strategy**: The standard practice for deploying a wallet is to first send a non-bounceable message with Toncoin to its address. This transitions the account to the `uninit` status. The wallet owner can then deploy the contract in a subsequent transaction, using the pre-funded balance.\n\n**Protection against errors**: standard wallets and applications manage these complexities by automatically setting the `bounce` flag based on the status of the destination account. Developers of custom applications must implement similar logic to prevent fund loss.\n\n## Summary\n\n- The account status (`nonexist`, `uninit`, `active`, `frozen`) defines behavior.\n- Correct handling of `state_init` and the `bounce` flag is crucial for successful deployment and avoiding unintended fund transfers.\n- There are many cases when the account status can become `nonexist` or `frozen`. Keep track of the amount of TON on the account balance!\n- Each new `state_init` is ignored when the account status is active.\n"
  },
  {
    "path": "foundations/system.mdx",
    "content": "---\ntitle: \"System contracts\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\n\n<Aside>\n  These are low-level TON Blockchain internals. You typically do not need to write or deploy these contracts.\n</Aside>\n\n<Aside>\n  System contracts are smart contracts and have on‑chain addresses. See [config parameters 1–4](https://tonviewer.com/config). The Config account stores the Config contract address. To track changes, review proposals to the Config contract.\n</Aside>\n\nIn TON, a set of special smart contracts controls consensus parameters for node operation — including TVM, catchain, fees, and chain topology — and how these parameters are stored and updated. Unlike older blockchains that hardcode these parameters, TON enables transparent on‑chain governance. The current governance contracts include the **Elector** and **Config** contracts, with expansion plans (for example, the extra‑currency **Minter**).\n\n## Elector\n\nThe **Elector** smart contract manages validator elections, validation rounds, and reward distribution. To become a validator and interact with the Elector, follow the [validator instructions](https://ton.org/validator).\n\n### Data storage\n\nThe Elector stores:\n\n- Non-withdrawn Toncoin in the `credits` hashmap.\n- New validator applications in the `elect` hashmap.\n- Past election data in the `past_elections` hashmap (including complaints and `frozen` stakes held for `stake_held_for` periods, defined in [**ConfigParam 15**](https://tonviewer.com/config#15)).\n\n### Key functions\n\n1. **Process validator applications**\n1. **Conduct elections**\n1. **Handle validator misbehavior reports**\n1. **Distribute validation rewards**\n\n#### Processing applications\n\nTo apply, a validator must:\n\n1. Send a message to the Elector with their Abstract Datagram Network Layer (ADNL) address, public key, `max_factor`, and stake (TON amount).\n1. The Elector validates the parameters and either registers the application or refunds the stake.\n   _Note:_ Only masterchain addresses can apply.\n\n### Conducting elections\n\nThe Elector is a special smart contract triggered by **Tick and Tock transactions** (forced executions at the start and end of each block). It checks whether it’s time to conduct a new election during each block.\n\n**Process details:**\n\n- Take applications with stake ≥ `min_stake` ([**ConfigParam 17**](https://tonviewer.com/config#17)).\n- Arrange candidates by stake in descending order.\n- If applicants exceed `max_validators` ([**ConfigParam 16**](https://tonviewer.com/config#16)), discard the lowest-staked candidates.\n- For each subset size `i` (from 1 to remaining candidates):\n- Assume the `i`-th candidate (lowest in the subset) defines the baseline.\n- Calculate effective stake (`true_stake`) for each `j`-th candidate (`j < i`) as:\n\n```python not runnable\nmin(stake[i] * max_factor[j], stake[j])\n```\n\n- Track the subset with the highest **total effective stake (TES)**.\n- Submit the winning validator set to the **Config** contract.\n- Return unused stakes and excess amounts (e.g., `stake[j] - min(stake[i] * max_factor[j], stake[j])`) to `credits`.\n\n**Example breakdown**:\n\n- **Case 1**: 9 candidates stake 100,000 TON (`max_factor=2.7`), 1 candidate stakes 10,000.\n\n- _Without the 10,000-stake candidate_: TES = 900,000.\n\n- _With the 10,000-stake candidate_: TES = 9 \\* 27,000 + 10,000 = 253,000.\n\n- **Result**: 10,000-stake candidate are excluded.\n\n- **Case 2**: 1 candidate stakes 100,000-stake (`max_factor=2.7`), 9 stake 10,000.\n\n- Effective stake for the 100,000-stake candidate: `10,000 * 2.7 = 27,000`.\n\n- Excess: `100,000 - 27,000 = 73,000` → sent to `credits`.\n\n- **Result**: All 10 participate.\n\n**Election constraints**:\n\n- `min_validators` ≤ participants ≤ `max_validators` (**ConfigParam 16**).\n- Stakes must satisfy:\n- `min_stake` ≤ stake ≤ `max_stake`\n- `min_total_stake` ≤ total stake ≤ `max_total_stake`\n- Stake ratios ≤ `max_stake_factor` (**ConfigParam 17**).\n- If conditions aren’t met, elections are **postponed**.\n\n### Report validator misbehavior\n\nEach validator is periodically assigned the duty to create new blocks, with the frequency of assignments determined by their weight. After a validation round, anyone can audit the blocks to check whether the actual number of blocks produced by a validator significantly deviates from the expected number (based on their weight). A statistically significant underperformance (e.g., fewer blocks created than expected) constitutes misbehavior.\n\nTo report misbehavior, a user must:\n\n1. Generate a **Merkle proof** demonstrating the validator's failure to produce the expected blocks.\n1. Propose a fine proportional to the severity of the offense.\n1. Submit the proof and fine proposal to the Elector contract, covering the associated storage costs.\n\nThe Elector registers the complaint in the `past_elections` hashmap. Current round validators then verify the complaint. If the proof is valid and the proposed fine aligns with the severity of the misbehavior, validators vote on the complaint. Approval requires agreement from over **two-thirds of the total validator weight** (not just a majority of participants).\n\nThe fine is deducted from the validator's `frozen` stake in the relevant `past_elections` record if approved. These funds stay locked for the period defined by [**ConfigParam 15**](https://tonviewer.com/config#15) (`stake_held_for`).\n\n#### Distributing rewards\n\nThe Elector releases `frozen` stakes and rewards (gas fees plus block rewards) proportionally to past validators. Funds move to `credits`, and the election record clears from `past_elections`.\n\n## Config\n\nThe **Config** contract manages TON’s configuration parameters, validator set updates, and proposal voting.\n\n### Validator set updates\n\n1. The **Elector** notifies **Config** of a new validator set.\n1. **Config** stores it in `ConfigParam 36` (_next validators_).\n1. At the scheduled time (`utime_since`), **Config**:\n\n- Moves the old set to `ConfigParam 32` (_previous validators_).\n- Promotes `ConfigParam 36` to `ConfigParam 34` (_current validators_).\n\n### Proposal/voting mechanism\n\n1. **Submit a proposal**: Pay storage fees to propose parameter changes.\n1. **Vote**: Validators (from **ConfigParam 34**) sign approval messages.\n1. **Outcome**:\n\n- **Approved**: After `min_wins` rounds (**ConfigParam 11**) with ≥3/4 weighted votes.\n- **Rejected**: After `max_losses` rounds.\n- _Critical parameters_ (**ConfigParam 10**) require more rounds.\n\n#### Emergency updates\n\n- Reserved indexes (`-999`, `-1000`, `-1001`) allow urgent updates to **Config**/**Elector** code.\n- A temporary emergency key (assigned to the TON Foundation in 2021) accelerated fixes but couldn't alter contracts.\n- **Key retired** on Nov 22, 2023 (**block 34312810**), replaced with zeros.\n- Later patched to a fixed byte sequence (`sha256(\"Not a valid curve point\")`) to prevent exploits.\n\n**Historical uses**:\n\n- **Apr 2022**: Increased gas limits (**blocks 19880281/19880300**) to unblock elections.\n- **Mar 2023**: Raised `special_gas_limit` to 25M (**block 27747086**) for election throughput.\n"
  },
  {
    "path": "foundations/traces.mdx",
    "content": "---\ntitle: \"Traces\"\n---\n\nimport { Image } from '/snippets/image.jsx';\n\nA trace is a partially ordered set of messages. This set includes all dependent messages. In other words, if message B was sent while message A was being processed, then both of these messages belong to exactly one trace. Strictly speaking, this set is partially ordered according to the causal relation “A is sent as a result of processing B.”\n\nWhen drawing a trace, messages are usually drawn on the edges, and the addresses of the accounts to which the messages are sent are drawn at the vertices. Transactions that occurred on the account at that moment in time are also usually signed at the vertex.\n\n### Start of the trace\n\nMost often, a trace begins with an [external message](/foundations/messages/external-in). It is the first one, since there is no message that could generate an external-in. However, trace may be started not only by external messages but also by [tick-tock transactions](/foundations/messages/overview#transactions), commonly used within TON Blockchain [system contracts](/foundations/system). Traces can also start with split and merge transactions, but since they are not currently implemented, this will not occur in a real network.\n\n<div\n  className=\"flex justify-center my-4\"\n>\n  <Image\n    src=\"/resources/images/rpc/trace_def_light.png\"\n    darkSrc=\"/resources/images/rpc/trace_def_dark.png\"\n    alt=\"Trace diagram\"\n  />\n</div>\n\nAs a result, messages in the trace are partially ordered by their [logical time (lt)](/foundations/whitepapers/tblkch#1-4-1-logical-time), reflecting their logical dependencies. The diagram shows transactions on independent accounts, each triggered by an incoming message, with `lt` values indicated for every message. It is important to note that in the network in general, lt is formed as follows:\n\n- lt transactions = lt incoming message + 1\n- lt outgoing message = lt transaction + outgoing message index\n  This scheme is not applicable to the first vertex if the trace is started by special transactions mentioned above, as in that case there is no `incoming message` for the first vertex.\n\n<Image\n  src=\"/resources/images/rpc/traces_lt_light.png\"\n  darkSrc=\"/resources/images/rpc/traces_lt_dark.png\"\n  alt=\"Traces with logical time\"\n/>\n\n## Traces representation in Tonviewer\n\nIn [Tonviewer](https://tonviewer.com/), traces are visualized as [directed acyclic graphs (DAGs)](https://en.wikipedia.org/wiki/Directed_acyclic_graph), where _transactions are nodes_ and _messages are edges_, showing the full sequence of account state changes.\n\n## Examples\n\nThe NFT transfer illustrates a single operation that consists of multiple messages. To learn how to read traces, follow [this article](/ecosystem/explorers/tonviewer#steps-to-read-a-trace).\n\nThis trace is started with an external message and can be inspected in [Tonviewer](https://tonviewer.com/transaction/47d0989633fc03ff3fdca05880ab5760d0321c196501a6a4cbb5578dea2624cb)\n\n<Image\n  src=\"/resources/images/rpc/nft_transfer_trace_light.png\"\n  darkSrc=\"/resources/images/rpc/nft_transfer_trace_dark.png\"\n  alt=\"NFT transfer trace\"\n/>\n\nHere is the [example](https://tonviewer.com/transaction/9effb91e18be732033fe6aa8c39941f26f5e9566848bc487aa7c6bfecdd9d89d) of the trace that started with tick-tock transaction\n\n<Image\n  src=\"/resources/images/rpc/tick_tock_initiated_trace_light.png\"\n  darkSrc=\"/resources/images/rpc/tick_tock_initiated_trace_dark.png\"\n  alt=\"Trace initiated by tick-tock transaction\"\n/>\n\n## Access using API\n\nTo fetch traces data, use the [`GET /traces`](/ecosystem/api/toncenter/v3/actions-and-traces/get-traces) endpoint. This method allows finding a trace if any of its parameters are known.\n"
  },
  {
    "path": "foundations/whitepapers/catchain.mdx",
    "content": "---\ntitle: \"Catchain consensus: an outline\"\nsidebarTitle: \"Catchain consensus\"\ndescription: \"Whitepaper by Dr. Nikolai Durov\"\n---\n\n**Authors**: Nikolai Durov <br />\n**Date**: February 19, 2020 <br />\n<Icon icon=\"file-pdf\" size={16} />: [Original whitepaper, PDF](/resources/pdfs/catchain.pdf)\n\n## Abstract\n\nThe aim of this text is to provide an outline of the Catchain Consensus Protocol, a Byzantine Fault Tolerant (BFT) protocol specifically crafted for [block generation and validation in the TON Blockchain](/foundations/whitepapers/ton#2-6-creating-and-validating-new-blocks). This protocol can potentially be used for purposes other than block generation in a proof-of-stake (PoS) blockchain; however, the current implementation uses some optimizations valid only for this specific problem.\n\n## 1   Overview\n\nThe Catchain Consensus protocol builds upon the overlay network construction protocol and the [overlay network broadcast protocol of TON Network](/foundations/whitepapers/ton#3-3-overlay-networks-and-multicasting-messages). The Catchain Consensus protocol itself can be decomposed into two separate protocols, one more low-level and general-purpose (the _Catchain protocol_<a id=\"ref-fn1\" /><sup>[1](#fn1)</sup>), and the other the high-level _Block Consensus Protocol (BCP)_, which makes use of the Catchain protocol. Higher levels in the TON protocol stack are occupied by the block generation and validation levels; however, all of them are executed essentially locally on one (logical) machine, with the problem of achieving consensus on the newly-generated block delegated to the Catchain protocol level.\n\nHere is an approximate diagram of the protocol stack employed by TON for block generation and distribution, showing the correct place of the Catchain Consensus protocol (or rather its two component protocols):\n\n- _Top-level:_ Block generation and block validation software, logically running on a stand-alone logical machine, with all the inputs provided and outputs handled by the lower-level protocols. The job of this software is to either generate a new valid block for a blockchain ([a shardchain or the masterchain of the TON Blockchain](/foundations/whitepapers/ton#2-1-1-list-of-blockchain-types)), or to check the validity of a block generated by somebody else.\n\n- _(TON) Block consensus protocol:_ Achieves (byzantine fault tolerant) consensus on the block to be accepted as the next one in the current validator group for the masterchain or a shardchain. This level makes use of (the abstract interface of) the block generation and validation software, and builds upon the lower-level Catchain protocol. This protocol is explained in more detail in [Block Consensus Protocol](#3-block-consensus-protocol).\n\n- _Catchain protocol:_ Provides secure persistent broadcasts in an overlay network (e.g., the task group of validators for a specific shardchain or the masterchain dedicated to generation, validation, and propagation of new blocks in this shardchain or masterchain), and detects attempts of \"cheating\" (protocol violation) on the part of some participants. This protocol is explained in more detail in [Catchain Protocol](#2-catchain-protocol).\n\n- _(TON Network) overlay broadcast protocol:_ A simple best-effort broadcast protocol for [overlay networks in the TON Network](/foundations/whitepapers/ton#3-3-overlay-networks-and-multicasting-messages). Simply broadcasts received broadcast messages to all neighbors in the same overlay network that did not receive a copy of these messages before, with minimal effort dedicated to keeping copies of undelivered broadcast messages for a short period of time.\n\n- _(TON Network) overlay protocol:_ Creates [overlay networks](/foundations/whitepapers/ton#3-3-1-overlay-networks) inside the ADNL protocol network, manages neighbor lists for these overlay networks. Each participant of an overlay network tracks several neighbors in the same overlay network and keeps dedicated ADNL connections (called \"channels\") to them, so that incoming messages can be efficiently broadcast to all neighbors with minimal overhead.\n\n- _Abstract Datagram Network Layer (ADNL) protocol:_ The basic protocol of the TON Network, that delivers packets (datagrams) between network nodes identified only by 256-bit abstract (ADNL) addresses, which effectively are cryptographic keys (or their hashes).\n\nThis text aims to describe only the second and the third protocol in this suite, namely, the (TON) block consensus protocol and the (TON) Catchain protocol.\n\nWe would like to point out here that the author of this text, while providing the general guidelines of how this protocol should be designed (on the lines of \"let's create a BFT-hardened group broadcast message system, and run a suitably adapted simple two-phase or three-phase commit protocol on top of this system\") and participating in several discussions during the development and implementation of the protocol, is definitely not the only designer of this protocol and especially of its current implementation. This is the work of several people.\n\nA few words on the efficiency of the combined Catchain Consensus protocol. Firstly, it is a true Byzantine Fault Tolerant (BFT) protocol, in the sense that it eventually achieves consensus on a valid next block of the blockchain even if some participants (validators) exhibit arbitrarily malicious behavior, provided these malicious participants are less than one third of the total number of the validators. It is well-known that achieving BFT consensus is impossible if at least one third of participants are malicious <sup>[\\[5\\]](#references)</sup>, so the Catchain Consensus protocol is as good as theoretically possible in this respect. Secondly, when the Catchain Consensus was first implemented (in December 2018) and tested on up to 300 nodes distributed all over the world, it achieved consensus on a new block in 6 seconds for 300 nodes and in 4–5 seconds for 100 nodes (and in 3 seconds for 10 nodes), even if some of these nodes fail to participate or exhibit incorrect behavior.<a id=\"ref-fn2\" /><sup>[2](#fn2)</sup> Since the TON Blockchain task groups are not expected to consist of more than a hundred validators (even if a total of a thousand or ten thousand validators are running, only a hundred of them with the largest stakes will generate new masterchain blocks, and the others will participate only in the creation of new shardchain blocks, each shardchain block generated and validated by 10–30 validators; of course, all numbers given here are configuration parameters ([TON whitepaper](/foundations/whitepapers/ton#2-1-21-configurable-parameters) and [TON Blockchain specification](/foundations/whitepapers/tblkch#1-6-configurable-parameters-and-smart-contracts)) and can be adjusted later by a consensus vote of validators if necessary), this means that the TON Blockchain is able to generate new blocks once every 4–5 seconds, as originally planned. This promise has been further tested and found out to be fulfilled with the launch of the Test Network of the TON Blockchain a couple of months later (in March 2019). Therefore, we see that the Catchain Consensus protocol is a new member of the ever-growing family of practical BFT protocols <sup>[\\[2\\]](#references)</sup>, even though it is based on slightly different principles.\n\n## 2  Catchain Protocol\n\nWe have already explained in the [Overview](#1-overview) that the BFT consensus protocol used by the TON Blockchain for achieving consensus on new blockchain blocks consists of two protocols. We provide here a brief description of the _Catchain protocol_, the lower-level of these two protocols that could be potentially used for purposes other than BFT consensus for blocks. The source code for the Catchain protocol resides in subdirectory $\\texttt{catchain}$ of the source tree.\n\n### 2.1. Prerequisites for running the Catchain protocol\n\nThe main prerequisite for running (an instance of) the Catchain protocol is the ordered list of all nodes that are participating (or allowed to participate) in this specific instance of the protocol. This list consists of public keys and ADNL addresses of all participating nodes. It has to be provided from the outside when an instance of the Catchain protocol is created.\n\n### 2.2. Nodes participating in the block consensus protocol\n\nFor the specific task of creating new blocks for one of the blockchains (i.e., the masterchain or one of the active shardchains) of the TON Blockchain, a special task group consisting of several validators is created. The list of members of this task group is used both to create a private overlay network inside ADNL (this means that the only nodes that can join this overlay network are those explicitly listed during its creation) and to run the corresponding instance of the Catchain protocol.\n\nThe construction of this list of members is the responsibility of the higher levels of the overall protocol stack (the block creation and validation software) and therefore is not the topic of this text ([Examples of configurable parameters](/foundations/whitepapers/tblkch#1-6-configurable-parameters-and-smart-contracts) would be a more appropriate reference). It is sufficient to know at this point that this list is a deterministic function of the current (most recent) masterchain state (and especially of the current value of the configuration parameters, such as the active list of all validators elected for creating new blocks along with their respective weights). Since the list is computed deterministically, all validators compute the same lists and in particular each validator knows in which task groups (i.e., instances of the Catchain protocol) it participates without any further need for network communication or negotiation.<a id=\"ref-fn3\" /><sup>[3](#fn3)</sup>\n\n#### 2.2.1. Catchains are created in advance\n\nIn fact, not only the current values of the lists alluded to above are computed, but also their immediately subsequent (future) values are computed as well, so that the Catchain is usually created in advance. In this way it is already in place when the first block has to be created by the new instance of the validator task group.\n\n### 2.3. The genesis block and the identifier of a catchain\n\nA _catchain_ (i.e., an instance of the Catchain protocol) is characterized by its _genesis block_ or _genesis message_. It is a simple data structure containing some magic numbers, the purpose of the catchain (e.g., the identifier of the shardchain, for which the blocks will be generated, and the so-called _catchain sequence number_, also obtained from the masterchain configuration and used to distinguish subsequent instances of the catchain generating \"the same\" shardchain, but possibly with different participating validators), and, most importantly, the list of all participating nodes (their [ADNL addresses and Ed25519 public keys](#2-1-prerequisites-for-running-the-catchain-protocol)). The Catchain protocol itself uses only this list and the SHA-256 hash of the overall data structure; this hash is used as an internal identifier of the catchain, i.e., of this specific instance of the Catchain protocol.\n\n#### 2.3.1. Distribution of the genesis block\n\nNote that the genesis block is not distributed among the participating nodes; it is rather [computed independently](#2-2-nodes-participating-in-the-block-consensus-protocol) by each participating node. Since the hash of the genesis block is used as the [catchain identifier](#2-3-the-genesis-block-and-the-identifier-of-a-catchain), if a node (accidentally or intentionally) computes a different genesis block, it will be effectively locked out from participating in the \"correct\" instance of the protocol.\n\n#### 2.3.2. List of nodes participating in a catchain\n\nNote that the (ordered) list of nodes participating in a catchain is fixed in the genesis block and hence it is known to all the participants and it is unambiguously determined by the hash of the genesis block (i.e., the catchain identifier)), provided there are no (known) collisions for SHA-256. Therefore, we fix the number of participating nodes $N$ in the discussion of one specific catchain below, and assume that the nodes are numbered from $1$ to $N$ (their real identities may be looked up in the list of participants using this index in range $1 \\ldots N$). The set of all participants will be denoted by $I$; we assume that $I = \\{1 \\ldots N\\}$.\n\n### 2.4. Messages in a catchain. Catchain as a process group\n\nOne perspective is that a catchain is a _(distributed) process group_ consisting of $N$ known and fixed _(communicating) processes_ (or _nodes_ in the preceding terminology), and these processes generate _broadcast messages_, that are eventually broadcast to all members of the process group. The set of all processes is denoted by $I$; we usually assume that $I = \\{1 \\ldots N\\}$. The broadcasts generated by each process are numbered starting from one, so the $n$-th broadcast of process $i$ will receive _sequence number_ or _height_ $n$; each broadcast should be uniquely determined by the identity or the index $i$ of the originating process and its height $n$, so we can think of the pair $(i,n)$ as the natural identifier of a broadcast message inside a process group.<a id=\"ref-fn4\" /><sup>[4](#fn4)</sup> The broadcasts generated by the same process $i$ are expected to be delivered to every other process in exactly the same order they have been created, i.e., in increasing order of their height. In this respect a catchain is very similar to a process group in the sense of <sup>[\\[1\\]](#references)</sup> or <sup>[\\[7\\]](#references)</sup>. The principal difference is that a catchain is a \"hardened\" version of a process group tolerant to possible Byzantine (arbitrarily malicious) behavior of some participants.\n\n#### 2.4.1. Dependence relation on messages\n\nOne can introduce a _dependence relation_ on all messages broadcast in a process group. This relation must be a strict partial order $\\prec$, with the property that $m_{i,k} \\prec m_{i,k+1}$, where $m_{i,k}$ denotes the $k$-th message broadcast by group member process with index $i$. The meaning of $m \\prec m'$ is that _$m'$ depends on $m$_, so that the (broadcast) message $m'$ can be processed (by a member of the process group) only if $m$ has been processed before. For instance, if the message $m'$ represents the reaction of a group member to another message $m$, then it is natural to set $m \\prec m'$. If a member of the process group receives a message $m'$ before all its dependencies, i.e., messages $m \\prec m'$, have been processed (or _delivered_ to the higher-level protocol), then its processing (or _delivery_) is delayed until all its dependencies are delivered.\n\nWe have defined the dependence relation to be a strict partial order, so it must be transitive ($m'' \\prec m'$ and $m' \\prec m$ imply $m'' \\prec m$), antisymmetric (at most one of $m' \\prec m$ and $m \\prec m'$ can hold for any two messages $m$ and $m'$) and anti-reflexive ($m \\prec m$ never holds). If we have a smaller set of \"basic dependencies\" $m' \\to m$, we can construct its transitive closure $\\to^+$ and put $\\prec := \\to^+$. The only other requirement is that every broadcast of a sender depends on all previous broadcasts of the same sender. It is not strictly necessary to assume this; however, this assumption is quite natural and considerably simplifies the design of a messaging system inside a process group, so the Catchain protocol makes this assumption.\n\n#### 2.4.2. Dependence set or cone of a message\n\nLet $m$ be a (broadcast) message inside a process group as above. We say that the set $D_m := \\{m' : m' \\prec m\\}$ is the _dependence set_ or _dependence cone_ of message $m$. In other words, $D_m$ is the _principal ideal_ generated by $m$ in the partially ordered finite set of all messages. It is precisely the set of all messages that must be delivered before $m$ is delivered.\n\n#### 2.4.3. Extended dependence cone of a message\n\nWe also define $D^+_m$, the _extended dependence cone of $m$_, by $D^+_m := D_m \\cup \\{m\\}$.\n\n#### 2.4.4. Cones, or ideals with respect to $\\prec$\n\nMore generally, we say that a subset $D$ of messages is a _cone_ if it is an ideal with respect to the dependence relation $\\prec$, i.e., if $m \\in D$ and $m' \\prec m$ imply $m' \\in D$. Of course, the dependence cone $D_m$ and the extended dependence cone $D^+_m$ of any message $m$ are cones (because any principal ideal in a partially ordered set is an ideal).\n\n#### 2.4.5. Identification of cones with the aid of vector time\n\nRecall that we have assumed that any message depends on all preceding messages of the same sender, i.e. $m_{i,s} \\prec m_{i,s+1}$ for any $i \\in I$ and any $s > 0$, such that $m_{i,s+1}$ exists. This implies that any cone $D$ is completely characterized by $N$ values $\\text{Vt}(D)_i$ indexed by $i \\in I$:\n\n$$\n\\text{Vt}(D)_i := \\sup\\{s \\in \\mathbb{N} : m_{i,s} \\in D\\} = \\inf\\{s \\in \\mathbb{N}_0 : m_{i,s+1} \\not\\in D\\} \\tag{1}\n$$\n\n(if no message $m_{i,s}$ is in $D$, we set $\\text{Vt}(D)_i := 0$). Indeed, it is clear that\n\n$$\nm_{i,s} \\in D \\Leftrightarrow s \\leq \\text{Vt}(D)_i \\tag{2}\n$$\n\nWe say that the vector $\\text{Vt}(D) = (\\text{Vt}(D)_i)_{i \\in I} \\in \\mathbb{N}_0^I$ with non-negative components $\\text{Vt}(D)_i$ is the _vector time_ or _vector timestamp_ corresponding to cone $D$ (<sup>[\\[1\\]](#references)</sup> or <sup>[\\[7\\]](#references)</sup> for a more detailed discussion of vector time).\n\n#### 2.4.6. Partial order on vector timestamps\n\nWe introduce a partial order $\\leq$ on the set of all possible vector times $\\mathbb{N}_0^I$, which is the product of the usual orders on $\\mathbb{N}_0$:\n\n$$\n\\mathbf{x} = (x_i)_{i \\in I} \\leq \\mathbf{y} = (y_i)_{i \\in I} \\quad \\text{iff} \\quad x_i \\leq y_i \\quad \\text{for all } i \\in I \\tag{3}\n$$\n\nIt is immediate that $D \\subset D'$ iff $\\mathit{Vt}(D) \\leq \\mathit{Vt}(D')$; therefore, $\\mathit{Vt}$ is a strict order-preserving embedding of the set of all cones contained in the set of all messages into $\\mathbb{N}_0^I$.\n\n#### 2.4.7. Vector timestamp $\\text{Vt}(m)$ of a message $m$\n\nGiven any message $m$, we define its _vector timestamp_ $\\text{Vt}(m)$ as $\\text{Vt}(D_m)$. In other words, message $m$ can be delivered only after the first $\\text{Vt}(m)_j$ messages generated by process $j$ are delivered, and this is true for all $j \\in I$.\n\nIf $i$ is the sender of message $m$, and $s$ is the height of message $m$, so that $m = m_{i,s}$, then $\\text{Vt}(m)_i = s - 1$. We can define the _adjusted vector timestamp_ $\\text{Vt}^+(m)$ of message $m$ by setting $\\text{Vt}^+(m)_j = \\text{Vt}(m)_j$ for $j \\neq i$, $\\text{Vt}^+(m)_i = \\text{Vt}(m)_i + 1 = s$. Alternatively, $\\text{Vt}^+(m) = \\text{Vt}(D^+_m)$, where $D^+_m := D_m \\cup \\{m\\}$ is the [extended dependence cone of $m$](#2-4-3-extended-dependence-cone-of-a-message).\n\nNote that $m' \\preceq m$ iff $D^+_{m'} \\subset D^+_m$ iff $\\text{Vt}^+(m') \\leq \\text{Vt}^+(m)$ in $\\mathbb{N}_0^I$, where $m' \\preceq m$ means \"$m' \\prec m$ or $m' = m$\". Similarly, $m' \\prec m$ iff $D^+_{m'} \\subset D_m$ iff $\\text{Vt}^+(m') \\leq \\text{Vt}(m)$. In other words, _the dependence relation $\\prec$ on (some or all) messages is completely determined by the adjusted vector timestamps of these messages._\n\n#### 2.4.8. Using vector timestamps to correctly deliver broadcast messages\n\nVector timestamps can be used (in non-byzantine settings) to correctly deliver messages broadcast in a process group.<a id=\"ref-fn5\" /><sup>[5](#fn5)</sup> Namely, suppose that every broadcast message $m = m_{i,s}$ contains the index of its sender $i$ and the vector timestamp of this message $\\text{Vt}(m)$. Then each receiver $j$ knows whether the message can be delivered or not. For this, $j$ keeps track of the cone $C_j$ of all messages delivered so far, for example by maintaining a _current timestamp_ $\\text{Vt}(j)$ equal to $\\text{Vt}(C_j)$. In other words, $\\text{Vt}(j)_k$ is the count of messages of sender $k$ processed by $j$ so far. If $\\text{Vt}(m) \\leq \\text{Vt}(j)$, then the message $m$ is delivered immediately and $\\text{Vt}(j)$ is updated to $\\sup(\\text{Vt}(j), \\text{Vt}^+(m))$ afterwards; this is equivalent to increasing $\\text{Vt}(j)_i$ by one, where $i$ is the original sender of message $m$. If this condition is not met, then $m$ may be put into a waiting queue until $\\text{Vt}(j)$ becomes large enough. Instead of passively waiting for the required broadcasts, $j$ can construct the list of message indices $(i', s')$ that are implicitly mentioned in $\\text{Vt}(m)$ of some received but not delivered message $m$, and request messages with these indices from the neighbors from which $j$ learned about $m$ and $\\text{Vt}(m)$; an alternative strategy (actually employed by the current implementation of the Catchain protocol) is to request these messages from randomly chosen neighbors from time to time. The latter strategy is simpler because it does not require remembering the immediate sources of all received messages (which may become unavailable anyway).\n\n### 2.5. Message structure in a catchain. Catchain as a multi-blockchain\n\nThe message structure in a catchain is a bit more complicated than described above because of the necessity to support a BFT protocol. In particular, vector timestamps are not sufficient in a Byzantine setting. They have to be complemented by descriptions based on maximal elements of a dependence cone (such descriptions are typically used in non-byzantine settings only when the process group is very large, so that vector timestamp sizes become prohibitive).\n\n#### 2.5.1. Describing cones by means of their maximal elements\n\nAn alternative way (to using a vector timestamp) of describing a message cone $D$ is by listing all its _maximal elements_ $\\text{Max}(D)$, i.e. elements $m \\in D$, such that $m \\prec m'$ does not hold for any $m' \\in D$. Of course, one needs a suitable way of referring to messages without including them completely in order for this representation to be practical.\n\n#### 2.5.2. Message identifiers inside a catchain\n\nCatchain protocol uses SHA-256 hashes of (suitably serialized) messages as their unique identifiers. If we assume that there are no collisions for SHA-256 (computable in reasonable, e.g., polynomial time), then a message $m$ is completely identified within the process group by its hash $\\text{Sha256}(m)$.\n\n#### 2.5.3. Message headers\n\nThe header of a message $m = m_{i,s}$ inside a catchain (i.e., an instance of the Catchain protocol) always contains the index $i$ of its sender, the height $s$, the [catchain identifier](#2-3-the-genesis-block-and-the-identifier-of-a-catchain) and the set of hashes of maximal elements of the dependence cone of $m$, i.e., the set $\\{\\text{Sha256}(m') : m' \\in \\text{Max}(D_m)\\}$. In particular, the hash $\\text{Sha256}(m_{i,s-1})$ of the previous message of the same sender is always included since $m_{i,s-1} \\in \\text{Max}(D_m)$ if $s > 1$; for performance reasons, there is a separate field in the message header containing $\\text{Sha256}(m_{i,s-1})$. If $s = 1$, then there is no previous message, so the [hash of the genesis message](#2-3-the-genesis-block-and-the-identifier-of-a-catchain) is used instead.\n\nThe vector timestamp $\\text{Vt}(m)$ is not included in the message header; however, the header implicitly determines $\\text{Vt}(m)$ since\n\n$$\n\\text{Vt}(m) = \\sup_{m' \\in D_m} \\text{Vt}^+(m') = \\sup_{m' \\in \\text{Max}(D_m)} \\text{Vt}^+(m') \\tag{4}\n$$\n\nNote that the message header is a part of the message, and in particular the hash of a message (i.e., the message identifier) depends on all data listed in the header. Therefore, we assume that the message identifier implicitly determines all the dependencies of the corresponding message (if there are no known collisions for SHA-256).\n\n#### 2.5.4. Message signatures\n\nApart from that, every message in a catchain is signed by its creator. Since the list of participating nodes (processes) in a catchain is known in advance, and this list includes the public keys of all processes, these message signatures can be checked by a receiving process immediately after a message is received. If the signature is invalid, the message is discarded without any further processing.\n\n#### 2.5.5. Message encryption\n\nAll messages in a catchain are also encrypted before being transferred from a node to its neighbor in the private overlay network underlying the catchain. However, this encryption is performed by lower-level network protocols (such as ADNL) and is not relevant to the discussion here. We would like to mention that correct encryption is possible here only because the list of participating processes includes not only the public keys of all processes, but also their ADNL addresses (which effectively are public encryption keys for network transmission).\n\nNotice that even if the encryption had been absent, this would not violate the BFT properties of the protocol, because faking a message from another sender would not be possible because of the signatures. However, this might lead to a leak of information to outside observers, which is often undesirable.\n\n#### 2.5.6. Alternative perspective: a catchain as a multi-blockchain\n\nNote that all messages created by the same sender $i$ in a catchain turn out to have a simple \"blockchain structure\", because the header of $m_{i,s+1}$ contains the hash $\\text{Sha256}(m_{i,s})$ (among other hashes of messages from $\\text{Max}(D_{m_{i,s+1}})$) of the previous message of sender $i$. In this way each process $i$ generates a simple blockchain consisting of its messages, with each \"block\" of this blockchain corresponding to one message and referring to the previous block by its hash, and sometimes includes references to blocks (i.e., messages) of other processes by mentioning the hashes of these blocks in its blocks. Each block is signed by its creator. The resulting structure is very similar to that of an [asynchronous payment channel](/foundations/whitepapers/ton#5-ton-payments), but with $N$ participants instead of 2.\n\n### 2.6. Message propagation in a catchain\n\nNow we are ready to describe message propagation in a catchain. Namely:\n\n- The (lower-level) overlay network protocol maintains a list of neighbors in the private overlay network underlying the catchain and provides ADNL channels to each of these neighbors. This private overlay network has the same list of members (processes, nodes) as the catchain, and the neighbors of each node form an (oriented) subgraph on the set of all participating nodes. This (essentially random) subgraph is strongly connected with probability very close to one.\n\n- Each process generates some new messages from time to time (as needed by the higher-level protocol). These messages are augmented by catchain [message headers](#2-5-3-message-headers), signed, and propagated to all known neighbors using the ADNL channels established by the overlay protocol.\n\n- In contrast with the usual simple overlay broadcast protocol, the messages received from neighbors are not immediately rebroadcast to all other neighbors that are not known yet to have a copy of them. Instead, the signature is checked first, and invalid messages are discarded. Then the message is either delivered (if all its dependent messages have already been delivered), or put into a waiting queue. In the latter case, all the required messages mentioned in its header (i.e., the set $\\text{Max}(D_m)$) are pulled from the neighbor that sent this message (apart from that, attempts to download these missing messages from random neighbors are performed from time to time). If necessary, this process is repeated recursively until some messages can be delivered. Once a message is ready for local delivery (i.e., all its dependencies are already present), it is also rebroadcast to all neighbors in the overlay network.\n\n- Apart from the recursive \"pull\" mechanism described above, a faster vector timestamp-based mechanism is also used, so that messages can be queried from neighbors by their senders and heights (learned from the vector timestamps of received messages). Namely, each process sends a special query containing the current vector timestamp to a randomly chosen neighbor from time to time. This peer-to-peer query leads to its receiver sending back all or some messages unknown to the sender (judging by their vector timestamps).\n\n- This faster vector timestamp-based mechanism can be disabled for messages originating from certain senders as soon as a \"fork\" is detected, i.e., a second message with the same sender $i$ and height $s$, but with a different hash, is learned from a neighbor, for example, during the fast or slow \"pull\" process. Once a fork created by $i$ is detected, the corresponding component $\\text{Vt}_i$ of all subsequent vector timestamps is set to a special value $\\infty$ to indicate that comparing the values of these components does not make sense anymore.\n\n- When a message is delivered (to the higher-level protocol), this message is added into the cone $C$ of processed messages of the current process (and the current vector timestamp is updated accordingly), and all subsequent messages generated by the current process will be assumed to depend on all the messages delivered so far (even if this is not logically necessary from the perspective of the higher-level protocol).\n\n- If the set $\\text{Max}(C)$ of the maximal elements of the cone of processed messages becomes too large (contains more elements than a certain amount fixed in advance by the genesis message of the catchain), then the Catchain protocol asks the higher-level protocol to generate a new message (empty if no useful payload is available). After this new message is generated (and immediately delivered to the current process), $C$ is updated and $\\text{Max}(C)$ consists of only one element (the new message). In this way the size of $\\text{Max}(C)$ and therefore the size of the message header always remain bounded.\n\n- Once a message $m$ is delivered and the set $C$ is modified to include this message, a timer is set, and after some small delay the higher-level protocol is asked to create a new message (empty if necessary), so that this new message $m^*$ would refer to the new $C$, similarly to the procedure described in the previous item. This new message $m^*$ is pushed to all neighbors; since its header contains $\\text{Max}(C)$ for the new $C$, and $m \\in C$, the neighbors learn not only about the newly-generated message $m^*$, but also about the original received message $m$. If some neighbors do not have a copy of $m$ yet, they would require one (from the current process or not).\n\n- All (broadcast) messages received and created in a catchain are stored into a special local database. This is especially important for [newly-created messages](#3-3-2-flushing-new-messages-to-disk): if a message is created and sent to neighbors, but not saved into the database (and flushed to disk) before the creating process crashes and is restarted, then another message with the same sender and height can be created after restart, thus effectively leading to an involuntary \"fork\".\n\n### 2.7. Forks and their prevention\n\nOne can see that the multi-blockchain structure of a catchain outlined above (with references to other blocks by their hashes and with signatures) leaves very little possibility for \"cheating\" in a consensus protocol built upon a catchain (i.e., using the catchain as a means for broadcasting messages inside a process group). The only possibility that is not detected immediately consists of creating two (or more) different versions of the same message $m_{i,s}$ (say, $m'_{i,s}$ and $m''_{i,s}$), and sending one version of this message $m'_{i,s}$ to some peers and a different version $m''_{i,s}$ to others. If $s$ is minimal (for a fixed $i$), then this corresponds to a _fork_ in blockchain terminology: two different next blocks $m'_{i,s}$ and $m''_{i,s}$ for the same previous block $m_{i,s-1}$.\n\nTherefore, the Catchain protocol takes care to detect forks as soon as possible and prevent their propagation.\n\n#### 2.7.1. Detection of forks\n\nThe detection of forks is simple: if there are two different blocks $m'_{i,s}$ and $m''_{i,s}$ with the same creator $i \\in I$ and the same height $s \\geq 1$, and with valid signatures of $i$, then this is a fork.\n\n#### 2.7.2. Fork proofs\n\nBlock signatures in the Catchain protocol are created in such a way that creating _fork proofs_ (i.e., the proof that a process $i$ has intentionally created a fork) is especially simple since it is the hash of a very small structure (containing a magic number, the values of $i$ and $s$, and the hash of the remainder of the message) that is actually signed. Therefore, only two such small structures and two signatures are required in a fork proof.\n\n#### 2.7.3. External punishment for creating forks\n\nNotice that an external punishment for creating catchain forks may be used in the proof-of-stake blockchain generation context. Namely, the fork proofs may be submitted to a special smart contract (such as the elector smart contract of the TON Blockchain), checked automatically, and some part or all of the stake of the offending party may be confiscated.\n\n#### 2.7.4. Internal processing of forks\n\nOnce a fork (created by $i$) is detected (by another process $j$), i.e. $j$ learns about two different messages $m_{i,s}$ and $m'_{i,s}$ created by $i$ and having same height $s$ (usually this happens while recursively downloading dependencies of some other messages), $j$ starts ignoring $i$ and all of its subsequent messages. They are not accepted and not broadcast further. However, messages created by $i$ prior to the fork detection may be still downloaded if they are referred to in messages (blocks) created by processes that did not see this fork before referring to such messages created by $i$.\n\n#### 2.7.5. Accepting messages from a \"bad\" process is bad\n\nFurthermore, if process $i$ learns about a fork created by process $j$, then $i$ shows this to its neighbors by creating a new service broadcast message that contains the corresponding [fork proof](#2-7-2-fork-proofs). Afterwards, this and all subsequent messages of $i$ cannot directly depend on any messages by the known \"bad\" producer $j$ (but they still can refer to messages from another party $k$ that directly or indirectly refer to messages of $i$ if no fork by $i$ was known to $k$ at the time when the referring message was created). If $i$ violates this restriction and creates messages with such invalid references, these messages will be discarded by all honest processes in the group.\n\n#### 2.7.6. The set of \"bad\" group members is a part of the intrinsic state\n\nEach process $i$ keeps its own copy of the set of known \"bad\" processes in the group, i.e., those processes that have created at least one fork or have [violated](#2-7-5-accepting-messages-from-a-“bad”-process-is-bad). This set is updated by adding $j$ into it as soon as $i$ learns about a fork created by $j$ (or about a [violation](#2-7-5-accepting-messages-from-a-“bad”-process-is-bad) by $j$); after that, a callback provided by the higher-level protocol is invoked. This set is used when a new broadcast message arrives: if the sender is bad, then the message is ignored and discarded.\n\n## 3   Block Consensus Protocol\n\nWe explain in this section the basic workings of the [TON Block Consensus Protocol](#1-overview), which builds upon the generic [Catchain protocol](#2-catchain-protocol) to provide the BFT protocol employed for generating and validating new blocks of the TON Blockchain. The source code for the TON Block Consensus protocol resides in subdirectory `validator-session` of the source tree.\n\n### 3.1. Internal state of the Block Consensus Protocol\n\nThe higher-level Block Consensus Protocol introduces a new notion to the catchain: that of an _internal state_ of the Block Consensus Protocol (BCP), sometimes also (not quite correctly) called \"the internal state of the catchain\" or simply _catchain state_. Namely, each process $i \\in I$ has a well-determined internal state $\\sigma_{C_i}$ after a subset of messages (actually always a dependence cone) $C_i$ is delivered by the Catchain protocol to the higher-level protocol (i.e., to the Block Consensus Protocol in this case). Furthermore, this state $\\sigma_{C_i} = \\sigma(C_i)$ depends only on cone $C_i$, but not on the identity of the process $i \\in I$, and can be defined for any dependence cone $S$ (not necessarily a cone $C_i$ of delivered messages for some process $i$ at some point).\n\n#### 3.1.1. Abstract structure of the internal state\n\nWe start with an abstract structure of the internal state employed by BCP; more specific details will be provided later.\n\n#### 3.1.2. Updating the internal state\n\nThe Catchain protocol knows nothing about the internal state; it simply invokes appropriate callbacks supplied by the higher-level protocol (i.e., the BCP) whenever a message $m$ is delivered. It is the job of the higher-level protocol to compute the new state $\\sigma_{S'}$ starting from the previously computed state $\\sigma_S$ and the message $m$, where $S' = S \\cup \\{m\\}$ (and necessarily $S \\supset D_m$, otherwise $m$ could not have been delivered at this point).\n\n#### 3.1.3. Recursive formula for updating the internal state\n\nThe abstract setup for computing $\\sigma_S$ for all cones $S$ consists of three components:\n\n- A value $\\sigma_\\emptyset$ for the initial state (this value actually depends on the genesis block of the catchain; we ignore this dependence here because we consider only one catchain at this point).\n\n- A function $f$ that computes the state $\\sigma_{D^+_m}$ from the previous state $\\sigma_{D_m}$ and the newly-delivered message $m$:\n\n$$\n\\sigma_{D^+_m} = f(\\sigma_{D_m}, m) \\tag{5}\n$$\n\nwhere $D_m$ is the dependence cone of message $m$ and $D^+_m = D_m \\cup \\{m\\}$ its [extended dependence cone](#2-4-3-extended-dependence-cone-of-a-message). In most cases, $f$ will actually satisfy the stronger condition\n\n$$\n\\sigma_{S \\cup \\{m\\}} = f(\\sigma_S, m) \\quad \\text{if $S$ and $S \\cup \\{m\\}$ are cones and $m \\notin S$}\n\\tag{6}\n$$\n\nHowever, this stronger condition is not required by the update algorithm.\n\n- A \"merge function\" $g$ that computes $\\sigma_{S \\cup T}$ from $\\sigma_S$ and $\\sigma_T$:\n\n$$\n\\sigma_{S \\cup T} = g(\\sigma_S, \\sigma_T) \\quad \\text{for any cones $S$ and $T$}\n\\tag{7}\n$$\n\n(the union of two cones always is a cone). This function $\\sigma$ is applied by the update algorithm only in the specific case $T = D^+_m$ and $m \\not\\in S$.\n\n#### 3.1.4. Commutativity and associativity of $g$\n\nNote that ([7](#3-1-3-recursive-formula-for-updating-the-internal-state)) (for arbitrary cones $S$ and $T$) implies associativity and commutativity of $g$, at least when $g$ is applied to possible states (values of form $\\sigma_S$ for some cone $S$). In this respect $g$ defines a commutative monoid structure on the set $\\Sigma = \\{\\sigma_S : S \\text{ is a cone}\\}$. Usually $g$ is defined or partially defined on a larger set $\\tilde{\\Sigma}$ of state-like values, and it may be commutative and associative on this larger set $\\tilde{\\Sigma}$, i.e., $g(x,y) = g(y,x)$ and $g(x,g(y,z)) = g(g(x,y),z)$ for $x, y, z \\in \\tilde{\\Sigma}$ (whenever both sides of the equality are defined), with $\\sigma_\\emptyset$ as a unit, i.e., $g(x, \\sigma_\\emptyset) = x = g(\\sigma_\\emptyset, x)$ for $x \\in \\tilde{S}$ (under the same condition). However, this property, useful for the formal analysis of the consensus algorithm, is not strictly required by the state update algorithm, because this algorithm uses $g$ in a deterministic fashion to compute $\\sigma_S$.\n\n#### 3.1.5. Commutativity of $f$\n\nNote that $f$, if it satisfies the stronger condition ([6](#3-1-3-recursive-formula-for-updating-the-internal-state)), must also exhibit a commutativity property\n\n$$\nf(f(\\sigma_S, m), m') = f(f(\\sigma_S, m'), m) \\tag{8}\n$$\n\nwhenever $S$ is a cone and $m$ and $m'$ are two messages with $D_m \\subset S$, $D_{m'} \\subset S$, $m \\not\\in S$ and $m' \\not\\in S$, because in this case $S \\cup \\{m\\}$, $S \\cup \\{m'\\}$ and $S \\cup \\{m, m'\\}$ are also cones, and ([6](#3-1-3-recursive-formula-for-updating-the-internal-state)) implies that both sides of ([8](#3-1-5-commutativity-of)) are equal to $\\sigma_{S \\cup \\{m, m'\\}}$. Similarly to [Commutativity and associativity of $g$](#3-1-4-commutativity-and-associativity-of), $f$ is usually defined or partially defined on the product of a larger set $\\tilde{\\Sigma}$ of state-like values and of a set of message-like values; it may exhibit the \"commutativity\" property ([8](#3-1-5-commutativity-of)) or not on this larger set. If it does, this might be useful for formal analysis of the algorithms relying on $\\sigma_S$, but this property is not strictly necessary.\n\n#### 3.1.6. The state update algorithm\n\nThe state update algorithm (independently executed by each process $i$) employed by the catchain (actually by the higher-level BCP) uses $\\sigma_\\emptyset$, $f$ and $g$ as follows:\n\n- The algorithm keeps track of all $\\sigma_{D^+_m}$ for all messages $m$ delivered so far.\n\n- The algorithm keeps track of $\\sigma_{C_i}$, where $C_i$ is the current dependence cone, i.e., the set of all messages $m$ delivered (to the current process $i$). The initial value of $\\sigma_{C_i}$ is $\\sigma_\\emptyset$.\n\n- When a new message $m$ is delivered, the value of $\\sigma_{D_m}$ is computed by a repeated application of $g$ since $D_m = \\bigcup_{m' \\in D_m} D^+_{m'} = \\bigcup_{m' \\in \\text{Max}(D_m)} D^+_{m'}$; therefore, if $\\text{Max}(D_m) = \\{m'_1, \\ldots, m'_k\\}$, then\n\n$$\n\\sigma_{D_m} = g(\\ldots g(g(\\sigma_{D^+_{m'_1}}, \\sigma_{D^+_{m'_2}}), \\sigma_{D^+_{m'_3}}), \\ldots, \\sigma_{D^+_{m'_k}}) \\quad.\n\\tag{9}\n$$\n\nThe set $\\text{Max}(D_m)$ is explicitly listed in the header of message $m$ in some fixed order $m'_1, \\ldots, m'_k$; the above formula is applied with respect to this order (so the computation of $D_m$ is deterministic). The first element in this list always is the previous message of the sender of $m$, i.e., if $m = m_{i,s+1}$, then $m'_1 = m_{i,s}$.\n\n- After that, the value of $\\sigma_{D^+_m}$ is computed by an application of $f$: $\\sigma_{D^+_m} = f(\\sigma_{D_m}, m)$. This value is memorized for future use.\n\n- Finally, when a new message $m$ is delivered to the current process $i$, thus updating $C_i$ to $C'_i := C_i \\cup \\{m\\}$, the algorithm uses the computed value $\\sigma_{D^+_m}$ to update the current state\n\n$$\n\\sigma_{C'_i} = g(\\sigma_{C_i}, \\sigma_{D^+_m}) \\tag{10}\n$$\n\nThis state, however, is \"virtual\" in the sense that it can be slightly changed later (especially if $g$ is not commutative). Nevertheless, it is used to make some important decisions by the higher-level algorithm (BCP).\n\n- Once a new message $m$ is generated and locally delivered, so that $C_i$ becomes equal to $D^+_m$, the previously computed value of $\\sigma_{C_i}$ is discarded and replaced with $\\sigma_{D^+_m}$ computed according to the general algorithm described above. If $g$ is not commutative or not associative (for example, it may happen that $g(x,y)$ and $g(y,x)$ are different but equivalent representations of the same state), then this might lead to a slight change of the current \"virtual\" state of process $i$.\n\n- If the lower-level (catchain) protocol reports to the higher-level protocol that a certain process $j \\notin i$ is \"bad\" (i.e., $j$ is found out to have [created a fork](#2-7-6-the-set-of-“bad”-group-members-is-a-part-of-the-intrinsic-state), or to have knowingly [endorsed a fork](#2-7-5-accepting-messages-from-a-“bad”-process-is-bad) by another process), then the current (virtual) state $\\sigma_{C_i}$ is recomputed from scratch using the new set $C'_i = \\bigcup_{m \\in C_i, \\text{ m was created by \"good\" process } k} D_m^+$ and the \"merge\" function $g$ applied to the set of $\\sigma_{D_m^+}$ where $m$ runs through the set of last messages of the processes known to be good (or through the set of maximal elements of this set). The next created outbound message will depend only on the messages from $C'_i$.\n\n#### 3.1.7. Necessity to know the internal state of the other processes\n\nFormula ([9](#3-1-6-the-state-update-algorithm)) implies that process $i$ must also keep track of $\\sigma_{D^+_m}$ for all messages $m$, created by this process or not. However, this is possible since these internal states are also computed by appropriate applications of the update algorithm. Therefore, BCP computes and remembers all $\\sigma_{D^+_m}$ as well.\n\n#### 3.1.8. Function $f$ would suffice\n\nNotice that the update algorithm applies $g$ only to compute $\\sigma_{S \\cup D^+_m} = g(\\sigma_S, \\sigma_{D^+_m})$ when $S$ is a cone containing $D_m$, but not containing $m$. Therefore, every actual application of $g$ could have been replaced by an application of $f$ satisfying the extended property ([6](#3-1-3-recursive-formula-for-updating-the-internal-state)):\n\n$$\n\\sigma_{S \\cup D^+_m} = g(\\sigma_S, \\sigma_{D^+_m}) = f(\\sigma_S, m) \\tag{11}\n$$\n\nHowever, the update algorithm does not use this \"optimization\", because it would disable the more important optimizations described below in [Sharing data between different states](#3-2-4-sharing-data-between-different-states) and [Memoizing nodes](#3-2-5-memoizing-nodes).\n\n### 3.2. The structure of the internal state\n\nThe structure of the internal state is optimized to make the _transition function $f$_ of ([5](#3-1-3-recursive-formula-for-updating-the-internal-state)) and the _merge function $g$_ ([7](#3-1-3-recursive-formula-for-updating-the-internal-state)) as efficiently computable as possible, preferably without the need of potentially unbounded recursion (just some loops). This motivates the inclusion of additional components into the internal state (even if these components are computable from the remainder of the internal state), which have to be stored and updated as well. This process of including additional components is similar to that employed while solving problems using dynamic programming, or to that used while proving statements by mathematical (or structural) induction.\n\n#### 3.2.1. The internal state is a representation of a value of an abstract algebraic data type\n\nThe internal representation of the internal state is essentially a (directed) tree (or rather a directed acyclic graph) or a collection of nodes; each node contains some immediate (usually integer) values and several pointers to other (previously constructed) nodes. If necessary, an extra _constructor tag_ (a small integer) is added at the beginning of a node to distinguish between several possibilities. This structure is very similar to that used to represent values of abstract algebraic data types in functional programming languages such as Haskell.\n\n#### 3.2.2. The internal state is persistent\n\nThe internal state is _persistent_, in the sense that the memory used to allocate the nodes which are part of the internal state is never freed up while the catchain is active. Furthermore, the internal state of a catchain is actually allocated inside a huge contiguous memory buffer, and new nodes are always allocated at the end of the used portion of this buffer by advancing a pointer. In this way the references to other nodes from a node inside this buffer may be represented by an integer offset from the start of the buffer. Every internal state is represented by a pointer to its root node inside this buffer; this pointer can be also represented by an integer offset from the start of the buffer.\n\n#### 3.2.3. The internal state of a catchain is flushed to an append-only file\n\nThe consequence of the structure of the buffer used to store the internal states of a catchain explained above is that it is updated only by appending some new data at its end. This means that the internal state (or rather the buffer containing all the required internal states) of a catchain can be flushed to an append-only file, and easily recovered after a restart. The only other data that needs to be stored before restarts is the offset (from the start of the buffer, i.e., of this file) of the current state of the catchain. A simple key-value database can be used for this purpose.\n\n#### 3.2.4. Sharing data between different states\n\nIt turns out that the tree (or rather the dag) representing the new state $\\sigma_{S \\cup \\{m\\}} = f(\\sigma_S, m)$ shares large subtrees with the previous state $\\sigma_S$, and, similarly, $\\sigma_{S \\cup T} = g(\\sigma_S, \\sigma_T)$ shares large subtrees with $\\sigma_S$ and $\\sigma_T$. The persistent structure used for representing the states in BCP makes it possible to reuse the same pointers inside the buffer for representing such shared data structures instead of duplicating them.\n\n#### 3.2.5. Memoizing nodes\n\nAnother technique employed while computing new states (i.e., the values of function $f$) is that of _memoizing new nodes_, also borrowed from functional programming languages. Namely, whenever a new node is constructed (inside the huge buffer containing all states for a specific catchain), its hash is computed, and a simple hash table is used to look up the latest node with the same hash. If a node with this hash is found, and it has the same contents, then the newly-constructed node is discarded and a reference to the old node with the same contents is returned instead. On the other hand, if no copy of the new node is found, then the hash table is updated, the end-of-buffer (allocation) pointer is advanced, and the pointer to the new node is returned to the caller.\n\nIn this way if different processes end up making similar computations and having similar states, large portions of these [states will be shared](#3-2-4-sharing-data-between-different-states) even if they are not directly related by application of function $f$.\n\n#### 3.2.6. Importance of optimization techniques\n\nThe optimization techniques [3.2.4](#3-2-4-sharing-data-between-different-states) and [3.2.5](#3-2-5-memoizing-nodes) used for sharing parts of different internal states inside the same catchain are drastically important for improving the memory profile and the performance of BCM in a large process group. The improvement is several orders of magnitude in groups of $N \\approx 100$ processes. Without these optimizations BCM would not be fit for its intended purpose (BFT consensus on new blocks generated by validators in the TON Blockchain).\n\n#### 3.2.7. Message $m$ contains a hash of state $\\sigma_{D^+_m}$\n\nEvery message $m$ contains a (Merkle) hash of (the abstract representation of) the corresponding state $\\sigma_{D^+_m}$. Very roughly, this hash is computed recursively using the [tree of nodes representation](#3-2-1-the-internal-state-is-a-representation-of-a-value-of-an-abstract-algebraic-data-type): all node references inside a node are replaced with (recursively computed) hashes of the referred nodes, and a simple 64-bit hash of the resulting byte sequence is computed. This hash is also used for [memoization](#3-2-5-memoizing-nodes).\n\nThe purpose of this field in messages is to provide a sanity check for the computations of $\\sigma_{D^+_m}$ performed by different processes (and possibly by different implementations of the state update algorithm): once $\\sigma_{D^+_m}$ is computed for a newly-delivered message $m$, the hash of computed $\\sigma_{D^+_m}$ is compared to the value stored in the header of $m$. If these values are not equal, an error message is output into an error log (and no further actions are taken by the software). These error logs can be examined to detect bugs or incompatibilities between different versions of BCP.\n\n### 3.3. State recovery after restart or crashes\n\nA catchain is typically used by the BCP for several minutes; during this period, the program (the validator software) running the Catchain protocol may be terminated and restarted, either deliberately (e.g., because of a scheduled software update) or unintentionally (the program might crash because of a bug in this or some other subsystem, and be restarted afterwards). One way of dealing with this situation would be to ignore all catchains not created after the last restart. However, this would lead to some validators not participating in creating any blocks for several minutes (until the next catchain instances are created), which is undesirable. Therefore, a catchain state recovery protocol is run instead after every restart, so that the validator can continue participating in the same catchain.\n\n#### 3.3.1. Database of all delivered messages\n\nTo this end, a special database is created for each active catchain. This database contains all known and delivered messages, indexed by their identifiers (hashes). A simple key-value database suffices for this purpose. The hash of the most recent outbound message $m = m_{i,s}$ generated by the current process $i$ is also stored in this database. After restart, all messages up to $m$ are recursively delivered in proper order (in the same way as if all these messages had been just received from the network in an arbitrary order) and processed by the higher-level protocol, until $m$ finally is delivered, thus recovering the current state.\n\n#### 3.3.2. Flushing new messages to disk\n\nWe have already explained that [newly-created messages](#2-6-message-propagation-in-a-catchain) are stored in the [database of all delivered messages](#3-3-1-database-of-all-delivered-messages) and the database is flushed to disk before the new message is sent to all network neighbors. In this way we can be sure that the message cannot be lost if the system crashes and is restarted, thus avoiding the creation of involuntary forks.\n\n#### 3.3.3. Avoiding the recomputation of states $\\sigma_{D^+_m}$\n\nAn implementation might use an [append-only file](#3-2-3-the-internal-state-of-a-catchain-is-flushed-to-an-append-only-file) containing all previously computed states to avoid recomputing all states after restart, trading off disk space for computational power. However, the current implementation does not use this optimization.\n\n### 3.4. High-level description of Block Consensus Protocol\n\nNow we are ready to present a high-level description of the Block Consensus Protocol employed by TON Blockchain validators to generate and achieve consensus on new blockchain blocks. Essentially, it is a three-phase commit protocol that runs over a catchain (an instance of the Catchain protocol), which is used as a \"hardened\" message broadcast system in a process group.\n\n#### 3.4.1. Creation of new catchain messages\n\nRecall that the lower-level Catchain protocol does not create broadcast messages on its own (with the only exception being [service broadcasts with fork proofs](#2-7-5-accepting-messages-from-a-“bad”-process-is-bad)). Instead, when a new message needs to be created, the higher-level protocol (BCP) is asked to do this by invoking a callback. Apart from that, the creation of new messages may be triggered by changes in the current virtual state and by timer alarms.\n\n#### 3.4.2. Payload of catchain messages\n\nIn this way the payload of catchain messages is always determined by the higher level protocol, such as BCP. For BCP, this payload consists of:\n\n- Current Unix time. It must be non-decreasing on subsequent messages of the same process. (If this restriction is violated, all processes processing this message will tacitly replace this Unix time by the maximum Unix time seen in previous messages of the same sender.)\n- Several (zero or more) _BCP events_ of one of the admissible types listed below.\n\n#### 3.4.3. BCP events\n\nWe have just explained that the payload of a catchain message contains several (possibly zero) BCP events. Now we list all admissible BCP event types:\n\n- $\\text{Submit}(\\mathit{round}, \\mathit{candidate})$ — suggest a new block candidate\n- $\\text{Approve}(\\mathit{round}, \\mathit{candidate}, \\mathit{signature})$ — a block candidate has passed local validation\n- $\\text{Reject}(\\mathit{round}, \\mathit{candidate})$ — a block candidate has failed local validation\n- $\\text{CommitSign}(\\mathit{round}, \\mathit{candidate}, \\mathit{signature})$ — a block candidate has been accepted and signed\n- $\\text{Vote}(\\mathit{round}, \\mathit{candidate})$ — a vote for a block candidate\n- $\\text{VoteFor}(\\mathit{round}, \\mathit{candidate})$ — this block candidate must be voted for in this round (even if the current process has another opinion)\n- $\\text{PreCommit}(\\mathit{round}, \\mathit{candidate})$ — a preliminary commitment to a block candidate (used in three-phase commit scheme)\n\n#### 3.4.4. Protocol parameters\n\nSeveral parameters of BCP must be fixed in advance (in the genesis message of the catchain, where they are initialized from the values of the configuration parameters extracted from the current masterchain state):\n\n- $K$ — duration of one attempt (in seconds). It is an integer amount of seconds in the current implementation; however, this is an implementation detail, not a restriction of the protocol\n- $Y$ — number of _fast_ attempts to accept a candidate\n- $C$ — block candidates suggested during one round\n- $\\Delta_i$ for $1 \\leq i \\leq C$ — delay before suggesting the block candidate with priority $i$\n- $\\Delta_\\infty$ — delay before approving the null candidate\n\nPossible values for these parameters are $K = 8$, $Y = 3$, $C = 2$, $\\Delta_i = 2(i-1)$, $\\Delta_\\infty = 2C$.\n\n#### 3.4.5. Protocol overview\n\nThe BCP consists of several _rounds_ that are executed inside the same catchain. More than one round may be active at one point of time, because some phases of a round may overlap with other phases of other rounds. Therefore, all BCP events contain an explicit round identifier _round_ (a small integer starting from zero). Every round is terminated either by (collectively) accepting a _block candidate_ suggested by one of the participating processes, or by accepting a special _null candidate_—a dummy value indicating that no real block candidate was accepted, for example because no block candidates were suggested at all. After a round is terminated (from the perspective of a participating process), i.e., once a block candidate collects $\\text{CommitSign}$ signatures of more than $2/3$ of all validators, only $\\text{CommitSign}$ events may be added to that round; the process automatically starts participating in the next round (with the next identifier) and ignores all BCP events with different values of _round_.<a id=\"ref-fn6\" /><sup>[6](#fn6)</sup>\n\nEach round is subdivided into several _attempts_. Each attempt lasts a predetermined time period of $K$ seconds (BCP uses clocks to measure time and time intervals and assumes that clocks of \"good\" processes are more or less in agreement with each other; therefore, BCP is not an asynchronous BFT protocol). Each attempt starts at Unixtime exactly divisible by $K$ and lasts for $K$ seconds. The attempt identifier _attempt_ is the Unixtime of its start divided by $K$. Therefore, the attempts are numbered more or less consecutively by 32-bit integers, but not starting from zero. The first $Y$ attempts of a round are _fast_; the remaining attempts are _slow_.\n\n#### 3.4.6. Attempt identification. Fast and slow attempts\n\nIn contrast with rounds, BCP events do not have a parameter to indicate the attempt they belong to. Instead, this attempt is implicitly determined by the Unix time indicated in the [payload of the catchain message](#3-4-2-payload-of-catchain-messages) containing the BCP event. Furthermore, the attempts are subdivided into _fast_ (the first $Y$ attempts of a round in which a process takes part) and _slow_ (the subsequent attempts of the same round). This subdivision is also implicit: the first BCP event sent by a process in a round belongs to a certain attempt, and $Y$ attempts starting from this one are considered fast by this process.\n\n#### 3.4.7. Block producers and block candidates\n\nThere are $C$ designated block producers (member processes) in each round. The (ordered) list of these block producers is computed by a deterministic algorithm (in the simplest case, processes $i$, $i+1$, ..., $i+C-1$ are used in the $i$-th round, with the indices taken modulo $N$, the total number of processes in the catchain) and is known to all participants without any extra communication or negotiation. The processes are ordered in this list by decreasing priority, so the first member of the list has the highest priority (i.e., if it suggests a block candidate in time, this block candidate has a very high chance to be accepted by the protocol).\n\nThe first block producer may suggest a block candidate immediately after the round starts. Other block producers can suggest block candidates only after some delay $\\Delta_i$, where $i$ is the index of the producer in the list of designated block producers, with $0 = \\Delta_1 \\leq \\Delta_2 \\leq \\ldots$. After some predetermined period of time $\\Delta_\\infty$ elapses from the round start, a special _null candidate_ is assumed automatically suggested (even if there are no explicit BCP events to indicate this). Therefore, at most $C+1$ block candidates (including the null candidate) are suggested in a round.\n\n#### 3.4.8. Suggesting a block candidate\n\nA block candidate for the TON Blockchain consists of two large \"files\" — the block and the collated data, along with a small header containing the description of the block being generated (most importantly, the complete _block identifier_ for the block candidate, containing the workchain and the shard identifier, the block sequence number, its file hash and its root hash) and the SHA-256 hashes of the two large files. Only a part of this small header (including the hashes of the two files and other important data) is used as _candidate_ in BCP events such as $\\text{Submit}$ or $\\text{CommitSign}$ to refer to a specific block candidate. The bulk of the data (most importantly, the two large files) is propagated in the overlay network associated with the catchain by the [streaming broadcast protocol](/foundations/whitepapers/ton#3-3-15-streaming-broadcast-protocol) implemented over ADNL for this purpose. This bulk data propagation mechanism is unimportant for the validity of the consensus protocol (the only important point is that the hashes of the large files are part of BCP events and hence of the catchain messages, where they are signed by the sender, and these hashes are checked after the large files are received by any participating nodes; therefore, nobody can replace or corrupt these files). A $\\text{Submit}(\\mathit{round}, \\mathit{candidate})$ BCP event is created in the catchain by the block producer in parallel with the propagation of the block candidate, indicating the submission of this specific block candidate by this block producer.\n\n#### 3.4.9. Processing block candidates\n\nOnce a process observes a $\\text{Submit}$ BCP event in a delivered catchain message, it checks the validity of this event (for instance, its originating process must be in the list of designated producers, and current Unixtime must be at least the start of the round plus the minimum delay $\\Delta_i$, where $i$ is the index of this producer in the list of designated producers), and if it is valid, remembers it in the current [catchain state](#3-1-internal-state-of-the-block-consensus-protocol). After that, when a streaming broadcast containing the files associated with this block candidates (with correct hash values) is received (or immediately, if these files are already present), the process invokes a validator instance to validate the new block candidate (even if this block candidate was suggested by this process itself!). Depending on the result of this validation, either an $\\text{Approve}(\\mathit{round}, \\mathit{candidate}, \\mathit{signature})$ or a $\\text{Reject}(\\mathit{round}, \\mathit{candidate})$ BCP event is created (and embedded into a new catchain message). Note that the _signature_ used in $\\text{Approve}$ events uses the same private key that will ultimately be used to sign the accepted block, but the signature itself is different from that used in $\\text{CommitSign}$ (the hash of a structure with different magic number is actually signed). Therefore, this interim signature cannot be used to fake the acceptance of this block by this particular validator process to an outside observer.\n\n#### 3.4.10. Overview of one round\n\nEach round of BCP proceeds as follows:\n\n- At the beginning of a round, several processes (from the predetermined list of designated producers) submit their block candidates (with certain delays depending on their producer priority) and reflect this fact by means of $\\text{Submit}$ events (incorporated into catchain messages).\n\n- Once a process receives a submitted block candidate (i.e., observes a $\\text{Submit}$ event and receives all necessary files by means external to the consensus protocol), it starts the validation of this candidate and eventually creates either an $\\text{Approve}$ or a $\\text{Reject}$ event for this block candidate.\n\n- During each _fast attempt_ (i.e., one of the first $Y$ attempts) every process votes either for a block candidate that has collected the votes of more than $2/3$ of all processes, or, if there are no such candidates yet, for the valid (i.e., $\\text{Approve}$d by more than $2/3$ of all processes) block candidate with the highest priority. The voting is performed by means of creating $\\text{Vote}$ events (embedded into new catchain messages).\n\n- During each _slow attempt_ (i.e., any attempt except the first $Y$) every process votes either for a candidate that was $\\text{PreCommit}$ted before (by the same process), or for a candidate that was suggested by $\\text{VoteFor}$.\n\n- If a block candidate has received votes from more than $2/3$ of all processes during the current attempt, and the current process observes these votes (which are collected in the catchain state), a $\\text{PreCommit}$ event is created, indicating that the process will vote only for this candidate in future.\n\n- If a block candidate collects $\\text{PreCommit}$s from more than $2/3$ of all processes inside an attempt, then it is assumed to be accepted (by the group), and each process that observes these $\\text{PreCommit}$s creates a $\\text{CommitSign}$ event with a valid block signature. These block signatures are registered in the catchain, and are ultimately collected to create a \"block proof\" (containing signatures of more than $2/3$ of the validators for this block). This block proof is the external output of the consensus protocol (along with the block itself, but without its collated data); it is ultimately propagated in the overlay network of all full nodes that have subscribed to new blocks of this shard (or of the masterchain).\n\n- Once a block candidate collects $\\text{CommitSign}$ signatures from more than $2/3$ of all validators, the round is considered finished (at least from the perspective of a process that observes all these signatures). After that, only a $\\text{CommitSign}$ can be added to that round by this process, and the process automatically starts participating in the next round (and ignores all events related to other rounds).\n\nNote that the above protocol may lead to a validator signing (in a $\\text{CommitSign}$ event) a block candidate that was $\\text{Reject}$ed by the same validator before (this is a kind of \"submitting to the will of majority\").\n\n#### 3.4.11. $\\text{Vote}$ and $\\text{PreCommit}$ messages are created deterministically\n\nNote that each process can create at most one $\\text{Vote}$ and at most one $\\text{PreCommit}$ event in each attempt. Furthermore, these events are completely determined by the state $\\sigma_{D_m}$ of the sender of catchain message $m$ containing such an event. Therefore, the receiver can detect invalid $\\text{Vote}$ or $\\text{Precommit}$ events and ignore them (thus mitigating byzantine behavior of other participants). On the other hand, a message $m$ that should contain a $\\text{Vote}$ or a $\\text{Precommit}$ event according to the corresponding state $\\sigma_{D_m}$ but does not contain one can be received. In this case, the current implementation automatically creates missing events and proceeds as if $m$ had contained them from the very beginning. However, such instances of byzantine behavior are either corrected or ignored (and a message is output into the error log), but the offending processes are not otherwise punished (because this would require very large misbehavior proofs for outside observers that do not have access to the internal state of the catchain).\n\n#### 3.4.12. Multiple $\\text{Vote}$s and $\\text{PreCommit}$s of the same process\n\nNote that a process usually ignores subsequent $\\text{Vote}$s and $\\text{PreCommit}$s generated by the same originating process inside the same attempt, so normally a process can vote for at most one block candidate. However, it may happen that a \"good\" process indirectly observes a fork created by a byzantine process, with $\\text{Vote}$s for different block candidates in different branches of this fork (this can happen if the \"good\" process learns about these two branches from two other \"good\" processes that did not see this fork before). In this case, both $\\text{Vote}$s (for different candidates) are taken into account (added into the merged state of the current process). A similar logic applies to $\\text{PreCommit}$s.\n\n#### 3.4.13. Approving or rejecting block candidates\n\nNotice that a block candidate cannot be $\\text{Approve}$d or $\\text{Reject}$ed before it has been $\\text{Submit}$ted (i.e., an $\\text{Approve}$ event that was not preceded by a corresponding $\\text{Submit}$ event will be ignored), and that a candidate cannot be approved before the minimum time of its submission (the round start time plus the priority-dependent delay $\\Delta_i$) is reached, i.e., any \"good\" process will postpone the creation of its $\\text{Approve}$ until this time. Furthermore, one cannot $\\text{Approve}$ more than one candidate of the same producer in the same round (i.e., even if a process $\\text{Submit}$s several candidates, only one of them—presumably the first one—will be $\\text{Approve}$d by other \"good\" processes; as usual, this means that subsequent $\\text{Approve}$ events will be ignored by \"good\" processes on receipt).\n\n#### 3.4.14. Approving the null block candidate\n\nThe implicit null block candidate is also explicitly approved (by creating an $\\text{Approve}$ event) by all (good) processes, once the delay $\\Delta_\\infty$ from the start of the round expires.\n\n#### 3.4.15. Choosing a block candidate for voting\n\nEach process chooses one of the available block candidates (including the implicit null candidate) and votes for this candidate (by creating a $\\text{Vote}$ event) by applying the following rules (in the order they are presented):\n\n- If the current process created a $\\text{PreCommit}$ event for a candidate during one of the previous attempts, and no other candidate has collected votes from more than $2/3$ of all processes since (i.e., inside one of the subsequent attempts, including the current one so far; we say that the $\\text{Precommit}$ event is still _active_ in this case), then the current process votes for this candidate again.\n\n- If the current attempt is fast (i.e., one of the first $Y$ attempts of a round from the perspective of the current process), and a candidate has collected votes from more than $2/3$ of all processes during the current or one of the previous attempts, the current process votes for this candidate. In the case of a tie, the candidate from the latest of all such attempts is chosen.\n\n- If the current attempt is fast, and the previous rules do not apply, then the process votes for the candidate with the highest priority among all _eligible candidates_, i.e., candidates that have collected $\\text{Approve}$s (observable by the current process) from more than $2/3$ of all processes.\n\n- If the current attempt is slow, then the process votes only after it receives a valid $\\text{VoteFor}$ event in the same attempt. If the first rule is applicable, the process votes according to it (i.e., for the previously $\\text{PreCommit}$ted candidate). Otherwise it votes for the block candidate that is mentioned in the $\\text{VoteFor}$ event. If there are several such valid events (during the current attempt), the candidate with the smallest hash is selected (this may happen in rare situations related to different $\\text{VoteFor}$ events created in [different branches of a fork](#3-4-12-multiples-ands-of-the-same-process)).\n\nThe \"null candidate\" is considered to have the least priority. It also requires an explicit $\\text{Approve}$ before being voted for (with the exception of the first two rules).\n\n#### 3.4.16. Creating $\\text{VoteFor}$ events during slow attempts\n\nA $\\text{VoteFor}$ event is created at the beginning of a slow attempt by the _coordinator_ — the process with index $\\mathit{attempt} \\bmod N$ in the ordered list of all processes participating in the catchain (as usual, this means that a $\\text{VoteFor}$ created by another process will be ignored by all \"good\" processes). This $\\text{VoteFor}$ event refers to one of the block candidates (including the null candidate) that have collected $\\text{Approve}$s from more than $2/3$ of all processes, usually randomly chosen among all such candidates. Essentially, this is a suggestion to vote for this block candidate directed to all other processes that do not have an active $\\text{PreCommit}$.\n\n### 3.5. Validity of BCP\n\nNow we present a sketch of the proof of validity of [TON Block Consensus Protocol (BCP)](#3-4-high-level-description-of-block-consensus-protocol), assuming that less than one third of all processes exhibit byzantine (arbitrarily malicious, possibly protocol-violating) behavior, as it is customary for Byzantine Fault Tolerant protocols. During this subsection, we consider only one round of BCP, subdivided into several attempts.\n\n#### 3.5.1. Fundamental assumption\n\nLet us emphasize once again that we assume that _less than one third of all processes are byzantine_. All other processes are assumed to be _good_, i.e., they follow the protocol.\n\n#### 3.5.2. Weighted BCP\n\nThe reasoning in this subsection is valid for the _weighted variant of BCP_ as well. In this variant, each process $i \\in I$ is pre-assigned a positive weight $w_i > 0$ (fixed in the genesis message of the catchain), and statements about \"more than $2/3$ of all processes\" and \"less than one third of all processes\" are understood as \"more than $2/3$ of all processes by weight\", i.e., \"a subset $J \\subset I$ of processes with total weight $\\sum_{j \\in J} w_j > \\frac{2}{3} \\sum_{i \\in I} w_i$\", and similarly for the second property. In particular, our \"[fundamental assumption](#3-5-1-fundamental-assumption)\" is to be understood in the sense that \"the total weight of all byzantine processes is less than one third of the total weight of all processes\".\n\n#### 3.5.3. Useful invariants\n\nWe collect here some useful invariants obeyed by all BCP events during one round of BCP (inside a catchain). These invariants are enforced in two ways. Firstly, any \"good\" (non-byzantine) process will not create events violating these invariants. Secondly, even if a \"bad\" process creates an event violating these invariants, all \"good\" processes will detect this when a catchain message containing this event is delivered to BCP and ignore such events. Some possible [issues related to forks](#3-4-12-multiples-ands-of-the-same-process) remain even after these precautions; we indicate how these issues are resolved separately, and ignore them in this list. So:\n\n- There is at most one $\\text{Submit}$ event by each process (inside one round of BCP).\n\n- There is at most one $\\text{Approve}$ or $\\text{Reject}$ event by each process related to one candidate (more precisely, even if there are multiple candidates created by the same designated block producer, only one of them can be $\\text{Approve}$d by another process).<a id=\"ref-fn7\" /><sup>[7](#fn7)</sup> This is achieved by requiring all \"good\" processes to ignore (i.e., not to create $\\text{Approve}$s or $\\text{Reject}$s for) all candidates suggested by the same producer but the very first one they have learned about.\n\n- There is at most one $\\text{Vote}$ and at most one $\\text{PreCommit}$ event by each process during each attempt.\n\n- There is at most one $\\text{VoteFor}$ event during each (slow) attempt.\n\n- There is at most one $\\text{CommitSign}$ event by each process.\n\n- During a slow attempt, each process votes either for its previously $\\text{PreCommit}$ted candidate, or for the candidate indicated in the $\\text{VoteFor}$ event of this attempt.\n\nOne might somewhat improve the above statements by adding the word \"valid\" where appropriate (e.g., there is at most one _valid_ $\\text{Submit}$ event...).\n\n#### 3.5.4. More invariants\n\n- There is at most one eligible candidate (i.e., candidate that has received $\\text{Approve}$s from more than $2/3$ of all processes) from each designated producer, and no eligible candidates from other producers.\n\n- There are at most $C+1$ eligible candidates in total (at most $C$ candidates from $C$ designated producers, plus the null candidate).\n\n- A candidate may be accepted only if it has collected more than $2/3$ $\\text{PreCommit}$s during the same attempt (more precisely, a candidate is accepted only if there are $\\text{PreCommit}$ events created by more than $2/3$ of all processes for this candidate and belonging to the same attempt).\n\n- A candidate may be $\\text{Vote}$d for, $\\text{PreCommit}$ted, or mentioned in a $\\text{VoteFor}$ only if it is an _eligible candidate_, meaning that it has previously collected $\\text{Approve}$s from more than $2/3$ of all validators (i.e., a valid $\\text{Vote}$ event may be created for a candidate only if $\\text{Approve}$ events for this candidate have been previously created by more than $2/3$ of all processes and registered in catchain messages observable from the message containing the $\\text{Vote}$ event, and similarly for $\\text{PreCommit}$ and $\\text{VoteFor}$ events).\n\n#### 3.5.5. At most one block candidate is accepted\n\nNow we claim that _at most one block candidate can be accepted (in a round of BCP)_. Indeed, a candidate can be accepted only if it collects $\\text{PreCommit}$s from more than $2/3$ of all processes inside the same attempt. Therefore, two different candidates cannot achieve this during the same attempt (otherwise more than one third of all validators must have created $\\text{PreCommit}$s for two different candidates inside an attempt, thus violating the above invariants; but we have assumed that less than one third of all validators exhibit byzantine behavior). Now suppose that two different candidates $c_1$ and $c_2$ have collected $\\text{PreCommit}$s from more than $2/3$ of all processes in two different attempts $a_1$ and $a_2$. We may assume that $a_1 < a_2$. According to the first rule of [Choosing a block candidate for voting](#3-4-15-choosing-a-block-candidate-for-voting), each process that has created a $\\text{PreCommit}$ for $c_1$ during attempt $a_1$ must continue voting for $c_1$ in all subsequent attempts $a' > a_1$, or at least cannot vote for any other candidate, unless another candidate $c'$ collects $\\text{Vote}$s of more than $2/3$ of all processes during a subsequent attempt (and this [invariant](#3-4-11-and-messages-are-created-deterministically) is enforced even if some processes attempt not to create these new $\\text{Vote}$ events for $c_1$). Therefore, if $c_2 \\neq c_1$ has collected the necessary amount of $\\text{PreCommit}$s during attempt $a_2 > a_1$, there is at least one attempt $a'$, $a_1 < a' \\leq a_2$, such that some $c' \\neq c_1$ (not necessarily equal to $c_2$) has collected $\\text{Vote}$s of more than $2/3$ of all processes during attempt $a'$. Let us fix the smallest such $a'$, and the corresponding $c' \\neq c_1$ that has collected many votes during attempt $a'$. More than $2/3$ of all validators have voted for $c'$ during attempt $a'$, and more than $2/3$ of all validators have $\\text{PreCommit}$ted for $c_1$ during attempt $a_1$, and by the minimality of $a'$ there was no attempt $a''$ with $a_1 < a'' < a'$, such that a candidate distinct from $c_1$ collected more than $2/3$ of all votes during attempt $a''$. Therefore, all validators that $\\text{PreCommit}$ted for $c_1$ could vote only for $c_1$ during attempt $a'$, and at the same time we supposed that $c'$ has collected votes from more than $2/3$ of all validators during the same attempt $a'$. This implies that more than $1/3$ of all validators have somehow voted both for $c_1$ and $c'$ during this attempt (or voted for $c'$ while they could have voted only for $c_1$), i.e., more than $1/3$ of all validators have exhibited byzantine behavior. This is impossible by our [fundamental assumption](#3-5-1-fundamental-assumption).\n\n#### 3.5.6. At most one block candidate may be  $\\text{PreCommit}$ted during one attempt\n\nNote that all valid $\\text{PreCommit}$ events (if any) created inside the same attempt must refer to the same block candidate, by the same reasoning as in the [first part](#3-5-5-at-most-one-block-candidate-is-accepted): since a valid $\\text{PreCommit}$ event for a candidate $c$ may be created only after votes from more than $2/3$ of all processes are observed for this candidate inside the same attempt (and invalid $\\text{PreCommit}$s are ignored by all good processes), the existence of valid $\\text{PreCommit}$ events for different candidates $c_1$ and $c_2$ inside the same attempt would imply that more than one third of all processes have voted both for $c_1$ and $c_2$ inside this attempt, i.e., they have exhibited byzantine behavior. This is impossible in view of our [fundamental assumption](#3-5-1-fundamental-assumption).\n\n#### 3.5.7. A previous $\\text{PreCommit}$ is deactivated by the observation of a newer one\n\nWe claim that _whenever a process with an active $\\text{PreCommit}$ observes a valid $\\text{PreCommit}$ created by any process in a later attempt for a different candidate, its previously active $\\text{PreCommit}$ is deactivated_. Recall that we say that a process has an _active $\\text{PreCommit}$_ if it has created a $\\text{PreCommit}$ for a certain candidate $c$ during a certain attempt $a$, did not create any $\\text{PreCommit}$ during any attempts $a' > a$, and did not observe votes of more than $2/3$ of all validators for any candidate $\\neq c$ during any attempts $a' > a$. Any process has at most one active $\\text{PreCommit}$, and if it has one, it must vote only for the precommitted candidate.\n\nNow we see that if a process with an active $\\text{PreCommit}$ for a candidate $c$ since attempt $a$ observes a valid $\\text{PreCommit}$ (usually by another process) for a candidate $c'$ created during some later attempt $a' > a$, then the first process must also observe all dependencies of the message that contains the newer $\\text{PreCommit}$; these dependencies necessarily include valid $\\text{Vote}$s from more than $2/3$ of all validators for the same candidate $c' \\neq c$ created during the same attempt $a' > a$ (because otherwise the newer $\\text{PreCommit}$ would not be valid, and would be ignored by the other process); by definition, the observation of all these $\\text{Vote}$s deactivates the original $\\text{PreCommit}$.\n\n#### 3.5.8. Assumptions for proving the convergence of the protocol\n\nNow we are going to prove that the protocol described above _converges_ (i.e., terminates after accepting a block candidate) with probability one under some assumptions, which essentially tell us that there are enough \"good\" processes (i.e., processes that diligently follow the protocol and do not introduce arbitrary delays before sending their new messages), and that these good processes enjoy good network connectivity at least from time to time. More precisely, our assumptions are as follows:\n\n- There is a subset $I^+ \\subset I$ consisting of \"good\" processes and containing more than $2/3$ of all processes.\n\n- All processes from $I^+$ have well-synchronized clocks (differing by at most $\\tau$, where $\\tau$ is a bound for network latency described below).\n\n- If there are infinitely many attempts, then infinitely many attempts are \"good\" with respect to network connectivity between processes from $I^+$, meaning that all messages created by a process from $I^+$ during this attempt or earlier are delivered to any other process from $I^+$ within at most $\\tau > 0$ seconds after being created with probability at least $q > 0$, where $\\tau > 0$ and $0 < q < 1$ are some fixed parameters, such that $5\\tau < K$, where $K$ is the duration of one attempt.\n\n- Furthermore, if the protocol runs for infinitely many attempts, then any arithmetic progression of attempts contains infinitely many \"good\" attempts in the sense described above.\n\n- A process from $I^+$ creates a $\\text{VoteFor}$ during a slow attempt after some fixed or random delay after the start of the slow attempt, in such a way that this delay belongs to the interval $(\\tau, K-3\\tau)$ with probability at least $q'$, where $q' > 0$ is a fixed parameter.\n\n- A process from $I^+$, when it is its turn to be the coordinator of a slow attempt, chooses a candidate for $\\text{VoteFor}$ uniformly at random among all eligible candidates (i.e., those candidates that have collected $\\text{Approve}$s from more than $2/3$ of all validators).\n\n#### 3.5.9. The protocol terminates under these assumptions\n\nNow we claim that _(each round of) the BCP protocol as described above terminates with probability one under the [assumptions](#3-5-8-assumptions-for-proving-the-convergence-of-the-protocol)_. The proof proceeds as follows:\n\n- Let us assume that the protocol does not converge. Then it continues running forever. We are going to ignore the first several attempts, and consider only attempts $a_0$, $a_0+1$, $a_0+2$, ... starting from some $a_0$, to be chosen later.\n\n- Since all processes from $I^+$ continue participating in the protocol, they will create at least one message not much later than the start of the round (which may be perceived slightly differently by each process). For instance, they will create an $\\text{Approve}$ for the null candidate no later than $\\Delta_\\infty$ seconds from the start of the round. Therefore, they will consider all attempts slow at most $KY$ seconds afterwards. By choosing $a_0$ appropriately, we can assume that all attempts we consider are slow from the perspective of all processes from $I^+$.\n\n- After a \"good\" attempt $a \\geq a_0$ all processes from $I^+$ will see the $\\text{Approve}$s for the null candidate created by all other processes from $I^+$, and will deem the null candidate eligible henceforth. Since there are infinitely many \"good\" attempts, this will happen sooner or later with probability one. Therefore, we can assume (increasing $a_0$ if necessary) that there is at least one eligible candidate from the perspective of all processes from $I^+$, namely, the null candidate.\n\n- Furthermore, there will be infinitely many attempts $a \\geq a_0$ that are perceived slow by all processes from $I^+$, that have a coordinator from $I^+$, and that are [\"good\"](#3-5-8-assumptions-for-proving-the-convergence-of-the-protocol) (with respect to the network connectivity). Let us call such attempts \"very good\".\n\n- Consider one \"very good\" slow attempt $a$. With probability $q' > 0$, its coordinator (which belongs to $I^+$) will wait for $\\tau' \\in (\\tau, K-3\\tau)$ seconds before creating its $\\text{VoteFor}$ event. Consider the most recent $\\text{PreCommit}$ event created by any process from $I^+$; let us suppose it was created during attempt $a' < a$ for some candidate $c'$. With probability $qq' > 0$, the catchain message carrying this $\\text{PreCommit}$ will be already delivered to the coordinator at the time of generation of its $\\text{VoteFor}$ event. In that case, the catchain message carrying this $\\text{VoteFor}$ will depend on this $\\text{PreCommit}(c')$ event, and all \"good\" processes that observe this $\\text{VoteFor}$ will also observe its dependencies, including this $\\text{PreCommit}(c')$. We see that _with probability at least $qq'$, all processes from $I^+$ that receive the_ $\\mathit{VoteFor}$ _event during a \"very good\" slow attempt receive also the most recent_ $\\mathit{PreCommit}$ _(if any)._\n\n- Next, consider any process from $I^+$ that receives this $\\text{VoteFor}$, for a randomly chosen eligible candidate $c$, and suppose that there are already some $\\text{PreCommit}$s, and that the previous statement holds. Since there are at most $C+1$ [eligible candidates](#3-5-4-more-invariants), with probability at least $1/(C+1) > 0$ we'll have $c = c'$, where $c'$ is the most recently $\\text{PreCommit}$ted candidate (there is at [most one such candidate](#3-5-6-at-most-one-block-candidate-may-be-ted-during-one-attempt)). In this case, all processes from $I^+$ will vote for $c = c'$ during this attempt immediately after they receive this $\\text{VoteFor}$ (which will be delivered to any process $j \\in I^+$ less than $K-2\\tau$ seconds after the beginning of the attempt with probability $qq'$). Indeed, if a process $j$ from $I^+$ did not have an active $\\text{PreCommit}$, it will vote for the value indicated in $\\text{VoteFor}$, which is $c$. If $j$ had an active $\\text{PreCommit}$, and it is as recent as possible, i.e., also created during attempt $a'$, then it must have been a $\\text{PreCommit}$ for the same value $c' = c$ (because we know about at least one valid $\\text{PreCommit}$ for $c'$ during attempt $a'$, and all other valid $\\text{PreCommit}$s during attempt $a'$ must be for the [same](#3-5-6-at-most-one-block-candidate-may-be-ted-during-one-attempt) $c'$). Finally, if $j$ had an active $\\text{PreCommit}$ from an attempt $< a'$, then it will become [inactive](#3-5-7-a-previous-is-deactivated-by-the-observation-of-a-newer-one) once the $\\text{VoteFor}$ with all its dependencies (including the newer $\\text{PreCommit}(c')$) has been delivered to this process $j$, and the process will again vote for the value $c$ indicated in $\\text{VoteFor}$. Therefore, all processes from $I^+$ will vote for the same $c = c'$ during this attempt, less than $K-2\\tau$ seconds after the beginning of the attempt (with some probability bounded away from zero).\n\n- If there are no $\\text{PreCommit}$s yet, then the above reasoning simplifies further: all processes from $I^+$ that receive this $\\text{VoteFor}$ will immediately vote for the candidate $c$ suggested by this $\\text{VoteFor}$.\n\n- In both cases, all processes from $I^+$ will create a $\\text{Vote}$ for the same candidate $c$ less than $K-2\\tau$ seconds from the beginning of the attempt, and this will happen with a positive probability bounded away from zero.\n\n- Finally, all processes from $I^+$ will receive these $\\text{Vote}$s for $c$ from all processes from $I^+$, again less than $(K-2\\tau) + \\tau = K-\\tau$ seconds after the beginning of this attempt, i.e., still during the same attempt (even after taking into account the imperfect clock synchronization between processes from $I^+$). This means that they will all create a valid $\\text{PreCommit}$ for $c$, i.e., the protocol will accept $c$ during this attempt with probability bounded away from zero.\n\n- Since there are infinitely many \"very good\" attempts, and the probability of successful termination during each such attempt is $\\geq p > 0$ for some fixed value of $p$, the protocol will terminate successfully with probability one.\n\n## References\n\n\\[1] K. Birman, _Reliable Distributed Systems: Technologies, Web Services and Applications_, Springer, 2005.\n\n\\[2] M. Castro, B. Liskov, et al., _Practical byzantine fault tolerance_, Proceedings of the Third Symposium on Operating Systems Design and Implementation (1999), p. 173–186, available at [http://pmg.csail.mit.edu/papers/osdi99.pdf](http://pmg.csail.mit.edu/papers/osdi99.pdf).\n\n\\[3] N. Durov, _Telegram Open Network_, 2017.\n\n\\[4] N. Durov, _Telegram Open Network Blockchain_, 2018.\n\n\\[5] L. Lamport, R. Shostak, M. Pease, _The byzantine generals problem_, ACM Transactions on Programming Languages and Systems, **4/3** (1982), p. 382–401.\n\n\\[6] A. Miller, Yu Xia, et al., _The honey badger of BFT protocols_, Cryptology e-print archive 2016/99, [https://eprint.iacr.org/2016/199.pdf](https://eprint.iacr.org/2016/199.pdf), 2016.\n\n\\[7] M. van Steen, A. Tanenbaum, _Distributed Systems, 3rd ed._, 2017.\n\n## Footnotes\n\n<span id=\"fn1\">1.</span> The original name of this protocol used during the initial stage of the research and development phase was _catch-chain_ or _catchchain_, because it essentially is a special blockchain dedicated to catching all events important for the consensus protocol; after saying and writing this name a lot of times it gradually got contracted to \"catchain\". [Back ↑](#ref-fn1)\n\n<span id=\"fn2\">2.</span> When the ratio of the malicious or non-participating or very slow validators grows up to one third, the protocol exhibits graceful degradation, with the block consensus time growing very slowly—say, by at most half a second—until the critical value of one third is almost achieved. [Back ↑](#ref-fn2)\n\n<span id=\"fn3\">3.</span> If some validators have an outdated masterchain state, they may fail to compute correct task group lists and to participate in the corresponding catchains; in this respect, they are treated as if they were malicious or malfunctioning and do not affect the overall validity of the BFT protocol as long as less than one third of all validators fail in this fashion. [Back ↑](#ref-fn3)\n\n<span id=\"fn4\">4.</span> In the Byzantine environment of a catchain this is not necessarily true in all situations. [Back ↑](#ref-fn4)\n\n<span id=\"fn5\">5.</span> We assume that all broadcast messages in the process group are \"causal broadcasts\" or \"cbcast\" in the terminology of distributed systems literature, because we only need cbcasts for the implementation of Catchain protocol and Catchain consensus. [Back ↑](#ref-fn5)\n\n<span id=\"fn6\">6.</span> This also means that each process implicitly determines the Unixtime of the start of the next round, and computes all delays, e.g., the block candidate submission delays, starting from this time. [Back ↑](#ref-fn6)\n\n<span id=\"fn7\">7.</span> In fact, $\\text{Reject}$s appear only in this restriction, and do not affect anything else. Therefore, any process can abstain from sending $\\text{Reject}$s without violating the protocol, and $\\text{Reject}$ events could have been removed from the protocol altogether. Instead, the current implementation of the protocol still generates $\\text{Reject}$s, but does not check anything on their receipt and does not remember them in the catchain state. Only a message is output into the error log, and the offending candidate is stored into a special directory for future study, because $\\text{Reject}$s usually indicate either the presence of a byzantine adversary, or a bug in the collator (block generation) or validator (block verification) software either on the node that suggested the block or on the node that created the $\\text{Reject}$ event. [Back ↑](#ref-fn7)\n"
  },
  {
    "path": "foundations/whitepapers/overview.mdx",
    "content": "---\ntitle: \"Overview\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nThe original TON documentation was written by Dr. Nikolai Durov and comprises a series of whitepapers. They provided a comprehensive overview of all aspects of TON.\n\nWhile most of the information described in the original PDFs holds some truth, those whitepapers are considered legacy due to a lack of updates and gradual integration of their contents into actual documentation pages. Notice that \"legacy\" here does not mean \"outdated\", but rather less kept up to date compared to the regular pages.\n\nOnly an English PDF version of whitepapers is considered \"official.\" English HTML version is provided by documentation team. The rest are community translations.\n\nThe code, comments, and documentation may reference \"gram\" and \"nanogram\". These are remnants of the original TON code developed by Telegram. Gram cryptocurrency was never issued. The official currency of TON is Toncoin.\n\n| Whitepaper                  | PDF                                                                                                                                                                                                                                                                                                                                                               | HTML                                                                                                                      |\n| --------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------ |\n| The Open Network (TON)      | [EN](/resources/pdfs/ton.pdf) [RU](https://github.com/Korolyow/TON_docs_ru/blob/main/pdf/ton_whitepaper_ru.pdf) [ZH](https://github.com/awesome-doge/TON_Paper/blob/main/zh_ton.pdf)  [ZH](https://github.com/kojhliang/Ton_White_Paper_SC/blob/main/Ton%E5%8C%BA%E5%9D%97%E9%93%BE%E7%99%BD%E7%9A%AE%E4%B9%A6_%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87%E7%89%88.pdf) | [EN](/foundations/whitepapers/ton) [RU](https://github.com/Korolyow/TON_docs_ru/blob/main/html/ton_whitepaper_ru.html)    |\n| TON Virtual Machine (TVM)   | [EN](/resources/pdfs/tvm.pdf) [RU](https://github.com/Korolyow/TON_docs_ru/blob/main/pdf/tvm_ru.pdf) [ZH](https://github.com/awesome-doge/TON_Paper/blob/main/zh_tvm.pdf)                                                                                                                                                                                         | [EN](/foundations/whitepapers/tvm) [RU](https://github.com/Korolyow/TON_docs_ru/blob/main/html/tvm_ru.html)               |\n| TON Blockchain              | [EN](/resources/pdfs/tblkch.pdf) [RU](https://github.com/Korolyow/TON_docs_ru/blob/main/pdf/ton_blockchain_ru.pdf) [ZH](https://github.com/awesome-doge/TON_Paper/blob/main/zh_tblkch.pdf)                                                                                                                                                                        | [EN](/foundations/whitepapers/tblkch) [RU](https://github.com/Korolyow/TON_docs_ru/blob/main/html/ton_blockchain_ru.html) |\n| Catchain consensus          | [EN](/resources/pdfs/catchain.pdf) [RU](https://github.com/Korolyow/TON_docs_ru/blob/main/pdf/catchain_ru.pdf) [ZH](https://github.com/awesome-doge/TON_Paper/blob/main/zh_catchain.pdf)                                                                                                                                                                          | [EN](/foundations/whitepapers/catchain) [RU](https://github.com/Korolyow/TON_docs_ru/blob/main/html/catchain_ru.html)     |\n| Fift language specification | [EN](/resources/pdfs/fiftbase.pdf) [RU](https://github.com/Korolyow/TON_docs_ru/blob/main/pdf/fiftbase_ru.pdf) [ZH](https://github.com/awesome-doge/TON_Paper/blob/main/zh_fiftbase.pdf)                                                                                                                                                                          | [EN](/languages/fift/whitepaper)                                                                                          |\n"
  },
  {
    "path": "foundations/whitepapers/tblkch.mdx",
    "content": "---\ntitle: \"Telegram Open Network (TON) Blockchain Specification\"\nsidebarTitle: \"TON Blockchain\"\ndescription: \"Whitepaper by Dr. Nikolai Durov\"\n---\n\n**Authors**: Nikolai Durov <br />\n**Date**: February 8, 2020 <br />\n<Icon icon=\"file-pdf\" size={16} />: [Original whitepaper, PDF](/resources/pdfs/tblkch.pdf)\n\n## Abstract\n\nThe aim of this text is to provide a detailed description of the Telegram Open Network (TON) Blockchain.\n\n---\n\n\n## Introduction\n\nThis document provides a detailed description of the TON Blockchain, including its precise block format, validity conditions, TON Virtual Machine (TVM) invocation details, smart-contract creation process, and cryptographic signatures. In this respect it is a continuation of the [TON whitepaper](/foundations/whitepapers/ton), so we freely use the terminology introduced in that document.\n\n[Chapter 1](#1-overview) provides a general overview of the TON Blockchain and its design principles, with particular attention to the introduction of compatibility and validity conditions and the implementation of message delivery guarantees. More detailed information, such as the TL-B schemes that describe the serialization of all required data structures into trees or collections (\"bags\") of cells, is provided in subsequent chapters, culminating in a complete description of the TON Blockchain (shardchain and masterchain) block layout in [Chapter 5](#5-block-layout).\n\nA detailed description of the elliptic curve cryptography used for signing blocks and messages, also accessible through TVM primitives, is provided in [Appendix A](#a-elliptic-curve-cryptography). TVM itself is described in a [separate document](/foundations/whitepapers/tvm).\n\nSome subjects have intentionally been left out of this document. One is the Byzantine Fault Tolerant(BFT) protocol used by the validators to determine the next block of the masterchain or a shardchain; that subject is left for a forthcoming document dedicated to the TON Network. And although this document describes the precise format of TON Blockchain blocks, and discusses the blockchain's validity conditions and serialized invalidity proofs,<a id=\"ref-fn1\"></a><sup>[1](#fn1)</sup> it provides no details about the network protocols used to propagate these blocks, block candidates, collated blocks, and invalidity proofs.\n\nSimilarly, this document does not provide the complete source code of the masterchain smart contracts used to elect the validators, change the configurable parameters or get their current values, or punish the validators for their misbehavior, even though these smart contracts form an important part of the total blockchain state and of the masterchain block zero. Instead, this document describes the location of these smart contracts and their formal interfaces.<a id=\"ref-fn2\"></a><sup>[2](#fn2)</sup> The source code of these smart contracts will be provided separately as downloadable files with comments.\n\nPlease note that the current version of this document describes a preliminary test version of the TON Blockchain; some minor details are likely to change prior to launch during the development, testing, and deployment phases.\n\n# 1   Overview\n\nThis chapter provides an overview of the main features and design principles of the TON Blockchain. More detail on each topic is provided in subsequent chapters.\n\n## 1.1   Everything is a bag of cells\n\nAll data in the blocks and state of the TON Blockchain is represented as a collection of [cells](/foundations/whitepapers/ton#2-5-global-shardchain-state-%E2%80%9Cbag-of-cells%E2%80%9D-philosophy). Therefore, this chapter begins with a general discussion of cells.\n\n### 1.1.1. TVM cells\n\nRecall that the TON Blockchain, as well as the TON Virtual Machine (TVM), represents all permanently stored data as a collection or [bag of so-called cells](/foundations/whitepapers/tvm#3-1-10-“everything-is-a-bag-of-cells”-paradigm). Each cell consists of up to 1023 data bits and up to four references to other cells. Cyclic cell references are not allowed, so the cells are usually organized into *trees of cells*, or rather *directed acyclic graphs (DAGs) of cells*.<a id=\"ref-fn3\"></a><sup>[3](#fn3)</sup> Any value of an abstract algebraic (dependent) data type may be represented (serialized) as a tree of cells. The precise way of representing values of an abstract data type as a tree of cells is expressed by means of a *TL-B scheme*.<a id=\"ref-fn4\"></a><sup>[4](#fn4)</sup>   A more thorough discussion of different kinds of cells may be found in [Generalities on cells](/foundations/whitepapers/tvm#3-1-generalities-on-cells).\n\n### 1.1.2. Application to TON Blockchain blocks and state\n\nThe above is particularly applicable to the blocks and state of the TON Blockchain, which also are values of certain (quite convoluted) dependent algebraic data types. Therefore, they are serialized according to various TL-B schemes (which are gradually presented throughout this document), and are represented as a collection or bag of cells.\n\n### 1.1.3. The layout of a single cell\n\nEach single cell consists of up to 1023 data bits and up to four references to other cells. When a cell is kept in memory, its exact representation is implementation-dependent. However, there is a standard representation of cells, useful for instance, for serializing cells for file storage or network transmission. \nThis \"standard representation\" or \"standard layout\" $\\text{CellRepr}(c)$ of a cell $c$ consists of the following:\n\n- Two *descriptor bytes* come first, sometimes denoted by $d_1$ and $d_2$. The first of these bytes $d_1$ equals (in the simplest case) the number of references $0\\leq r\\leq 4$ in the cell. The second descriptor byte $d_2$ encodes the bit length $l$ of the data part of the cell as follows: the first seven bits of $d_2$ equal $\\lfloor l/8\\rfloor$, the number of complete data bytes present in the cell, while the last bit of $d_2$ is the *completion tag*, equal to one if $l$ is not divisible by eight. Therefore,\n\n  $$\n  d_2=2\\lfloor l/8\\rfloor+[l\\bmod 8\\neq0]=\\lfloor l/8\\rfloor+\\lceil l/8\\rceil \\tag{1}\n  $$\n\nwhere $[A]$ equals one when condition $A$ is true, and zero otherwise.\n\n- Next, $\\lceil l/8\\rceil$ data bytes follow. This means that the $l$ data bits of the cell are split into groups of eight, and each group is interpreted as a big-endian 8-bit integer and stored into a byte. If $l$ is not divisible by eight, a single binary one and a suitable number of binary zeroes (up to six) are appended to the data bits, and the completion tag (the least significant bit of the descriptor byte $d_2$) is set.\n\n- Finally, $r$ references to other cells follow. Each reference is normally represented by 32 bytes containing the [SHA-256 hash](#1-1-4-the-sha-256-hash-of-a-cell) of the referenced cell computed.\n\nIn this way, the standard representation $\\text{CellRepr}(c)$ of a cell $c$ with $l$ data bits and $r$ references is $2+\\lceil l/8\\rceil+32r$ bytes long.\n\n### 1.1.4. The SHA-256 hash of a cell\n\nThe SHA-256 hash of a cell $c$ is recursively defined as the SHA-256 of the standard representation $\\text{CellRepr}(c)$ of the cell in question:\n\n$$\n\\text{Hash}(c):=\\text{Sha256}(c):=\\text{Sha256}\\bigl(\\text{CellRepr}(c)\\bigr) \\tag{2}\n$$\n\nBecause cyclic cell references are not allowed (the relationships among all cells must constitute a directed acyclic graph, or DAG), the SHA-256 hash of a cell is always well-defined.\n\nFurthermore, because SHA-256 is tacitly assumed to be collision-resistant, we assume that all the cells that we encounter are completely determined by their hashes. In particular, the cell references of a cell $c$ are completely determined by the hashes of the referenced cells, contained in the standard representation $\\text{CellRepr}(c)$.\n\n### 1.1.5. Exotic cells\n\nApart from the *ordinary* cells (also called *simple* or *data* cells) considered so far, cells of other types, called *exotic cells*, sometimes appear in the actual representations of TON Blockchain blocks and other data structures. Their representation is somewhat different; they are distinguished by having the first [descriptor byte](/foundations/whitepapers/tvm#3-1-4-standard-cell-representation) $d_1\\geq 5$.\n\n### 1.1.6. External reference cells\n\n*(External) reference cells*, which contain the 32-byte $\\text{Sha256}(c)$ of a \"true\" data cell $c$ instead of the data cell itself, are one example of exotic cells. These cells can be used in the serialization of a bag of cells corresponding to a TON Blockchain block in order to refer to data cells absent in the serialization of the block itself, but assumed to be present somewhere else (e.g., in the previous state of the blockchain).\n\n### 1.1.7. Transparency of reference cells with respect to most operations\n\nMost cell operations do not observe any reference cells or other \"exotic\" kinds of cells; they see only data cells, with any reference cell transparently replaced by the cell referred to. For example, when the *transparent* cell hash $\\text{Hash}^\\flat(c)$ is recursively computed, the hash of a reference cell is set to be equal to the hash of the cell referred to, not the hash of the standard representation of the reference cell.\n\n### 1.1.8. Transparent hash and representation hash of a cell\n\nIn this way, $\\text{Sha256}^\\flat(c)=\\text{Hash}^\\flat(c)$ is the *transparent hash* of a cell $c$ (or the tree of cells rooted in $c$).\n\nHowever, sometimes we need to reason about the exact representation of a tree of cells present in a block. To this end, a *representation hash* $\\text{Hash}^\\sharp(c)$ is defined, which is not transparent with respect to reference cells and other exotic types of cells. We often say that the representation hash of $c$ is \"the\" hash of $c$, because it is the most frequently used hash of a cell.\n\n### 1.1.9. Use of representation hashes for signatures\n\nSignatures are an excellent example of the application of representation hashes. For instance:\n\n- Validators sign the representation hash of a block, not just its transparent hash, because they need to certify that the block does contain the required data, not just some external references to them.\n- When external messages are signed and sent by off-chain parties (e.g., human clients using an application to initiate blockchain transactions), if external references may be present in some of these messages, it is the representation hashes of the messages that must be signed.\n\n### 1.1.10. Higher hashes of a cell\n\nIn addition to the transparent and representation hashes of a cell $c$, a sequence of [higher hashes](/foundations/whitepapers/tvm#3-1-6-the-higher-hashes-of-a-cell) $\\text{Hash}_i(c)$, $i=1,2,\\dots$ may be defined, which eventually stabilizes at $\\text{Hash}_\\infty(c)$.\n\n---\n\n## 1.2   Principal components of a block and the blockchain state\n\nThis section briefly describes the principal components of a block and of the blockchain state, without delving too much into the details.\n\n### 1.2.1. The Infinite Sharding Paradigm (ISP) applied to blockchain block and state\n\nRecall that according to the Infinite Sharding Paradigm, each account can be considered as lying in its separate \"accountchain\", and the (virtual) blocks of these accountchains are then grouped into shardchain blocks for efficiency purposes. Specifically, the state of a shardchain consists, roughly speaking, of the states of all its \"accountchains\" (i.e., of all accounts assigned to it); similarly, a block of a shardchain essentially consists of a collection of virtual \"blocks\" for some accounts assigned to the shardchain.<a id=\"ref-fn5\"></a><sup>[5](#fn5)</sup>\n\nWe can summarize this as follows:\n\n$$\n\\textit{ShardState} \\approx \\text{Hashmap}(n,\\textit{AccountState}) \\tag{3}\n$$\n\n$$\n\\textit{ShardBlock} \\approx \\text{Hashmap}(n,\\textit{AccountBlock}) \\tag{4}\n$$\n\nwhere $n$ is the bit length of the $\\mathit{account\\_id}$, and $\\text{Hashmap}(n,X)$ describes a partial map $\\mathbf{2}^n\\dashrightarrow X$ from bitstrings of length $n$ into values of type $X$.\n\nRecall that each shardchain—or, more precisely, each shardchain block<a id=\"ref-fn6\"></a><sup>[6](#fn6)</sup>—corresponds to all accountchains that belong to the same \"workchain\" (i.e., have the same $\\mathit{workchain\\_id}=w$) and have an $\\mathit{account\\_id}$ beginning with the same binary prefix $s$, so that $(w,s)$ completely determines a shard. Therefore, the above hashmaps must contain only keys beginning with prefix $s$.\n\nWe will see in a moment that the above description is only an approximation: the state and block of the shardchain need to contain some extra data that are not split according to the $\\mathit{account\\_id}$ as suggested by ([3](#1-2-1-the-infinite-sharding-paradigm-isp-applied-to-blockchain-block-and-state)).\n\n### 1.2.2. Split and non-split part of the shardchain block and state\n\nA shardchain block and its state may each be classified into two distinct parts. The parts with the ISP-dictated form of ([3](#1-2-1-the-infinite-sharding-paradigm-isp-applied-to-blockchain-block-and-state)) will be called the *split* parts of the block and its state, while the remainder will be called the *non-split* parts.\n\n### 1.2.3. Interaction with other blocks and the outside world. Global and local consistency conditions\n\nThe non-split parts of the shardchain block and its state are mostly related to the interaction of this block with some other \"neighboring\" blocks. The global consistency conditions of the blockchain as a whole are reduced to internal consistency conditions of separate blocks by themselves as well as external local [consistency conditions](#1-3-consistency-conditions) between certain blocks.\n\nMost of these local consistency conditions are related to message forwarding between different shardchains, transactions involving more than one shardchain, and message delivery guarantees. However, another group of local consistency conditions relates a block with its immediate antecessors and successors inside a shardchain; for instance, the initial state of a block usually must coincide with the final state of its immediate antecessor.<a id=\"ref-fn7\"></a><sup>[7](#fn7)</sup>\n\n### 1.2.4. Inbound and outbound messages of a block\n\nThe most important components of the non-split part of a shardchain block are the following:\n\n* *InMsgDescr* — The description of all messages \"imported\" into this block (i.e., either processed by a transaction included in the block, or forwarded to an output queue, in the case of a transit message travelling along the path dictated by Hypercube Routing).\n* *OutMsgDescr* — The description of all messages \"exported\" or \"generated\" by the block (i.e., either messages generated by a transaction included in the block, or transit messages with destination not belonging to the current shardchain, forwarded from *InMsgDescr*).\n\n### 1.2.5. Block header\n\nAnother non-split component of a shardchain block is the *block header*, which contains general information such as $(w,s)$ (i.e., the $\\mathit{workchain\\_id}$ and the common binary prefix of all $\\mathit{account\\_id}$s assigned to the current shardchain), the block's *sequence number* (defined to be the smallest non-negative integer larger than the sequence numbers of its predecessors), *logical time*, and *generation unixtime*. It also contains the hash of the immediate antecessor of the block (or of its two immediate antecessors in the case of a preceding shardchain merge event), the hashes of its initial and final states (i.e., of the states of the shardchain immediately before and immediately after processing the current block), and the hash of the most recent masterchain block known when the shardchain block was generated.\n\n### 1.2.6. Validator signatures, signed and unsigned blocks\n\nThe block described so far is an *unsigned block*; it is generated in its entirety and considered as a whole by the validators. When the validators ultimately sign it, the *signed block* is created, consisting of the unsigned block along with a list of validator signatures (of a certain [representation hash](#1-1-9-use-of-representation-hashes-for-signatures) of the unsigned block). This list of signatures is also a non-split component of the (signed) block; however, since it lies outside the unsigned block, it is somewhat different from the other data kept in a block.\n\n### 1.2.7. Outbound message queue of a shardchain\n\nSimilarly, the most important non-split part of the shardchain state is *OutMsgQueue*, the outbound message queue. It contains *undelivered* messages included into *OutMsgDescr*, either by the last shardchain block leading to this state or by one of its antecessors.\n\nOriginally, each outbound message is included into *OutMsgQueue*; it is removed from the queue only after it has either been included into the *InMsgDescr* of a block of a \"neighboring\" shardchain (the next one with respect to Hypercube Routing), or has been delivered to (i.e., has appeared in the *InMsgDescr* of) its ultimate destination shardchain via Instant Hypercube Routing. In both cases, the *reason* for the removal of a message from the *OutMsgQueue* is made explicit in the *OutMsgDescr* of the block in which such a state transformation has occurred.\n\n### 1.2.8. Layout of *InMsgDescr*, *OutMsgDescr* and *OutMsgQueue*\n\nAll of the most important non-split shardchain data structures related to messages are organized as *hashmaps* or *dictionaries* (implemented by means of [Patricia trees](/foundations/whitepapers/tvm#3-3-2-hashmaps-as-patricia-trees) serialized into a tree of cells), with the following keys:\n\n- The inbound message description *InMsgDescr* uses the 256-bit message hash as a key.\n- The outbound message description *OutMsgDescr* uses the 256-bit message hash as a key.\n- The outbound message queue *OutMsgQueue* uses the 352-bit concatenation of the 32-bit destination $\\mathit{workchain\\_id}$, the first 64 bits of destination address $\\mathit{account\\_id}$, and the 256-bit message hash as a key.\n\n### 1.2.9. The split part of the block: transaction chains\n\nThe split part of a shardchain block consists of a hashmap mapping some of the accounts assigned to the shardchain to \"virtual accountchain blocks\" *AccountBlock* ([3](#1-2-1-the-infinite-sharding-paradigm-isp-applied-to-blockchain-block-and-state)). Such a virtual accountchain block consists of a sequential list of *transactions* related to that account.\n\n### 1.2.10. Transaction description\n\nEach transaction is described in the block by an instance of the *Transaction* type, which contains in particular the following information:\n\n- A reference to exactly one *inbound message* (which must be present in *InMsgDescr* as well) that has been *processed* by the transaction.\n- References to several (maybe zero) *outbound messages* (also present in *OutMsgDescr* and most likely included in *OutMsgQueue*) that have been *generated* by the transaction.\n\nThe transaction consists of an invocation of the TVM with the code of the smart contract corresponding to the account in question loaded into the virtual machine, and with the data root cell of the smart contract loaded into the virtual machine's [register c4](/foundations/whitepapers/tvm#1-3-2-list-of-control-registers). The inbound message itself is passed in the stack as an argument to the smart contract's `main()` function, along with some other important data, such as the amount of TON Gram and other defined currencies attached to the message, the sender account address, the current balance of the smart contract, and so on.\n\nIn addition to the information listed above, a *Transaction* instance also contains the original and final states of the account (i.e., of the smart contract), as well as some of the TVM running statistics (gas consumed, gas price, instructions performed, cells created/destroyed, virtual machine termination code, etc.).\n\n### 1.2.11. The split part of the shardchain state: account states\n\nRecall that, according to ([3](#1-2-1-the-infinite-sharding-paradigm-isp-applied-to-blockchain-block-and-state)), the split part of the shardchain state consists of a hashmap mapping each \"defined\" account identifier (belonging to the shardchain in question) to the *state* of the corresponding account, given by an instance of the *AccountState* type.\n\n### 1.2.12. Account state\n\nThe account state itself approximately consists of the following data:\n\n- Its *balance* in Grams and (optionally) in some other defined cryptocurrencies/tokens.\n- The *smart-contract code*, or the hash of the smart-contract code if it will be provided (uploaded) later by a separate message.\n- The persistent *smart-contract data*, which can be empty for simple smart contracts. It is a tree of cells, the root of which is loaded into register $\\texttt{c4}$ during smart-contract execution.\n- Its *storage usage statistics*, including the number of cells and bytes kept in the persistent storage of the smart contract (i.e., inside the blockchain state) and the last time a storage usage payment was exacted from this account.\n- An optional *formal interface description* (intended for smart contracts) and/or *user public information* (intended mostly for human users and organizations).\n\nNotice that there is no distinction between \"smart contract\" and \"account\" in the TON Blockchain. Instead, \"simple\" or \"wallet\" accounts, typically employed by human users and their cryptocurrency wallet applications for simple cryptocurrency transfers, are just simple smart contracts with standard (shared) code and with persistent data consisting of the public key of the [wallet](#1-7-6-example%3A-creating-a-cryptocurrency-wallet-smart-contract) (or several public keys in the case of a multi-signature wallet).\n\n### 1.2.13. Masterchain blocks\n\nIn addition to shardchain blocks and their states, the TON Blockchain contains *masterchain blocks* and the *masterchain state* (also called the *global state*). The masterchain blocks and state are quite similar to the shardchain blocks and state considered so far, with some notable differences:\n\n- The masterchain cannot be split or merged, so a masterchain block usually has exactly one immediate antecessor. The sole exception is the \"masterchain block zero\", distinguished by having a sequence number equal to zero; it has no antecessors at all, and contains the initial configuration of the whole TON Blockchain (e.g., the original set of validators).\n- The masterchain blocks contain another important non-split structure: *ShardHashes*, a binary tree with a list of all defined shardchains along with the hashes of the latest block inside each of the listed shardchains. It is the inclusion of a shardchain block into this structure that makes a shardchain block \"canonical\", and enables other shardchains' blocks to refer to data (e.g., outbound messages) contained in the shardchain block.\n- The state of the masterchain contains global configuration parameters of the whole TON Blockchain, such as the minimum and maximum gas prices, the supported versions of TVM, the minimum stake for the validator candidates, the list of alternative cryptocurrencies supported in addition to Grams, the total amount of Grams issued so far, and the current set of validators responsible for creating and signing new blocks, along with their public keys.\n- The state of the masterchain also contains the code of the smart contracts used to elect the subsequent sets of validators and to modify the global configuration parameters. The code of these smart contracts itself is a part of the global configuration parameters and can be modified accordingly. In this respect, this code (along with the current values of these parameters) functions like a \"constitution\" for the TON Blockchain. It is initially established in masterchain block zero.\n- There are no transit messages through the masterchain: each inbound message must have a destination inside the masterchain, and each outbound message must have a source inside the masterchain.\n\n---\n\n## 1.3   Consistency conditions\n\nIn addition to the data structures contained in the block and in the blockchain state, which are serialized into bags of cells according to certain TL-B schemes explained in detail later (Chapters [3](#3-messages%2C-message-descriptors%2C-and-queues)—[5](#5-block-layout)), an important component of the blockchain layout is the [consistency conditions](#1-2-3-interaction-with-other-blocks-and-the-outside-world-global-and-local-consistency-conditions) between data kept inside one or in different blocks. This section describes in detail the function of consistency conditions in the blockchain.\n\n### 1.3.1. Expressing consistency conditions\n\nIn principle, dependent data types (such as those used in TL-B) could be used not only to describe the serialization of block data, but also to express conditions imposed on the components of such data types. (For instance, one could define data type $\\textit{OrderedIntPair}$, with pairs of integers $(x,y)$, such that $x<y$, as values.) However, TL-B currently is not expressive enough to encode all the consistency conditions we need, so we opt for a semi-formalized approach in this text. In the future, we may present a subsequent complete formalization in a suitable proof assistant such as Coq.\n\n### 1.3.2. Importance of consistency conditions\n\nThe consistency conditions ultimately are at least as important as the \"unrestricted\" data structures on which they are imposed, especially in the blockchain context. For instance, the consistency conditions ensure that the state of an account does not change between blocks, and that it can change within a block only as a result of a transaction. In this way, the consistency conditions ensure the safe storage of cryptocurrency balances and other information inside the blockchain.\n\n### 1.3.3. Kinds of consistency conditions\n\nThere are several kinds of consistency conditions imposed on the TON Blockchain:\n\n- *Global conditions* — Express the invariants throughout the entire TON Blockchain. For instance, the *message delivery guarantees*, which assert that each message generated must be delivered to its destination account and delivered exactly once, are part of the global conditions.\n- *Internal (local) conditions* — Express the conditions imposed on the data kept inside one block. For example, each transaction included in the block (i.e., present in the transaction list of some account) processes exactly one inbound message; this inbound message must be listed in the *InMsgDescr* structure of the block as well.\n- *External (local) conditions* — Express the conditions imposed on the data of different blocks, usually belonging to the same or to neighboring shardchains (with respect to Hypercube Routing). Therefore, the external conditions come in several flavors:\n  - *Antecessor/successor conditions* — Express the conditions imposed on the data of some block and of its immediate antecessor or (in the case of a preceding shardchain merge event) two immediate antecessors. The most important of these conditions is the one stating that the initial state for a shardchain block must coincide with final shardchain state of the immediate antecessor block, provided no shardchain split/merge event happened in between.\n  - *Masterchain/shardchain conditions* — Express the conditions imposed on a shardchain block and on the masterchain block that refers to it in its *ShardHashes* list or is referred to in the header of the shardchain block.\n  - *Neighbor (block) conditions* — Express the relations between the blocks of neighboring shardchains with respect to Hypercube Routing. The most important of these conditions express the relation between the *InMsgDescr* of a block and the *OutMsgQueue* of the state of a neighboring block.\n\n### 1.3.4. Decomposition of global and local conditions into simpler local conditions\n\nThe *global* consistency conditions, such as the message delivery guarantees, are truly necessary for the blockchain to work properly; however, they are hard to enforce and verify directly. Therefore, we instead introduce a lot of simpler *local* consistency conditions, which are easier to enforce and verify since they involve only one block, or perhaps two adjacent blocks. These local conditions are chosen in such a fashion that the desired global conditions are logical consequences of (the conjunction of) all the local conditions. In this respect, we say that the global conditions have been \"decomposed\" into simpler local conditions.\n\nSometimes a local condition still turns out to be too cumbersome to enforce or verify. In that case it is decomposed further, into even simpler local conditions.\n\n### 1.3.5. Decomposition may require additional data structures and additional internal consistency conditions\n\nThe decomposition of a condition into simpler local consistency conditions sometimes requires the introduction of additional data structures. For example, the *InMsgDescr* explicitly lists all inbound messages processed in a block, even if this list might have been obtained by scanning the list of all the transactions present in the block. However, *InMsgDescr* greatly simplifies the neighbor conditions related to message forwarding and routing, which ultimately add up to the global message delivery guarantees.\n\nNotice that the introduction of such additional data structures is a sort of \"database denormalization\" (i.e., it leads to some redundancy, or to some data being present more than once), and therefore more internal consistency conditions need to be imposed (e.g., if some data are now present in two copies, we must require that these two copies coincide). For instance, once we introduce *InMsgDescr* to facilitate message forwarding between shardchains, we need to introduce internal consistency conditions relating *InMsgDescr* to the transaction list of the same block.\n\n### 1.3.6. Correct serialization conditions\n\nApart from the high-level internal consistency conditions, which treat the contents of a block as a value of an abstract data type, there are some lower-level internal consistency conditions, called \"(correct) serialization conditions\", which ensure that the tree of cells present in the block is indeed a valid serialization of a value of the expected abstract data type. Such serialization conditions can be automatically generated from the TL-B scheme describing the abstract data type and its serialization into a tree of cells.\n\nNotice that the serialization conditions are a set of mutually recursive predicates on cells or cell slices. For example, if a value of type $A$ consists of a 32-bit magic number $m_A$, a 64-bit integer $l$, and two references to cells containing values of types $B$ and $C$, respectively, then the correct serialization condition for values of type $A$ will require a cell or a cell slice to contain exactly 96 data bits and two cell references $r_1$ and $r_2$, with the additional requirements that the first 32 data bits contain $m_A$, and the two cells referred to by $r_1$ and $r_2$ satisfy the serialization conditions for values of types $B$ and $C$, respectively.\n\n### 1.3.7. Constructive elimination of existence quantifiers\n\nThe local conditions one might want to impose sometimes are *non-constructible*, meaning that they do not necessarily contain an explanation of why they are true. A typical example of such a condition $C$ is given by\n\n$$\nC :\\equiv \\forall_{(x:X)} \\exists_{(y:Y)} A(x, y) \\quad , \\tag{5}\n$$\n\n\"for any $x$ from $X$, there is a $y$ from $Y$ such that condition $A(x,y)$ holds\". Even if we know $C$ to be true, we do not have a way of quickly finding a $y:Y$, such that $A(x,y)$, for a given $x:X$. As a consequence, the verification of $C$ may be quite time-consuming.\n\nIn order to simplify the verification of local conditions, they are made *constructible* (i.e., verifiable in bounded time) by adding some *witness* data structures. For instance, condition $C$ of (5) may be transformed by adding a new data structure $f:X\\to Y$ (a map $f$ from $X$ to $Y$) and imposing the following condition $C'$ instead:\n\n$$\nC':\\equiv\\forall_{(x:X)}A\\bigl(x,f(x)\\bigr)\\quad. \\tag{6}\n$$\n\nOf course, the \"witness\" value $f(x):Y$ may be included inside the (modified) data type $X$ instead of being kept in a separate table $f$.\n\n### 1.3.8. Example: consistency condition for *InMsgDescr*\n\nFor instance, the consistency condition between $X:=\\textit{InMsgDescr}$, the list of all inbound messages processed in a block, and $Y:=\\textit{Transactions}$, the list of all transactions present in a block, is of the above sort: \"For any input message $x$ present in *InMsgDescr*, a transaction $y$ must be present in the block such that $y$ processes $x$\".<a id=\"ref-fn8\"></a><sup>[8](#fn8)</sup> The procedure of [$\\exists$-elimination](#1-3-7-constructive-elimination-of-existence-quantifiers) leads us to introduce an additional field in the inbound message descriptors of *InMsgDescr*, containing a reference to the transaction in which the message is actually processed.\n\n### 1.3.9. Constructive elimination of logical disjunctions\n\nSimilarly to the [transformation condition](#1-3-7-constructive-elimination-of-existence-quantifiers),\n\n$$\nD :\\equiv \\forall_{(x:X)} (A_1(x) \\vee A_2(x)) \\quad , \\tag{7}\n$$\n\n\"for all $x$ from $X$, at least one of $A_1(x)$ and $A_2(x)$ holds\", may be transformed into a function $i:X\\to\\mathbf{2}=\\{1,2\\}$ and a new condition\n\n$$\nD':\\equiv\\forall_{(x:X)}A_{i(x)}(x) \\tag{8}\n$$\n\nThis is a special case of the existential quantifier elimination considered before for $Y=\\mathbf{2}=\\{1,2\\}$. It may be useful when $A_1(x)$ and $A_2(x)$ are complicated conditions that cannot be verified quickly, so that it is useful to know in advance which of them is in fact true.\n\nFor instance, [InMsgDescr](#1-3-8-example%3A-consistency-condition-for-inmsgdescr), can contain both messages processed in the block and transit messages. We might introduce a field in the inbound message description to indicate whether the message is transit or not, and, in the latter case, include a witness field for the transaction processing the message.\n\n### 1.3.10. Constructivization of conditions\n\nThis process of eliminating the non-constructible logical binders $\\exists$ (existence quantifier) and (sometimes) $\\vee$ (logical disjunction) by introducing additional data structures and fields—that is, the process of making a condition constructible—will be called *constructivization*. If taken to its theoretical limit, this process leads to logical formulas containing only universal quantifiers and logical conjunctions, at the expense of adding some witness fields into certain data structures.\n\n### 1.3.11. Validity conditions for a block\n\nUltimately, all of the internal conditions for a block, along with the local antecessor and neighbor conditions involving this block and another previously generated block, constitute the *validity conditions* for a shardchain or masterchain block. A block is *valid* if it satisfies the validity conditions. It is the responsibility of validators to generate valid blocks, as well as check the validity of blocks generated by other validators.\n\n### 1.3.12. Witnesses of the invalidity of a block\n\nIf a block does not satisfy all of the validity conditions $C_1, \\ldots, C_n$ (i.e., the conjunction $V:\\equiv\\bigwedge_i C_i$ of the validity conditions), it is *invalid*. This means that it satisfies the \"invalidity condition\" $\\neg V=\\bigvee_i\\neg C_i$. If all of the $C_i$—and hence, also $V$—have been [constructivized](#1-3-10-constructivization-of-conditions), so that they contain only logical conjunctions and universal quantifiers (and simple atomic propositions), then $\\neg V$ contains only logical disjunctions and existential quantifiers. Then a constructivization of $\\neg V$ may be defined, which would involve an *invalidity witness*, starting with an index $i$ of the specific validity condition $C_i$ which fails.\n\nSuch invalidity witnesses may also be serialized and presented to other validators or committed into the masterchain to prove that a specific block or block candidate is in fact invalid. Therefore, the construction and serialization of invalidity witnesses is an important part of a Proof-of-Stake (PoS) blockchain design.<a id=\"ref-fn9\"></a><sup>[9](#fn9)</sup>\n\n### 1.3.13. Minimizing the size of witnesses\n\nAn important consideration for the design of the local conditions, their decomposition into simpler conditions, and their constructivization is to make the verification of each condition as simple as possible. However, another requirement is that we should minimize the size of witnesses both for a condition (so that block size does not grow too much during the constructivization process) and for its negation (so that the invalidity proofs have bounded size, which simplifies their verification, transmission, and inclusion into the masterchain). These two design principles are sometimes at odds, and a compromise must be then sought.\n\n### 1.3.14. Minimizing the size of Merkle proofs\n\nThe consistency conditions are originally intended to be processed by a party who already has all the relevant data (e.g., all the blocks mentioned in the condition). On some occasions, however, they must be verified by a party who does not have all the blocks in question, but knows only their hashes. For example, suppose that a block invalidity proof were augmented by the signature of a validator that had signed an invalid block (and therefore would have to be punished). In this case, the signature would contain only the hash of the wrongly signed block; the block itself would have to be recovered from a different place before verifying the block invalidity proof.\n\nA compromise between providing only the hash of the supposedly invalid block and providing the entire invalid block along with the invalidity witness is to augment the invalidity witness by a Merkle proof starting from the hash of the block (i.e., of the root cell of the block). Such a proof would include all the cells referred to in the invalidity witness, along with all the cells on the paths from these cells to the root cells and the hashes of their siblings. Then an invalidity proof becomes self-contained enough to provide sufficient justification on its own for punishing a validator. For example, the invalidity proof suggested above might be presented to a smart contract residing in the masterchain that punishes the validators for incorrect behavior.\n\nSince such an invalidity proof must be augmented by a Merkle proof, it makes sense to write the consistency conditions so that the Merkle proofs for their negations would be as small as possible. In particular, each individual condition must be as \"local\" as possible (i.e., involve a minimal number of cells). This also optimizes the verification time of the invalidity proof.\n\n### 1.3.15. Collated data for the external conditions\n\nWhen a validator suggests an unsigned block to the other validators of a shardchain, these other validators must check the validity of this block candidate—i.e., verify that it satisfies all of the internal and external local consistency conditions. While the internal conditions do not require any extra data in addition to the block candidate itself, the external conditions need some other blocks, or at least some information out of those blocks. Such additional information may be extracted from those blocks, along with all cells on the paths from the cells containing the required additional information to the root cell of the corresponding blocks and the hashes of the siblings of the cells on these paths, to present a Merkle proof that can be processed without knowledge of the referred blocks themselves.\n\nThis additional information, called *collated* data, is serialized as a bag of cells and presented by the validator along with the unsigned block candidate itself. The block candidate along with the collated data is called a *collated block*.\n\n### 1.3.16. Conditions for a collated block\n\nThe *external* consistency conditions for a block candidate are thus (automatically) transformed into *internal* consistency conditions for a collated block, which greatly simplifies and speeds up their verification by the other validators. However, some data—such as the final state of the immediate antecessor of the block being validated—is not collated. Instead, all validators are supposed to keep a local copy of this data.\n\n### 1.3.17. Representation conditions and representation hashes\n\nNotice that once Merkle proofs are included into a collated block, the consistency conditions must take into account which data (i.e., which cells) are actually present in the collated block, and not just referred to by their hashes. This leads to a new group of conditions, called *representation conditions*, which must be able to distinguish an external cell reference (usually represented by its 256-bit hash) from the cell itself. A validator can be punished for suggesting a collated block that does not contain all of the expected collated data inside, even if the block candidate itself is valid.\n\nThis also leads to the utilization of *representation hashes* instead of *transparent hashes* for collated blocks.\n\n### 1.3.18. Verification in the absence of the collated data\n\nNotice that a block must still be verifiable in the absence of the collated data; otherwise, no party except the validators would be able to check a previously committed block by its own means. In particular, witnesses cannot be included into the collated data: they must reside in the block itself. The collated data must contain only some portions of neighboring blocks referred to in the principal block along with suitable Merkle proofs, which can be reconstructed by anybody who has the referenced blocks themselves.\n\n### 1.3.19. Inclusion of Merkle proofs in the block itself\n\nNotice that on some occasions Merkle proofs must be embedded into the block itself, and not just into collated data. For instance:\n\n- During Instant Hypercube Routing (IHR), a message may be included directly into the *InMsgDescr* of a block of the destination shardchain, without travelling all the way along the edges of the hypercube. In this case, a Merkle proof of the existence of the message in the *OutMsgDescr* of a block of the originating shardchain must be included into *InMsgDescr* along with the message itself.\n- An invalidity proof, or another proof of validator misbehavior, may be committed into the masterchain by including it in the body of a message sent to a special smart contract. In this case, the invalidity proof must include some cells along with a Merkle proof, which must therefore be contained in a message body.\n- Similarly, a smart contract defining a payment channel, or another kind of side-chain, may accept finalization messages or misbehavior proof messages that contain suitable Merkle proofs.\n- The final state of a shardchain is not included into a shardchain block. Instead, only the cells that have been modified are included; those cells that are inherited from the old state are referred to by their hashes, along with suitable Merkle proofs consisting of the cells on the path from the root of the old state to the cells of the old state referred to.\n\n### 1.3.20. Provisions for handling incomplete data\n\nAs we have seen, it is necessary to include incomplete data and Merkle proofs into the body of a block, into the body of some messages contained in a block, and into the state. This necessity is reflected by some extra representation conditions, as well as provisions for the messages (and by extension, the cell trees processed by TVM) to contain incomplete data (external cell references and Merkle proofs). In most cases, such external cell references contain only the 256-bit SHA-256 hash of a cell along with a flag; if a smart contract attempts to inspect the contents of such a cell by a $\\texttt{CTOS}$ primitive (e.g., for deserialization), an exception is triggered. However, an external reference to such a cell can be stored into the smart contract's persistent storage, and both the transparent and the representation hashes of such a cell can be computed.\n\n---\n\n## 1.4   Logical time and logical time intervals\n\nThis section takes a closer look at so-called *logical time*, extensively used in the TON Blockchain for message forwarding and message delivery guarantees, among other purposes.\n\n### 1.4.1. Logical time\n\nA component of the TON Blockchain that also plays an important role in message delivery is the *logical time*, usually denoted by $\\text{Lt}$. It is a non-negative 64-bit integer, assigned to certain events roughly as follows:\n\n> If an event $e$ logically depends on events $e_1$, ..., $e_n$, then $\\text{Lt}(e)$ is the smallest non-negative integer greater than all $\\text{Lt}(e_i)$.\n\nIn particular, if $n=0$ (i.e., if $e$ does not depend on any prior events), then $\\text{Lt}(e)=0$.\n\n### 1.4.2. A relaxed variant of logical time\n\nOn some occasions we relax the definition of logical time, requesting only that\n\n$$\n\\text{Lt}(e)>\\text{Lt}(e')\\quad\\text{whenever $e\\succ e'$ (i.e., $e$ logically depends on $e'$),} \\quad (9)\n$$\n\nwithout insisting that $\\text{Lt}(e)$ be the smallest non-negative integer with this property. In such cases we can speak about *relaxed* logical time, as opposed to the *strict* [logical time](#1-4-1-logical-time). Notice, however, that the condition ([9](#1-4-2-a-relaxed-variant-of-logical-time)) is a fundamental property of logical time and cannot be relaxed further.\n\n### 1.4.3. Logical time intervals\n\nIt makes sense to assign to some events or collections of events $C$ an *interval* of logical times $\\text{Lt}^\\bullet(C)=[\\text{Lt}^-(C),\\text{Lt}^+(C))$, meaning that the collection of events $C$ took place in the specified \"interval\" of logical times, where $\\text{Lt}^-(C)<\\text{Lt}^+(C)$ are some integers (64-bit integers in practice). In this case, we can say that $C$ *begins* at logical time $\\text{Lt}^-(C)$, and *ends* at logical time $\\text{Lt}^+(C)$.\n\nBy default, we assume $\\text{Lt}^+(e)=\\text{Lt}(e)+1$ and $\\text{Lt}^-(e)=\\text{Lt}(e)$ for simple or \"atomic\" events, assuming that they last exactly one unit of logical time. In general, if we have a single value $\\text{Lt}(C)$ as well as logical time interval $\\text{Lt}^\\bullet(C)=[\\text{Lt}^-(C),\\text{Lt}^+(C))$, we always require that\n\n$$\n\\text{Lt}(C)\\in[\\text{Lt}^-(C),\\text{Lt}^+(C)) \\tag{10}\n$$\n\nor, equivalently,\n\n$$\n\\text{Lt}^-(C)\\leq\\text{Lt}(C)<\\text{Lt}^+(C) \\tag{11}\n$$\n\nIn most cases, we choose $\\text{Lt}(C)=\\text{Lt}^-(C)$.\n\n### 1.4.4. Requirements for logical time intervals\n\nThe three principal requirements for logical time intervals are:\n\n- $0\\leq\\text{Lt}^-(C)<\\text{Lt}^+(C)$ are non-negative integers for any collection of events $C$.\n- If $e'\\prec e$ (i.e., if an atomic event $e$ logically depends on another atomic event $e'$), then $\\text{Lt}^\\bullet(e')<\\text{Lt}^\\bullet(e)$ (i.e., $\\text{Lt}^+(e')\\leq\\text{Lt}^-(e)$).\n- If $C\\supset D$ (i.e., if a collection of events $C$ contains another collection of events $D$), then $\\text{Lt}^\\bullet(C)\\supset\\text{Lt}^\\bullet(D)$, i.e.,\n\n$$\n\\text{Lt}^-(C)\\leq\\text{Lt}^-(D)<\\text{Lt}^+(D)\\leq\\text{Lt}^+(C) \\tag{12}\n$$\n\nIn particular, if $C$ consists of atomic events $e_1$, ..., $e_n$, then $\\text{Lt}^-(C)\\leq\\inf_i\\text{Lt}^-(e_i)\\leq\\inf_i\\text{Lt}(e_i)$ and $\\text{Lt}^+(C)\\geq\\sup_i\\text{Lt}^+(e_i)\\geq 1+\\sup_i\\text{Lt}(e_i)$.\n\n### 1.4.5. Strict, or minimal, logical time intervals\n\nOne can assign to any finite collection of atomic events $E=\\{e\\}$ related by a causality relation (partial order) $\\prec$, and all subsets $C\\subset E$, *minimal* logical time intervals. That is, among all assignments of [logical time intervals](#1-4-4-requirements-for-logical-time-intervals) satisfying the conditions, we choose the one having all $\\text{Lt}^+(C)-\\text{Lt}^-(C)$ as small as possible, and if several assignments with this property exist, we choose the one that has the minimum $\\text{Lt}^-(C)$ as well.\n\nSuch an assignment can be achieved by first assigning [logical time](#1-4-1-logical-time) $\\text{Lt}(e)$ to all atomic events $e\\in E$, then setting $\\text{Lt}^-(C):=\\inf_{e\\in C}\\text{Lt}(e)$ and $\\text{Lt}^+(C):=1+\\sup_{e\\in C}\\text{Lt}(e)$ for any $C\\subset E$.\n\nIn most cases when we need to assign logical time intervals, we use the minimal logical time intervals just described.\n\n### 1.4.6. Logical time in the TON Blockchain\n\nThe TON Blockchain assigns logical time and logical time intervals to several of its components.\n\nFor instance, each outbound message created in a transaction is assigned its *logical creation time*; for this purpose, the creation of an outbound message is considered an atomic event, logically dependent on the previous message created by the same transaction, as well as on the previous transaction of the same account, on the inbound message processed by the same transaction, and on all events contained in the blocks referred to by hashes contained in the block with the same transaction. As a consequence, *outbound messages created by the same smart contract have strictly increasing logical creation times*. The transaction itself is considered a collection of atomic events, and is assigned a [logical time interval](#1-4-3-logical-time-intervals).\n\nEach block is a collection of transaction and message creation events, so it is assigned a logical time interval, explicitly mentioned in the header of the block.\n\n---\n\n## 1.5  Total blockchain state\n\nThis section discusses the total state of the TON Blockchain, as well as the states of separate shardchains and the masterchain. For example, the precise definition of the state of the neighboring shardchains becomes crucial for correctly formalizing the consistency condition asserting that the validators for a shardchain must [import the oldest messages](#2-2-5-logical-time-monotonicity%3A-importing-the-oldest-message-from-the-neighbors) from the union of *OutMsgQueues* taken from the states of all neighboring shardchains.\n\n### 1.5.1. Total state defined by a masterchain block\n\nEvery masterchain block contains a list of all currently active shards and of the latest blocks for each of them. In this respect, *every masterchain block defines the corresponding total state of the TON Blockchain, since it fixes the state of every shardchain, and of the masterchain as well*.\n\nAn important requirement imposed on this list of the latest blocks for all shardchain blocks is that, if a masterchain block $B$ lists $S$ as the latest block of some shardchain, and a newer masterchain block $B'$, with $B$ as one of its antecessors, lists $S'$ as the latest block of the same shardchain, then $S$ must be one of the antecessors of $S'$.<a id=\"ref-fn10\"></a><sup>[10](#fn10)</sup> This condition makes the total state of the TON blockchain defined by a subsequent masterchain block $B'$ compatible with the total state defined by a previous block $B$.\n\n### 1.5.2. Total state defined by a shardchain block\n\nEvery shardchain block contains the hash of the most recent masterchain block in its header. Consequently, all the blocks referred to in that masterchain block, along with their antecessors, are considered \"known\" or \"visible\" to the shardchain block, and no other blocks are visible to it, with the sole exception of its antecessors inside its proper shardchain.\n\nIn particular, when we say that a block *must* import in its *InMsgDescr* the messages from the *OutMsgQueue* of the states of all neighboring shardchains, it means that precisely the blocks of other shardchains visible to that block must be taken into account, and at the same time the block cannot contain messages from \"invisible\" blocks, even if they are otherwise correct.\n\n---\n\n## 1.6   Configurable parameters and smart contracts\n\nRecall that the TON Blockchain has several so-called [\"configurable parameters\"](/foundations/whitepapers/ton#2-1-21-configurable-parameters), which are either certain values or certain smart contracts residing in the masterchain. This section discusses the storage of and access to these configurable parameters.\n\n### 1.6.1. Examples of configurable parameters\n\nThe properties of the blockchain controlled by configurable parameters include:\n\n- The minimum stake for validators.\n- The maximum size of the group of elected validators.\n- The maximum number of blocks for which the same group of validators are responsible.\n- The validator election process.\n- The validator punishing process.\n- The currently active and the next elected set of validators.\n- The process of changing configurable parameters, and the address of the smart contract $\\gamma$ responsible for holding the values of the configurable parameters and for modifying their values.\n\n### 1.6.2. Location of the values of configurable parameters\n\nThe configurable parameters are kept in the persistent data of a special configuration smart contract $\\gamma$ residing in the masterchain of the TON Blockchain. More precisely, the first reference of the root cell of the persistent data of that smart contract is a dictionary mapping 64-bit keys (parameter numbers) to the values of the corresponding parameters; each value is serialized into a cell slice according to the type of that value. If a value is a \"smart contract\" (necessarily residing in the masterchain), its 256-bit account address is used instead.\n\n### 1.6.3. Quick access through the header of masterchain blocks\n\nTo simplify access to the current values of configurable parameters, and to shorten the Merkle proofs containing references to them, the header of each masterchain block contains the address of smart contract $\\gamma$. It also contains a direct cell reference to the dictionary containing all values of configurable parameters, which lies in the persistent data of $\\gamma$. Additional consistency conditions ensure that this reference coincides with the one obtained by inspecting the final state of smart contract $\\gamma$.\n\n### 1.6.4. Getting values of configurable parameters by get methods\n\nThe configuration smart contract $\\gamma$ provides access to some of configurable parameters by means of \"get methods\". These special methods of the smart contract do not change its state, but instead return required data in the TVM stack.\n\n### 1.6.5. Getting values of configurable parameters by get messages\n\nSimilarly, the configuration smart contract $\\gamma$ may define some \"ordinary\" methods (i.e., special inbound messages) to request the values of certain configuration parameters, which will be sent in the outbound messages generated by the transaction processing such an inbound message. This may be useful for some other fundamental smart contracts that need to know the values of certain configuration parameters.\n\n### 1.6.6. Values obtained by get methods may be different from those obtained through the block header\n\nNotice that the state of the configuration smart contract $\\gamma$, including the values of configurable parameters, may change several times inside a masterchain block, if there are several transactions processed by $\\gamma$ in that block. As a consequence, the values obtained by invoking get methods of $\\gamma$, or sending get messages to $\\gamma$, may be different from those obtained by inspecting the reference in the [block header](#1-6-3-quick-access-through-the-header-of-masterchain-blocks), which refers to the *final* state of the configurable parameters in the block.\n\n### 1.6.7. Changing the values of configurable parameters\n\nThe procedure for changing the values of configurable parameters is defined in the code of smart contract $\\gamma$. For most configurable parameters, called *ordinary*, any validator may suggest a new value by sending a special message with the number of the parameter and its proposed value to $\\gamma$. If the suggested value is valid, further voting messages from the validators are collected by the smart contract, and if more than two-thirds each of the current and next sets of validators support the proposal, the value is changed.\n\nSome parameters, such as the current set of validators, cannot be changed in this way. Instead, the current configuration contains a parameter with the address of smart contract $\\nu$ responsible for electing the next set of validators, and smart contract $\\gamma$ accepts messages only from this smart contract $\\nu$ to modify the value of the configuration parameter containing the current set of validators.\n\n### 1.6.8. Changing the validator election procedure\n\nIf the validator election procedure ever needs to be changed, this can be accomplished by first committing a new validator election smart contract into the masterchain, and then changing the ordinary configurable parameter containing the address $\\nu$ of the validator election smart contract. This will require two-thirds of the validators to [accept](#1-6-7-changing-the-values-of-configurable-parameters) the proposal in a vote.\n\n### 1.6.9. Changing the procedure of changing configurable parameters\n\nSimilarly, the address of the configuration smart contract itself is a configurable parameter and may be changed in this fashion. In this way, most fundamental parameters and smart contracts of the TON Blockchain may be modified in any direction agreed upon by the qualified majority of the validators.\n\n### 1.6.10. Initial values of the configurable parameters\n\nThe initial values of most configurable parameters appear in block zero of the masterchain as part of the masterchain's initial state, which is explicitly present with no omissions in this block. The code of all fundamental smart contracts is also present in the initial state. In this way, the original \"constitution\" and configuration of the TON Blockchain, including the original set of validators, is made explicit in block zero.\n\n---\n\n## 1.7   New smart contracts and their addresses\n\nThis section discusses the creation and initialization of new smart contracts—in particular, the origin of their initial code, persistent data, and balance. It also discusses the assignment of account addresses to new smart contracts.\n\n### 1.7.1. Description valid only for masterchain and basic workchain\n\nThe mechanisms for creating new smart contracts and assigning their addresses described in this section are valid only for the basic workchain and the masterchain. Other workchains may define their own mechanisms for dealing with these problems.\n\n### 1.7.2. Transferring cryptocurrency to uninitialized accounts\n\nFirst of all, *it is possible to send messages, including value-bearing messages, to previously unmentioned accounts*. If an inbound message arrives at a shardchain with a destination address $\\eta$ corresponding to an undefined account, it is processed by a transaction as if the code of the smart contract were empty (i.e., consisting of an implicit $\\texttt{RET}$). If the message is value-bearing, this leads to the creation of an \"uninitialized account\", which may have a non-zero balance (if value-bearing messages have been sent to it),<a id=\"ref-fn11\"></a><sup>[11](#fn11)</sup> but has no code and no data. Because even an uninitialized account occupies some persistent storage (needed to hold its balance), some small persistent-storage payments will be exacted from time to time from the account's balance, until it becomes negative.\n\n### 1.7.3. Initializing smart contracts by constructor messages\n\nAn account, or smart contract, is created by sending a special *constructor message* $M$ to its address $\\eta$. The body of such a message contains the tree of cells with the initial code of the smart contract (which may be replaced by its hash in some situations), and the initial data of the smart contract (maybe empty; it can be replaced by its hash). The hash of the code and of the data contained in the constructor message must coincide with the address $\\eta$ of the smart contract; otherwise, it is rejected.\n\nAfter the code and data of the smart contract are initialized from the body of the constructor message, the remainder of the constructor message is processed by a transaction (the *creating transaction* for smart contract $\\eta$) by invoking TVM in a manner similar to that used for processing ordinary inbound messages.\n\n### 1.7.4. Initial balance of a smart contract\n\nNotice that the constructor message usually must bear some value, which will be transferred to the balance of the newly-created smart contract; otherwise, the new smart contract would have a balance of zero and would not be able to pay for storing its code and data in the blockchain. The minimum balance required from a newly-created smart contract is a linear (more precisely, affine) function of the storage it uses. The coefficients of this function may depend on the workchain; in particular, they are higher in the masterchain than in the basic workchain.\n\n### 1.7.5. Creating smart contracts by external constructor messages\n\nIn some cases, it is necessary to create a smart contract by a constructor message that cannot bear any value—for instance, by a constructor message \"from nowhere\" (an external inbound message). Then one should first transfer a sufficient amount of funds to the [uninitialized smart contract](#1-7-2-transferring-cryptocurrency-to-uninitialized-accounts), and only then send a constructor message \"from nowhere\".\n\n### 1.7.6. Example: creating a cryptocurrency wallet smart contract\n\nAn example of the above situation is provided by cryptocurrency wallet applications for human users, which must create a special wallet smart contract in the blockchain in which to keep the user's funds. This can be achieved as follows:\n\n- The cryptocurrency wallet application generates a new cryptographic public/private key pair (typically for Ed25519 elliptic curve cryptography, supported by special TVM primitives) for signing the user's future transactions.\n- The cryptocurrency wallet application knows the code of the smart contract to be created (which typically is the same for all users), as well as the data, which typically consists of the public key of the wallet (or of its hash) and is generated at the very beginning. The hash of this information is the address $\\xi$ of the wallet smart contract to be created.\n- The wallet application may display the user's address $\\xi$, and the user may start to receive funds to her uninitialized account $\\xi$—for example, by buying some cryptocurrency at an exchange, or by asking a friend to transfer a small sum.\n- The wallet application can inspect the shardchain containing account $\\xi$ (in the case of a basic workchain account) or the masterchain (in the case of a masterchain account), either by itself or using a blockchain explorer, and check the balance of $\\xi$.\n- If the balance is sufficient, the wallet application may create and sign (with the user's private key) the constructor message (\"from nowhere\"), and submit it for inclusion to the validators or the collators for the corresponding blockchain.\n- Once the constructor message is included into a block of the blockchain and processed by a transaction, the wallet smart contract is finally created.\n- When the user wants to transfer some funds to some other user or smart contract $\\eta$, or wants to send a value-bearing message to $\\eta$, she uses her wallet application to create the message $m$ that she wants her wallet smart contract $\\xi$ to send to $\\eta$, envelope $m$ into a special \"message from nowhere\" $m'$ with destination $\\xi$, and sign $m'$ with her private key. Some provisions against [replay attacks](#2-2-1-message-uniqueness) must be made.\n- The wallet smart contract receives message $m'$ and checks the validity of the signature with the aid of the public key stored in its persistent data. If the signature is correct, it extracts embedded message $m$ from $m'$ and sends it to its intended destination $\\eta$, with the indicated amount of funds attached to it.\n- If the user does not need to immediately start transferring funds, but only wants to passively receive some funds, she may keep her account uninitialized as long as she wants (provided the persistent storage payments do not lead to the exhaustion of its balance), thus minimizing the storage profile and persistent storage payments of the account.\n- Notice that the wallet application may create for the human user the illusion that the funds are kept in the application itself, and provide an interface to transfer funds or send arbitrary messages \"directly\" from the user's account $\\xi$. In reality, all these operations will be performed by the user's wallet smart contract, which effectively acts as a proxy for such requests. We see that a cryptocurrency wallet is a simple example of a *mixed* application, having an on-chain part (the wallet smart contract, used as a proxy for outbound messages) and an off-chain part (the external wallet application running on a user's device and keeping the private account key).\n\nOf course, this is just one way of dealing with the simplest user wallet smart contracts. One can create multi-signature wallet smart contracts, or create a shared wallet with internal balances kept inside it for each of its individual users, and so on.\n\n### 1.7.7. Smart contracts may be created by other smart contracts\n\nNotice that a smart contract may generate and send a constructor message while processing any transaction. In this way, smart contracts may automatically create new smart contracts, if they need to, without any human intervention.\n\n### 1.7.8. Smart contracts may be created by wallet smart contracts\n\nOn the other hand, a user may compile the code for her new smart contract $\\nu$, generate the corresponding constructor message $m$, and use the wallet application to force her wallet smart contract $\\xi$ to send message $m$ to $\\nu$ with an adequate amount of funds, thus creating the new smart contract $\\nu$.\n\n---\n\n## 1.8   Modification and removal of smart contracts\n\nThis section explains how the code and state of a smart contract may be changed, and how and when a smart contract may be destroyed.\n\n### 1.8.1. Modification of the data of a smart contract\n\nThe persistent data of a smart contract is usually modified as a result of executing the code of the smart contract in TVM while processing a transaction, triggered by an inbound message to the smart contract. More specifically, the code of the smart contract has access to the old persistent storage of the smart contract via TVM control register $\\texttt{c4}$, and may modify the persistent storage by storing another value into $\\texttt{c4}$ before normal termination.\n\nNormally, there are no other ways to modify the data of an existing smart contract. If the code of the smart contract does not provide any ways to modify the persistent data (e.g., if it is a simple [wallet smart contract](#1-7-6-example%3A-creating-a-cryptocurrency-wallet-smart-contract), which initializes the persistent data with the user's public key and does not intend to ever change it), then it will be effectively immutable—unless the code of the smart contract is modified first.\n\n### 1.8.2. Modification of the code of a smart contract\n\nSimilarly, the code of an existing smart contract may be modified only if some provisions for such an upgrade are present in the current code. The code is modified by invoking TVM primitive $\\texttt{SETCODE}$, which sets the root of the code for the current smart contract from the top value in the TVM stack. The modification is applied only after the normal termination of the current transaction.\n\nTypically, if the developer of a smart contract wants to be able to upgrade its code in the future, she provides a special \"code upgrade method\" in the original code of the smart contract, which invokes $\\texttt{SETCODE}$ in response to certain inbound \"code upgrade\" messages, using the new code sent in the message itself as an argument to $\\texttt{SETCODE}$. Some provisions must be made to protect the smart contract from unauthorized replacement of the code; otherwise, control of the smart contract and the funds on its balance could be lost. For example, code upgrade messages might be accepted only from a trusted source address, or they might be protected by requiring a valid cryptographic signature and a correct sequence number.\n\n### 1.8.3. Keeping the code or data of the smart contract outside the blockchain\n\nThe code or data of the smart contract may be kept outside the blockchain and be represented only by their hashes. In such cases, only empty inbound messages may be processed, as well as messages carrying a correct copy of the smart-contract code (or its portion relevant for processing the specific message) and its data inside special fields. An example of such a situation is given by the [uninitialized smart contracts](#1-7-new-smart-contracts-and-their-addresses) and constructor messages.\n\n### 1.8.4. Using code libraries\n\nSome smart contracts may share the same code, but use different data. One example of this is [wallet smart contracts](#1-7-6-example%3A-creating-a-cryptocurrency-wallet-smart-contract), which are likely to use the same code (throughout all wallets created by the same software), but with different data (because each wallet must use its own pair of cryptographic keys). In this case, the code for all the wallet smart contracts is best committed by the developer into a shared *library*; this library would reside in the masterchain, and be referred to by its hash using a special \"external library cell reference\" as the root of the code of each wallet smart contract (or as a subtree inside that code).\n\nNotice that even if the library code becomes unavailable—for example, because its developer stops paying for its storage in the masterchain—it is still possible to use the smart contracts referring to this library, either by committing the library again into the masterchain, or by including its relevant parts inside a message sent to the smart contract. This [external cell reference](#4-4-3-smart-contract-library-environment) resolution mechanism is discussed in more detail later.\n\n### 1.8.5. Destroying smart contracts\n\nNotice that a smart contract cannot really be destroyed until its balance becomes zero or negative. It may become negative as a result of collecting persistent storage payments, or after sending a value-bearing outbound message transferring almost all of its previous balance.\n\nFor example, a user may decide to transfer all remaining funds from her wallet to another wallet or smart contract. This may be useful, for instance, if one wants to upgrade the wallet, but the wallet smart contract does not have any provisions for future upgrades; then one can simply create a new wallet and transfer all funds to it.\n\n### 1.8.6. Frozen accounts\n\nWhen the balance of an account becomes non-positive after a transaction, or smaller than a certain workchain-dependent minimum, the account is *frozen* by replacing all its code and data by a single 32-byte hash. This hash is kept afterwards for some time (e.g., a couple of months) to prevent recreation of the smart contract by its original creating transaction (which still has the correct hash, equal to the account address), and to allow its owner to recreate the account by transferring some funds and sending a message containing the account's code and data, to be reinstated in the blockchain. In this respect, frozen accounts are similar to uninitialized accounts; however, the hash of the correct code and data for a frozen account is not necessarily equal to the account address, but is kept separately.\n\nNotice that frozen accounts may have a negative balance, indicating that persistent storage payments are due. An account cannot be unfrozen until its balance becomes positive and larger than a prescribed minimum value.\n\n---\n\n# 2   Message forwarding and delivery guarantees\n\nThis chapter discusses the forwarding of messages inside the TON Blockchain, including the Hypercube Routing (HR) and Instant Hypercube Routing (IHR) protocols. It also describes the provisions required to implement the message delivery guarantees and the FIFO ordering guarantee.\n\n## 2.1  Message addresses and next-hop computation\n\nThis section explains the computation of transit and next-hop addresses by the variant of the hypercube routing algorithm employed in TON Blockchain. The hypercube routing protocol itself, which uses the concepts and next-hop address computation algorithm introduced in this section, is presented in the next section.\n\n### 2.1.1. Account addresses\n\nThe *source address* and *destination address* are always present in any message. Normally, they are *(full) account addresses*. A full account address consists of a $\\mathit{workchain\\_id}$ (a signed 32-bit big-endian integer defining a workchain), followed by a (usually) 256-bit *internal address* or *account identifier* $\\mathit{account\\_id}$ (which may also be interpreted as an unsigned big-endian integer) defining the account within the chosen workchain.\n\nDifferent workchains may use account identifiers that are shorter or longer than the \"standard\" 256 bits used in the masterchain ($\\mathit{workchain\\_id}=-1$) and in the basic workchain ($\\mathit{workchain\\_id}=0$). To this end, the masterchain state contains a list of all workchains defined so far, along with their account identifier lengths. An important restriction is that the $\\mathit{account\\_id}$ for any workchain must be at least 64 bits long.\n\nIn what follows, we often consider only the case of 256-bit account addresses for simplicity. Only the first 64 bits of the $\\mathit{account\\_id}$ are relevant for the purposes of message routing and shardchain splitting.\n\n### 2.1.2. Source and destination addresses of a message\n\nAny message has both a *source address* and a *destination address*. Its source address is the address of the account (smart contract) that has created the message while processing some transaction; the source address cannot be changed or set arbitrarily, and smart contracts heavily rely on this property. By contrast, when a message is created, any well-formed destination address may be chosen; after that, the destination address cannot be changed.\n\n### 2.1.3. External messages with no source or destination address\n\nSome messages can have no source or no destination address (though at least one of them must be present), as indicated by special flags in the message header. Such messages are the *external messages* intended for the interaction of the TON Blockchain with the outside world—human users and their cryptowallet applications, off-chain and mixed applications and services, other blockchains, and so on.\n\nExternal messages are never routed inside the TON Blockchain. Instead, \"messages from nowhere\" (i.e., with no source address) are directly included into the *InMsgDescr* of a destination shardchain block (provided some conditions are met) and processed by a transaction in that very block. Similarly, \"messages to nowhere\" (i.e., with no TON Blockchain destination address), also known as *log messages*, are also present only in the block containing the transaction that generated such a message.<a id=\"ref-fn12\"></a><sup>[12](#fn12)</sup>\n\nTherefore, external messages are almost irrelevant for the discussion of message routing and message delivery guarantees. In fact, the message delivery guarantees for outbound external messages are trivial (at most, the message must be included into the *LogMsg* part of the block), and for inbound external messages there are none, since the validators of a shardchain block are free to include or ignore suggested inbound external messages at their discretion (e.g., according to the processing fee offered by the message).<a id=\"ref-fn13\"></a><sup>[13](#fn13)</sup>\n\nIn what follows, we focus on \"usual\" or \"internal\" messages, which have both a source and a destination address.\n\n### 2.1.4. Transit and next-hop addresses\n\nWhen a message needs to be routed through intermediate shardchains before reaching its intended destination, it is assigned a *transit address* and a *next-hop address* in addition to the (immutable) source and destination addresses. When a copy of the message resides inside a transit shardchain awaiting its relay to its next hop, the *transit address* is its intermediate address lying in the transit shardchain, as if belonging to a special message-relay smart contract whose only job is to relay the unchanged message to the next shardchain on the route. The *next-hop address* is the address in a neighboring shardchain (or, on some rare occasions, in the same shardchain) to which the message needs to be relayed. After the message is relayed, the next-hop address usually becomes the transit address of the copy of the message included in the next shardchain.\n\nImmediately after an outbound message is created in a shardchain (or in the masterchain), its transit address is set to its source address.<a id=\"ref-fn14\"></a><sup>[14](#fn14)</sup>\n\n### 2.1.5. Computation of the next-hop address for hypercube routing\n\nThe TON Blockchain employs a variant of hypercube routing. This means that the next-hop address is computed from the transit address (originally equal to the source address) as follows:\n\n1. The (big-endian signed) 32-bit $\\mathit{workchain\\_id}$ components of both the transit address and destination address are split into groups of $n_1$ bits (currently, $n_1=32$), and they are scanned from the left (i.e., the most significant bits) to the right. If one of the groups in the transit address differs from the corresponding group in the destination address, then the value of this group in the transit address is replaced by its value in the destination address to compute the next-hop address.\n\n2. If the $\\mathit{workchain\\_id}$ parts of the transit and destination addresses match, then a similar process is applied to the $\\mathit{account\\_id}$ parts of the addresses: $\\mathit{account\\_id}$ parts, or rather their first (most significant) 64 bits, are split into groups of $n_2$ bits (currently, $n_2=4$ bit groups are used, corresponding to the hexadecimal digits of the address) starting from the most significant bit, and are compared starting from the left. The first group that differs is replaced in the transit address with its value in the destination address to compute the next-hop address.\n\n3. If the first 64 bits of the $\\mathit{account\\_id}$ parts of the transit and destination addresses match as well, then the destination account belongs to the current shardchain, and the message should not be forwarded outside the current shardchain at all. Instead, it must be processed by a transaction inside it.\n\n### 2.1.6. Notation for the next-hop address\n\nWe denote by\n\n$$\n\\text{NextHop}(\\xi,\\eta) \\tag{13}\n$$\n\nthe next-hop address computed for current (source or transit) address $\\xi$ and destination address $\\eta$.\n\n### 2.1.7. Support for anycast addresses\n\n\"Large\" smart contracts, which can have separate instances in different shardchains, may be reached using *anycast destination addresses*. These addresses are supported as follows.\n\nAn anycast address $(\\eta,d)$ consists of a usual address $\\eta$ along with its \"splitting depth\" $d\\leq 31$. The idea is that the message may be delivered to any address differing from $\\eta$ only in the first $d$ bits of the internal address part (i.e., not including the workchain identifier, which must match exactly). This is achieved as follows:\n\n- The effective destination address $\\tilde\\eta$ is computed from $(\\eta,d)$ by replacing the first $d$ bits of the internal address part of $\\eta$ with the corresponding bits taken from the source address $\\xi$.\n- All computations of $\\text{NextHop}(\\nu,\\eta)$ are replaced by $\\text{NextHop}(\\nu,\\tilde\\eta)$, for $\\nu=\\xi$ as well as for all other intermediate addresses $\\nu$. In this way, Hypercube Routing or Instant Hypercube Routing will ultimately deliver the message to the shardchain containing $\\tilde\\eta$.\n- When the message is processed in its destination shardchain (the one containing address $\\tilde\\eta$), it may be processed by an account $\\eta'$ of the same shardchain differing from $\\eta$ and $\\tilde\\eta$ only in the first $d$ bits of the internal address part. More precisely, if the common shard address prefix is $s$, so that only internal addresses starting with binary string $s$ belong to the destination shard, then $\\eta'$ is computed from $\\eta$ by replacing the first $\\min(d,|s|)$ bits of the internal address part of $\\eta$ with the corresponding bits of $s$.\n\nThat said, we tacitly ignore the existence of anycast addresses and the additional processing they require in the following discussions.\n\n### 2.1.8 Hamming optimality of the next-hop address algorithm\n\nNotice that the specific [hypercube routing](#2-1-5-computation-of-the-next-hop-address-for-hypercube-routing) next-hop computation algorithm  may potentially be replaced by another algorithm, provided it satisfies certain properties. One of these properties is the *Hamming optimality*, meaning that the Hamming ($L_1$) distance from $\\xi$ to $\\eta$ equals the sum of Hamming distances from $\\xi$ to $\\text{NextHop}(\\xi,\\eta)$ and from $\\text{NextHop}(\\xi,\\eta)$ to $\\eta$:\n\n$$\n\\|\\xi-\\eta\\|_1=\\bigl\\|\\xi-\\text{NextHop}(\\xi,\\eta)\\bigr\\|_1+\\bigl\\|\\text{NextHop}(\\xi,\\eta)-\\eta\\bigr\\|_1 \\quad (14)\n$$\n\nHere $\\|\\xi-\\eta\\|_1$ is the Hamming distance between $\\xi$ and $\\eta$, equal to the number of bit positions in which $\\xi$ and $\\eta$ differ:<a id=\"ref-fn15\"></a><sup>[15](#fn15)</sup>\n\n$$\n\\|\\xi-\\eta\\|_1=\\sum_i|\\xi_i-\\eta_i| \\quad (15)\n$$\n\nNotice that in general one should expect only an inequality in ([14](#2-1-8-hamming-optimality-of-the-next-hop-address-algorithm)), following from the triangle inequality for the $L_1$-metric. Hamming optimality essentially means that $\\text{NextHop}(\\xi,\\eta)$ lies on one of the (Hamming) shortest paths from $\\xi$ to $\\eta$. It can also be expressed by saying that $\\nu=\\text{NextHop}(\\xi,\\eta)$ is always obtained from $\\xi$ by changing the values of bits at some positions to their values in $\\eta$: for any bit position $i$, we have $\\nu_i=\\xi_i$ or $\\nu_i=\\eta_i$.<a id=\"ref-fn16\"></a><sup>[16](#fn16)</sup>\n\n### 2.1.9. Non-stopping of NextHop\n\nAnother important property of the $\\text{NextHop}$ is its *non-stopping*, meaning that $\\text{NextHop}(\\xi,\\eta)=\\xi$ is possible only when $\\xi=\\eta$. In other words, if we have not yet arrived at $\\eta$, the next hop cannot coincide with our current position.\n\nThis property implies that the path from $\\xi$ to $\\eta$—i.e., the sequence of intermediate addresses $\\xi^{(0)}:=\\xi$, $\\xi^{(n)}:=\\text{NextHop}(\\xi^{(n-1)},\\eta)$—will gradually stabilize at $\\eta$: for some $N\\geq0$, we have $\\xi^{(n)}=\\eta$ for all $n\\geq N$. Indeed, one can always take $N:=\\|\\xi-\\eta\\|_1$.\n\n### 2.1.10. Convexity of the HR path with respect to sharding\n\nA consequence of Hamming optimality property ([14](#2-1-8-hamming-optimality-of-the-next-hop-address-algorithm)) is what we call the *convexity* of the path from $\\xi$ to $\\eta$ with respect to sharding. Namely, if $\\xi^{(0)}:=\\xi$, $\\xi^{(n)}:=\\text{NextHop}(\\xi^{(n-1)},\\eta)$ is the computed path from $\\xi$ to $\\eta$, and $N$ is the first index such that $\\xi^{(N)}=\\eta$, and $S$ is a shard of some workchain in any shard configuration, then the indices $i$ with $\\xi^{(i)}$ residing in shard $S$ constitute a subinterval in $[0,N]$. In other words, if integers $0\\leq i\\leq j\\leq k\\leq N$ are such that $\\xi^{(i)}$, $\\xi^{(k)}\\in S$, then $\\xi^{(j)}\\in S$ as well.\n\nThis convexity property is important for some proofs related to message forwarding in the presence of dynamic sharding.\n\n### 2.1.11. Internal routing\n\nNotice that the [next-hop address computed](#2-1-5-computation-of-the-next-hop-address-for-hypercube-routing) according to the rules may belong to the same shardchain as the current one (i.e., the one containing the transit address). In that case, the \"internal routing\" occurs immediately, the transit address is replaced by the value of the computed next-hop address, and the next-hop address computation step is repeated until a next-hop address lying outside the current shardchain is obtained. The message is then kept in the transit output queue according to its computed next-hop address, with its last computed transit address as the \"intermediate owner\" of the transit message. If the current shardchain splits into two shardchains before the message is forwarded further, it is the shardchain containing the intermediate owner that inherits this transit message.\n\nAlternatively, we might go on computing the next-hop addresses only to find out that the destination address already belongs to the current shardchain. In that case, the message will be processed (by a transaction) inside this shardchain instead of being forwarded further.\n\n### 2.1.12. Neighboring shardchains\n\nTwo shards in a shard configuration—or the two corresponding shardchains—are said to be *neighbors*, or *neighboring shardchains*, if one of them contains a next-hop address for at least one combination of allowed source and destination addresses, while the other contains the transit address for the same combination. In other words, two shardchains are neighbors if a message can be forwarded directly from one of them into the other via Hypercube Routing.\n\nThe masterchain is also included in this definition, as if it were the only shardchain of the workchain with $\\mathit{workchain\\_id}=-1$. In this respect, it is a neighbor of all the other shardchains.\n\n### 2.1.13. Any shard is a neighbor of itself\n\nNotice that a shardchain is always considered a neighbor of itself. This may seem redundant, because we always repeat the [next-hop computation](#2-1-5-computation-of-the-next-hop-address-for-hypercube-routing) until we obtain a next-hop address [outside](#2-1-11-internal-routing) the current shardchain. However, there are at least two reasons for such an arrangement:\n\n- Some messages have the source and the destination address inside the same shardchain, at least when the message is created. However, if such a message is not processed immediately in the same block where it has been created, it must be added to the outbound message queue of its shardchain, and be imported as an inbound message (with an entry in the *InMsgDescr*) in one of the subsequent blocks of the same shardchain.<a id=\"ref-fn17\"></a><sup>[17](#fn17)</sup>\n- Alternatively, the next-hop address may originally be in some other shardchain that later gets merged with the current shardchain, so that the next hop becomes inside the same shardchain. Then the message will have to be imported from the outbound message queue of the merged shardchain, and forwarded or processed accordingly to its next-hop address, even though they reside now inside the same shardchain.\n\n### 2.1.14. Hypercube Routing and the ISP\n\nUltimately, the Infinite Sharding Paradigm (ISP) applies here: a shardchain should be considered a provisional union of accountchains, grouped together solely to minimize the block generation and transmission overhead.\n\nThe forwarding of a message runs through several intermediate accountchains, some of which can happen to lie in the same shard. In this case, once a message reaches an accountchain lying in this shard, it is immediately [\"internally\" routed](#2-1-11-internal-routing) inside that shard until the last accountchain lying in the same shard is reached. Then the message is enqueued in the output queue of that last accountchain.<a id=\"ref-fn18\"></a><sup>[18](#fn18)</sup>\n\n### 2.1.15. Representation of transit and next-hop addresses\n\nNotice that the transit and next-hop addresses differ from the source address only in the $\\mathit{workchain\\_id}$ and in the first (most significant) 64 bits of the account address. Therefore, they may be represented by 96-bit strings. Furthermore, their $\\mathit{workchain\\_id}$ usually coincides with the $\\mathit{workchain\\_id}$ of either the source address or the destination address; a couple of bits may be used to indicate this situation, thus further reducing the space required to represent the transit and next-hop addresses.\n\nIn fact, the required storage may be reduced even further by observing that the specific [hypercube routing](#2-1-5-computation-of-the-next-hop-address-for-hypercube-routing) algorithm always generates intermediate (i.e., transit and next-hop) addresses that coincide with the destination address in their first $k$ bits, and with the source address in their remaining bits. Therefore, one might use just the values $0\\leq k_{\\text{tr}},k_{\\text{nh}}\\leq 96$ to fully specify the transit and next-hop addresses. One might also notice that $k':=k_{\\text{nh}}$ turns out to be a fixed function of $k:=k_{\\text{tr}}$ (for instance, $k'=k+n_2=k+4$ for $k\\geq32$), and therefore include only one 7-bit value of $k$ in the serialization.\n\nSuch optimizations have the obvious disadvantage that they rely too much on the specific routing algorithm used, which can be changed in the future, so they are used in [Enveloped messages](#3-1-15-enveloped-messages) with a provision to specify more general intermediate addresses if necessary.\n\n### 2.1.16. Message envelopes\n\nThe transit and next-hop addresses of a forwarded message are not included in the message itself, but are kept in a special *message envelope*, which is a cell (or a cell slice) containing the transit and next-hop addresses with the above optimizations, some other information relevant for forwarding and processing, and a reference to a cell containing the unmodified original message. In this way, a message can easily be \"extracted\" from its original envelope (e.g., the one present in the *InMsgDescr*) and be put into another envelope (e.g., before being included into the *OutMsgQueue*).\n\nIn the representation of a block as a tree, or rather a DAG, of cells, the two different envelopes will contain references to a shared cell with the original message. If the message is large, this arrangement avoids the need to keep more than one copy of the message in the block.\n\n---\n\n## 2.2   Hypercube Routing protocol\n\nThis section exposes the details of the hypercube routing protocol employed by the TON Blockchain to achieve guaranteed delivery of messages between smart contracts residing in arbitrary shardchains. For the purposes of this document, we will refer to the variant of hypercube routing employed by the TON Blockchain as Hypercube Routing (HR).\n\n### 2.2.1. Message uniqueness\n\nBefore continuing, let us observe that any (internal) message is *unique*. Recall that a message contains its full source address along with its logical creation time, and all outbound messages created by the same smart contract have strictly increasing [logical creation times](#1-4-6-logical-time-in-the-ton-blockchain); therefore, the combination of the full source address and the logical creation time uniquely defines the message. Since we assume the chosen hash function SHA-256 to be collision resistant, *a message is uniquely determined by its hash*, so we can identify two messages if we know that their hashes coincide.\n\nThis does not extend to external messages \"from nowhere\", which have no source addresses. Special care must be taken to prevent replay attacks related to such messages, especially by designers of user wallet smart contracts. One possible solution is to include a sequence number in the body of such messages, and keep the count of external messages already processed inside the smart-contract persistent data, refusing to process an external message if its sequence number differs from this count.\n\n### 2.2.2. Identifying messages with equal hashes\n\nThe TON Blockchain assumes that two messages with the same hashes coincide, and treats either of them as a redundant copy of the other. [Message uniqueness](#2-2-1-message-uniqueness) does not lead to any unexpected effects for internal messages. However, if one sends two coinciding \"messages from nowhere\" to a smart contract, it may happen that only one of them will be delivered—or both. If their action is not supposed to be idempotent (i.e., if processing the message twice has a different effect from processing it once), some provisions should be made to distinguish the two messages, for instance by including a sequence number in them.\n\nIn particular, the *InMsgDescr* and  *OutMsgDescr* use the (unenveloped) message hash as a key, tacitly assuming that distinct messages have distinct hashes. In this way, one can trace the path and the fate of a message across different shardchains by looking up the message hash in the *InMsgDescr* and *OutMsgDescr* of different blocks.\n\n### 2.2.3. The structure of *OutMsgQueue*\n\nRecall that the outbound messages—both those created inside the shardchain, and transit messages previously imported from a neighboring shardchain to be relayed to the next-hop shardchain—are accumulated in the [OutMsgQueue](#1-2-7-outbound-message-queue-of-a-shardchain), which is part of the state of the shardchain. In contrast with *InMsgDescr* and *OutMsgDescr*, the key in *OutMsgQueue* is not the message hash, but its next-hop address—or at least its first 96 bits—concatenated with the message hash.\n\nFurthermore, the *OutMsgQueue* is not just a dictionary (hashmap), mapping its keys into (enveloped) messages. Rather, it is a *min-augmented dictionary with respect to the logical creation time*, meaning that each node of the Patricia tree representing *OutMsgQueue* has an additional value (in this case, an unsigned 64-bit integer), and that this augmentation value in each fork node is set to be equal to the minimum of the augmentation values of its children. The augmentation value of a leaf equals the logical creation time of the message contained in that leaf; it need not be stored explicitly.\n\n### 2.2.4. Inspecting the *OutMsgQueue* of a neighbor\n\nSuch a structure for the *OutMsgQueue* enables the validators of a neighboring shardchain to inspect it to find its part (Patricia subtree) relevant to them (i.e., consisting of messages with the next-hop address belonging to the neighboring shard in question—or having the next-hop address with a given binary prefix), as well as quickly compute the \"oldest\" (i.e., with the minimum logical creation time) message in that part.\n\nFurthermore, the shard validators do not even need to track the total state of all their neighboring shardchains—they only need to keep and update a copy of their *OutMsgQueue*, or even of its subtree related to them.\n\n### 2.2.5. Logical time monotonicity: importing the oldest message from the neighbors\n\nThe first fundamental local condition of message forwarding, called *(message import) (logical time) monotonicity condition*, may be summarized as follows:\n\n> While importing messages into the *InMsgDescr* of a shardchain block from the *OutMsgQueues* of its neighboring shardchains, the validators must import the messages in the increasing order of their logical time; in the case of a tie, the message with the smaller hash is imported first.\n\nMore precisely, each shardchain block contains the hash of a masterchain block (assumed to be \"the latest\" masterchain block at the time of the shardchain block's creation), which in turn contains the hashes of the most recent shardchain blocks. In this way, each shardchain block indirectly \"knows\" the most recent state of all other shardchains, and especially its neighboring shardchains, including their *OutMsgQueues*.<a id=\"ref-fn19\"></a><sup>[19](#fn19)</sup>\n\nNow an alternative equivalent formulation of the monotonicity condition is as follows:\n\n> If a message is imported into the *InMsgDescr* of the new block, its logical creation time cannot be greater than that of any message left unimported in the *OutMsgQueue* of the most recent state of any of the neighboring shardchains.\n\nIt is this form of the monotonicity condition that appears in the local consistency conditions of the TON Blockchain blocks and is enforced by the validators.\n\n### 2.2.6 Witnesses to violations of the message import logical time monotonicity condition\n\nNotice that if this condition is not fulfilled, a small Merkle proof witnessing its failure may be constructed. Such a proof will contain:\n\n- A path in the *OutMsgQueue* of a neighbor from the root to a certain message $m$ with small logical creation time.\n- A path in the *InMsgDescr* of the block under consideration showing that the key equal to $\\text{Hash}(m)$ is absent in *InMsgDescr* (i.e., that $m$ has not been included in the current block).\n- A proof that $m$ has not been included in a preceding block of the same shardchain, using the block header information containing the smallest and the largest logical time of all messages imported into the block ([2.3.4](#2-3-4-checking-whether-a-message-has-already-been-delivered-to-its-final-destination)–[2.3.7](#2-3-7-checking-whether-an-hr-message-has-already-been-delivered-via-ihr-to-its-final-destination) for more information).\n- A path in *InMsgDescr* to another included message $m'$, such that either $\\text{Lt}(m')>\\text{Lt}(m)$, or $\\text{Lt}(m')=\\text{Lt}(m)$ and $\\text{Hash}(m')>\\text{Hash}(m)$.\n\n### 2.2.7. Deleting a message from *OutMsgQueue*\n\nA message must be deleted from *OutMsgQueue* sooner or later; otherwise, the storage used by *OutMsgQueue* would grow to infinity. To this end, several \"garbage collection rules\" are introduced. They allow the deletion of a message from *OutMsgQueue* during the evaluation of a block only if an explicit special \"delivery record\" is present in the *OutMsgDescr* of that block. This record contains either a reference to the neighboring shardchain block that has included the message into its *InMsgDescr* (the hash of the block is sufficient, but collated material for the block may contain the relevant Merkle proof), or a Merkle proof of the fact that the message has been delivered to its final destination via Instant Hypercube Routing.\n\n### 2.2.8. Guaranteed message delivery via Hypercube Routing\n\nIn this way, a message cannot be [deleted](#2-2-7-deleting-a-message-from-outmsgqueue) from the outbound message queue unless it has been either relayed to its next-hop shardchain or delivered to its final destination. Meanwhile, the message import [monotonicity condition](#2-2-5-logical-time-monotonicity%3A-importing-the-oldest-message-from-the-neighbors) ensures that any message will sooner or later be relayed into the next shardchain, taking into account other conditions which require the validators to use at least half of the block's space or gas limits for importing inbound internal messages (otherwise the validators might choose to create empty blocks or import only external messages even in the presence of non-empty outbound message queues at their neighbors).\n\n### 2.2.9 Message processing order\n\nWhen several imported messages are processed by transactions inside a block, the *message processing order conditions* ensure that older messages are processed first. More precisely, if a block contains two transactions $t$ and $t'$ of the same account, which process inbound messages $m$ and $m'$, respectively, and $\\text{Lt}(m)<\\text{Lt}(m')$, then we must have $\\text{Lt}(t)<\\text{Lt}(t')$.\n\n### 2.2.10 FIFO guarantees of Hypercube Routing\n\nThe [message processing order](#2-2-9-message-processing-order) conditions, along with the message import [monotonicity conditions](#2-2-5-logical-time-monotonicity%3A-importing-the-oldest-message-from-the-neighbors), imply the *FIFO guarantees for Hypercube Routing*. Namely, if a smart contract $\\xi$ creates two messages $m$ and $m'$ with the same destination $\\eta$, and $m'$ is generated later than $m$ (meaning that $m\\prec m'$, hence $\\text{Lt}(m)<\\text{Lt}(m')$), then $m$ will be processed by $\\eta$ before $m'$. This is so because both messages will follow the same routing steps on the path from $\\xi$ to $\\eta$ (the [Hypercube Routing](#2-1-5-computation-of-the-next-hop-address-for-hypercube-routing) algorithm is deterministic), and in all outbound queues and inbound message descriptions $m'$ will appear \"after\" $m$.<a id=\"ref-fn20\"></a><sup>[20](#fn20)</sup>\n\nIf message $m'$ can be delivered to $B$ via Instant Hypercube Routing, this is not necessarily true anymore. Therefore, a simple way of ensuring FIFO message delivery discipline between a pair of smart contracts consists in setting a special bit in the message header preventing its delivery via IHR.\n\n### 2.2.11. Delivery uniqueness guarantees of Hypercube Routing\n\nNotice that the message import monotonicity conditions also imply the *uniqueness* of the delivery of any message via Hypercube Routing—i.e., that it cannot be imported and processed by the destination smart contract more than once. [Enforcing](#2-3-instant-hypercube-routing-and-combined-delivery-guarantees) delivery uniqueness when both Hypercube Routing and Instant Hypercube Routing are active is more complicated.\n\n### 2.2.12 An overview of Hypercube Routing\n\nLet us summarize all routing steps performed to deliver an internal message $m$ created by source account $\\xi_0$ to destination account $\\eta$. We denote by $\\xi_{k+1}:=\\text{NextHop}(\\xi_k,\\eta)$, $k=0,1,2,\\ldots$ the intermediate addresses dictated by HR for forwarding the message $m$ to its final destination $\\eta$. Let $S_k$ be the shard containing $\\xi_k$.\n\n- [Birth] — Message $m$ with destination $\\eta$ is created by a transaction $t$ belonging to an account $\\xi_0$ residing in some shardchain $S_0$. The logical creation time $\\text{Lt}(m)$ is fixed at this point and included into the message $m$.\n\n- [ImmediateProcessing?] — If the destination $\\eta$ resides in the same shardchain $S_0$, the message may be processed in the same block it was generated in. In this case, $m$ is included into *OutMsgDescr* with a flag indicating it has been processed in this very block and need not be forwarded further. Another copy of $m$ is included into *InMsgDescr*, along with the usual data describing the processing of inbound messages. (Notice that $m$ is not included into the *OutMsgQueue* of $S_0$.)\n\n- [InitialInternalRouting] — If $m$ either has a destination outside $S_0$, or is not processed in the same block where it was generated, the [internal routing](#2-1-11-internal-routing) procedure is applied, until an index $k$ is found such that $\\xi_k$ lies in $S_0$, but $\\xi_{k+1}=\\text{NextHop}(\\xi_k,\\eta)$ does not (i.e., $S_k=S_0$, but $S_{k+1}\\neq S_0$). Alternatively, this process stops if $\\xi_k=\\eta$ or $\\xi_k$ coincides with $\\eta$ in its first 96 bits.\n\n- [OutboundQueuing] — The message $m$ is included into *OutMsgDescr* (with the key equal to its hash), with an [envelope](#2-1-16-message-envelopes) containing its [transit address](#2-1-15-representation-of-transit-and-next-hop-addresses) $\\xi_k$ and next-hop address $\\xi_{k+1}$. The same enveloped message is also included in the *OutMsgQueue* of the state of $S_k$, with the key equal to the concatenation of the first 96 bits of its next-hop address $\\xi_{k+1}$ (which may be equal to $\\eta$ if $\\eta$ belongs to $S_k$) and the message hash $\\text{Hash}(m)$.\n\n- [QueueWait] — Message $m$ waits in the *OutMsgQueue* of shardchain $S_k$ to be forwarded further. In the meantime, shardchain $S_k$ may split or merge with other shardchains; in that case, the new shard $S'_k$ containing the transit address $\\xi_k$ inherits $m$ in its *OutMsgQueue*.\n\n- [ImportInbound] — At some point in the future, the validators for the shardchain $S_{k+1}$ containing the next-hop address $\\xi_{k+1}$ scan the *OutMsgQueue* in the state of shardchain $S_k$ and decide to import message $m$ in keeping with the [monotonicity condition](#2-2-5-logical-time-monotonicity%3A-importing-the-oldest-message-from-the-neighbors) and other conditions. A new block for shardchain $S_{k+1}$ is generated, with an enveloped copy of $m$ included in its *InMsgDescr*. The entry in *InMsgDescr* contains also the reason for importing $m$ into this block, with a hash of the most recent block of shardchain $S'_k$, and the previous next-hop and transit addresses $\\xi_k$ and $\\xi_{k+1}$, so that the corresponding entry in the *OutMsgQueue* of $S'_k$ can be easily located.\n\n- [Confirmation] — This entry in the *InMsgDescr* of $S_{k+1}$ also serves as a confirmation for $S'_k$. In a later block of $S'_k$, message $m$ must be removed from the *OutMsgQueue* of $S'_k$; this modification is reflected in a special entry in the *OutMsgDescr* of the block of $S'_k$ that performs this state modification.\n\n- [Forwarding?] — If the final destination $\\eta$ of $m$ does not reside in $S_{k+1}$, the message is *forwarded*. Hypercube Routing is applied until some $\\xi_l$, $l>k$, and $\\xi_{l+1}=\\text{NextHop}(\\xi_l,\\eta)$ are obtained, such that $\\xi_l$ lies in $S_{k+1}$, but $\\xi_{l+1}$ [does not](#2-1-11-internal-routing). After that, a newly-enveloped copy of $m$ with transit address set to $\\xi_l$ and next-hop address $\\xi_{l+1}$ is included into both the *OutMsgDescr* of the current block of $S_{k+1}$ and the *OutMsgQueue* of the new state of $S_{k+1}$. The entry of $m$ in *InMsgDescr* contains a flag indicating that the message has been forwarded; the entry in *OutMsgDescr* contains the newly-enveloped message and a flag indicating that this is a forwarded message. Then all the steps starting from [OutboundQueueing] are repeated, for $l$ instead of $k$.\n\n- [Processing?] — If the final destination $\\eta$ of $m$ resides in $S_{k+1}$, then the block of $S_{k+1}$ that imported the message must process it by a transaction $t$ included in the same block. In this case, *InMsgDescr* contains a reference to $t$ by its logical time $\\text{Lt}(t)$, and a flag indicating that the message has been processed.\n\nThe above message routing algorithm does not take into account some further modifications required to implement Instant Hypercube Routing (IHR). For instance, a message may be *discarded* after being imported (listed in *InMsgDescr*) into its final or intermediate shardchain block, because a proof of delivery via IHR to the final destination is presented. In this case, such a proof must be included into *InMsgDescr* to explain why the message was not forwarded further or processed.\n\n\n## 2.3   Instant Hypercube Routing and combined delivery guarantees\n\nThis section describes the Instant Hypercube Routing protocol, normally applied by TON Blockchain in parallel to the previously discussed Hypercube Routing protocol to achieve faster message delivery. However, when both Hypercube Routing and Instant Hypercube Routing are applied to the same message in parallel, achieving delivery and unique delivery guarantees is more complicated. This topic is also discussed in this section.\n\n### 2.3.1. An overview of Instant Hypercube Routing\n\nLet us explain the major steps applied when the Instant Hypercube Routing (IHR) mechanism is applied to a message. (Notice that normally both the usual HR and IHR work in parallel for the same message; some provisions must be taken to guarantee the uniqueness of delivery of any message.)\n\nConsider the [routing](#2-2-12-an-overview-of-hypercube-routing) and delivery of the same message $m$ with source $\\xi$ and destination $\\eta$:\n\n- [NetworkSend] — After the validators of $S_0$ have agreed on and signed the block containing the creating transaction $t$ for $m$, and observed that the destination $\\eta$ of $m$ does not reside inside $S_0$, they may send a datagram (encrypted network message), containing the message $m$ along with a Merkle proof of its inclusion into the *OutMsgDescr* of the block just generated, to the validator group of the shardchain $T$ currently owning the destination $\\eta$.\n\n- [NetworkReceive] — If the validators of shardchain $T$ receive such a message, they check its validity starting from the most recent masterchain block and the shardchain block hashes listed in it, including the most recent \"canonical\" block of shardchain $S_0$ as well. If the message is invalid, they silently discard it. If that block of shardchain $S_0$ has a larger sequence number than the one listed in the most recent masterchain block, they may either discard it or postpone the verification until the next masterchain block appears.\n\n- [InclusionConditions] — The validators check inclusion conditions for message $m$. In particular, they must check that this message has not been delivered before, and that the *OutMsgQueues* of the neighbors do not have unprocessed outbound messages with destinations in $T$ with smaller logical creation times than $\\text{Lt}(m)$.\n\n- [Deliver] — The validators deliver and process the message, by including it into the *InMsgDescr* of the current shardchain block along with a bit indicating that it is an IHR message, the Merkle proof of its inclusion into the *OutMsgDescr* of the original block, and the logical time of the transaction $t'$ processing this inbound message into the currently generated block.\n\n- [Confirm] — Finally, the validators send encrypted datagrams to all the validator groups of the intermediate shardchains on the path from $\\xi$ to $\\eta$, containing a Merkle proof of the inclusion of message $m$ into the *InMsgDescr* of its final destination. The validators of an intermediate shardchain may use this proof to *discard* the copy of message $m$ travelling by the rules of HR, by importing the message into their *InMsgDescr* along with the Merkle proof of final delivery and setting a flag indicating that the message has been discarded.\n\nThe overall procedure is even simpler than that for Hypercube Routing. Notice, however, that IHR comes with no delivery or FIFO guarantees: the network datagram may be lost in transit, or the validators of the destination shardchain may decide not to act on it, or they may discard it due to buffer overflow. This is the reason why IHR is used as a complement to HR, and not as a replacement.\n\n### 2.3.2. Overall eventual delivery guarantees\n\nNotice that the combination of HR and IHR guarantees the ultimate delivery of any internal message to its final destination. Indeed, the HR by itself is guaranteed to deliver any message eventually, and the HR for message $m$ can be cancelled at an intermediate stage only by a Merkle proof of delivery of $m$ to its final destination (via IHR).\n\n### 2.3.3. Overall unique delivery guarantees\n\nHowever, the *uniqueness* of message delivery for the combination of HR and IHR is more difficult to achieve. In particular, one must check the following conditions, and, if necessary, be able to provide short Merkle proofs that they do or don't hold:\n\n- When a message $m$ is imported into its next intermediate shardchain block via HR, we must check that $m$ has not already been imported via HR.\n- When $m$ is imported and processed in its final destination shardchain, we must check that $m$ has not already been processed. If it has, there are three subcases:\n  - If $m$ is being considered for import via HR, and it has already been imported via HR, it must not be imported at all.\n  - If $m$ is being considered for import via HR, and it has already been imported via IHR (but not HR), then it must be imported and immediately discarded (without being processed by a transaction). This is necessary to remove $m$ from the *OutMsgQueue* of its previous intermediate shardchain.\n  - If $m$ is being considered for import via IHR, and it has already been imported via either IHR or HR, it must not be imported at all.\n\n### 2.3.4 Checking whether a message has already been delivered to its final destination\n\nConsider the following general algorithm for checking whether a message $m$ has already been delivered to its final destination $\\eta$: One can simply scan the last several blocks belonging to the shardchain containing the destination address, starting from the latest block and working backwards through the previous block references. (If there are two previous blocks—i.e., if a shardchain merge event occurred at some point—one would follow the chain containing the destination address.) The *InMsgDescr* of each of these blocks can be checked for an entry with key $\\text{Hash}(m)$. If such an entry is found, the message $m$ has already been delivered, and we can easily construct a Merkle proof of this fact. If we do not find such an entry before arriving at a block $B$ with $\\text{Lt}^+(B)<\\text{Lt}(m)$, implying that $m$ could not be delivered in $B$ or any of its predecessors, then the message $m$ definitely has not been delivered yet.\n\nThe obvious disadvantage of this algorithm is that, if message $m$ is very old (and most likely delivered a long time ago), meaning that it has a small value of $\\text{Lt}(m)$, then a large number of blocks will need to be scanned before yielding an answer. Furthermore, if the answer is negative, the size of the Merkle proof of this fact will increase linearly with the number of blocks scanned.\n\n### 2.3.5. Checking whether an IHR message has already been delivered to its final destination\n\nTo check whether an IHR message $m$ has already been delivered to its [destination](#2-3-4-checking-whether-a-message-has-already-been-delivered-to-its-final-destination) shardchain, we can apply the modified to inspect only the last $c$ blocks for some small constant $c$ (say, $c=8$). If no conclusion can be reached after inspecting these blocks, then the validators for the destination shardchain may simply discard the IHR message instead of spending more resources on this check.\n\n### 2.3.6. Checking whether an HR message has already been delivered via HR to its final destination or an intermediate shardchain\n\nTo check whether an HR-received message $m$ (or rather, a message $m$ being considered for import via HR) has already been imported via HR, we can use the following algorithm: Let $\\xi_k$ be the transit address of $m$ (belonging to a neighboring shardchain $S_k$) and $\\xi_{k+1}$ be its next-hop address (belonging to the shardchain under consideration). Since we are considering the inclusion of $m$, $m$ must be present in the *OutMsgQueue* of the most recent state of shardchain $S_k$, with $\\xi_k$ and $\\xi_{k+1}$ indicated in its envelope. In particular, (a) the message has been included into *OutMsgQueue*, and we may even know when, because the entry in *OutMsgQueue* sometimes contains the logical time of the block where it has been added, and (b) it has not yet been removed from *OutMsgQueue*.\n\nNow, the validators of the neighboring shardchain are required to remove a message from *OutMsgQueue* as soon as they observe that message (with transit and next-hop addresses $\\xi_k$ and $\\xi_{k+1}$ in its envelope) has been imported into the *InMsgDescr* of the message's next-hop shardchain. Therefore, (b) implies that the message could have been imported into the *InMsgDescr* of a preceding block only if this preceding block is very new (i.e., not yet known to the most recent neighboring shardchain block). Therefore, only a very limited number of preceding blocks (typically one or two, at most) need to be scanned by the [algorithm](#2-3-4-checking-whether-a-message-has-already-been-delivered-to-its-final-destination) to conclude that the message has not yet been imported.<a id=\"ref-fn21\"></a><sup>[21](#fn21)</sup> In fact, if this check is performed by the validators or collators for the current shardchain themselves, it can be optimized by keeping in memory the *InMsgDescrs* of the several latest blocks.\n\n### 2.3.7 Checking whether an HR message has already been delivered via IHR to its final destination\n\nFinally, to check whether an HR message has already been delivered to its final destination via IHR, one can use the [general algorithm](#2-3-4-checking-whether-a-message-has-already-been-delivered-to-its-final-destination). In contrast, we cannot [abort](#2-3-5-checking-whether-an-ihr-message-has-already-been-delivered-to-its-final-destination) the verification process after scanning a fixed number of the latest blocks in the destination shardchain, because HR messages cannot be dropped without a reason.\n\nInstead, we indirectly bound the number of blocks to be inspected by forbidding the inclusion of IHR message $m$ into a block $B$ of its destination shardchain if there are already more than, say, $c=8$ blocks $B'$ in the destination shardchain with $\\text{Lt}^+(B')\\geq\\text{Lt}(m)$.\n\nSuch a condition effectively restricts the time interval after the creation of message $m$ in which it could have been delivered via IHR, so that only a small number of blocks of the destination shardchain (at most $c$) will need to be inspected.\n\nNotice that this condition nicely aligns with the modified [algorithm](#2-3-5-checking-whether-an-ihr-message-has-already-been-delivered-to-its-final-destination), effectively forbidding the validators from importing the newly-received IHR message if more than $c=8$ steps are needed to check that it had not been imported already.\n\n---\n\n# 3   Messages, message descriptors, and queues\n\nThis chapter presents the internal layout of individual messages, message descriptors (such as *InMsgDescr* or *OutMsgDescr*), and message queues (such as *OutMsgQueue*). [Enveloped messages](#2-1-16-message-envelopes) are also discussed here.\n\nNotice that most general conventions related to messages must be obeyed by all shardchains, even if they do not belong to the basic shardchain; otherwise, messaging and interaction between different workchains would not be possible. It is the *interpretation* of the message contents and the *processing* of messages, usually by some transactions, that differs between workchains.\n\n## 3.1   Address, currency, and message layout\n\nThis chapter begins with some general definitions, followed by the precise layout of addresses used for serializing source and destination addresses in a message.\n\n### 3.1.1. Some standard definitions\n\nFor the reader's convenience, we reproduce here several general TL-B definitions.<a id=\"ref-fn22\"></a><sup>[22](#fn22)</sup> These definitions are used below in the discussion of address and message layout, but otherwise are not related to the TON Blockchain.\n\n```\nunit$_ = Unit;\ntrue$_ = True;\n// EMPTY False;\nbool_false$0 = Bool;\nbool_true$1 = Bool;\nnothing$0 {X:Type} = Maybe X;\njust$1 {X:Type} value:X = Maybe X;\nleft$0 {X:Type} {Y:Type} value:X = Either X Y;\nright$1 {X:Type} {Y:Type} value:Y = Either X Y;\npair$_ {X:Type} {Y:Type} first:X second:Y = Both X Y;\n\nbit$_ _:(## 1) = Bit;\n```\n\n### 3.1.2. TL-B scheme for addresses\n\nThe serialization of source and destination addresses is defined by the following TL-B scheme:\n\n```\naddr_none$00 = MsgAddressExt;\naddr_extern$01 len:(## 9) external_address:(len * Bit) \n             = MsgAddressExt;\nanycast_info$_ depth:(## 5) rewrite_pfx:(depth * Bit) = Anycast;\naddr_std$10 anycast:(Maybe Anycast) \n   workchain_id:int8 address:uint256  = MsgAddressInt;\naddr_var$11 anycast:(Maybe Anycast) addr_len:(## 9) \n   workchain_id:int32 address:(addr_len * Bit) = MsgAddressInt;\n_ MsgAddressInt = MsgAddress;\n_ MsgAddressExt = MsgAddress;\n```\n\nThe two last lines define type `MsgAddress` to be the internal union of types `MsgAddressInt` and `MsgAddressExt` (not to be confused with their [external union](#3-1-1-some-standard-definitions) `Either MsgAddressInt MsgAddressExt` ), as if the preceding four lines had been repeated with the right-hand side replaced by `MsgAddress`. In this way, type `MsgAddress` has four constructors, and types `MsgAddressInt` and `MsgAddressExt` are both subtypes of `MsgAddress`.\n\n### 3.1.3. External addresses\n\nThe first two constructors, `addr_none` and `addr_extern`, are used for source addresses of \"messages from nowhere\" (inbound external messages), and for destination addresses of \"messages to nowhere\" (outbound external messages). The `addr_extern` constructor defines an \"external address\", which is ignored by the TON Blockchain software altogether (which treats `addr_extern` as a longer variant of `addr_none`), but may be used by external software for its own purposes. For example, a special external service may inspect the destination address of all outbound external messages found in all blocks of the TON Blockchain, and, if a special magic number is present in the `external_address` field, parse the remainder as an IP address and UDP port or a (TON Network) ADNL address, and send a datagram with a copy of the message to the network address thus obtained.\n\n### 3.1.4 Internal addresses\n\nThe two remaining constructors, `addr_std` and `addr_var`, represent internal addresses. The first of them, `addr_std`, represents a signed 8-bit $\\mathit{workchain\\_id}$ (sufficient for the masterchain and for the basic workchain) and a 256-bit internal address in the selected workchain. The second of them, `addr_var`, represents addresses in workchains with a \"large\" $\\mathit{workchain\\_id}$, or internal addresses of length not equal to 256. Both of these constructors have an optional `anycast` value, absent by default, which enables \"address rewriting\" when present.<a id=\"ref-fn23\"></a><sup>[23](#fn23)</sup>\n\nThe validators must use `addr_std` instead of `addr_var` whenever possible, but must be ready to accept `addr_var` in inbound messages. The `addr_var` constructor is intended for future extensions.\n\nNotice that $\\mathit{workchain\\_id}$ must be a valid workchain identifier enabled in the current masterchain configuration, and the length of the internal address must be in the range allowed for the indicated workchain. For example, one cannot use $\\mathit{workchain\\_id}=0$ (basic workchain) or $\\mathit{workchain\\_id}=-1$ (masterchain) with addresses that are not exactly 256 bits long.\n\n### 3.1.5. Representing Gram currency amounts\n\nAmounts of Grams are expressed with the aid of two types representing variable-length unsigned or signed integers, plus a type `Grams` explicitly dedicated to representing non-negative amounts of nanograms, as follows:\n\n```\nvar_uint$_ {n:#} len:(#< n) value:(uint (len * 8))\n         = VarUInteger n;\nvar_int$_ {n:#} len:(#< n) value:(int (len * 8)) \n        = VarInteger n;\nnanograms$_ amount:(VarUInteger 16) = Grams;\n```\n\nIf one wants to represent $x$ nanograms, one selects an integer $\\ell<16$ such that $x<2^{8\\ell}$, and serializes first $\\ell$ as an unsigned 4-bit integer, then $x$ itself as an unsigned $8\\ell$-bit integer. Notice that four zero bits represent a zero amount of Grams.\n\nRecall that the original total supply of [Grams](/foundations/whitepapers/ton#a-the-ton-coin,-or-the-gram) is fixed at five billion (i.e., $5\\cdot10^{18}<2^{63}$ nanograms), and is expected to grow very slowly. Therefore, all the amounts of Grams encountered in practice will fit in unsigned or even signed 64-bit integers. The validators may use the 64-bit integer representation of Grams in their internal computations; however, the serialization of these values the blockchain is another matter.\n\n### 3.1.6. Representing collections of arbitrary currencies\n\nRecall that the TON Blockchain allows its users to define arbitrary cryptocurrencies or tokens apart from the Gram, provided some conditions are met. Such additional cryptocurrencies are identified by 32-bit $\\textit{currency\\_id}$s. The list of defined additional cryptocurrencies is a part of the blockchain configuration, stored in the masterchain.\n\nWhen some amounts of one or several such cryptocurrencies need to be represented, a [dictionary](/foundations/whitepapers/tvm#3-3-hashmaps,-or-dictionaries) with 32-bit $\\textit{currency\\_id}$s as keys and `VarUInteger 32` values is used:\n\n```\nextra_currencies$_ dict:(HashmapE 32 (VarUInteger 32)) \n                 = ExtraCurrencyCollection;\ncurrencies$_ grams:Grams other:ExtraCurrencyCollection \n           = CurrencyCollection;\n```\n\nThe value attached to an internal message is represented by a value of the `CurrencyCollection` type, which may describe a certain (non-negative) amount of (nano)grams as well as some additional currencies, if needed. Notice that if no additional currencies are required, `other` reduces to just one zero bit.\n\n### 3.1.7. Message layout\n\nA message consists of its *header* followed by its *body, or payload*. The body is essentially arbitrary, to be interpreted by the destination smart contract. The message header is standard and is organized as follows:\n\n```\nint_msg_info$0 ihr_disabled:Bool bounce:Bool\n  src:MsgAddressInt dest:MsgAddressInt \n  value:CurrencyCollection ihr_fee:Grams fwd_fee:Grams\n  created_lt:uint64 created_at:uint32 = CommonMsgInfo;\next_in_msg_info$10 src:MsgAddressExt dest:MsgAddressInt \n  import_fee:Grams = CommonMsgInfo;\next_out_msg_info$11 src:MsgAddressInt dest:MsgAddressExt\n  created_lt:uint64 created_at:uint32 = CommonMsgInfo;\n\ntick_tock$_ tick:Bool tock:Bool = TickTock;\n\n_ split_depth:(Maybe (## 5)) special:(Maybe TickTock)\n  code:(Maybe ^Cell) data:(Maybe ^Cell)\n  library:(Maybe ^Cell) = StateInit;\n\nmessage$_ {X:Type} info:CommonMsgInfo\n  init:(Maybe (Either StateInit ^StateInit))\n  body:(Either X ^X) = Message X;\n```\n\nThe meaning of this scheme is as follows.\n\nType `Message X` describes a message with the body (or payload) of type $X$. Its serialization starts with `info` of type `CommonMsgInfo`, which comes in three flavors: for internal messages, inbound external messages, and outbound external messages, respectively. All of them have a source address `src` and destination address `dest`, which are external or internal according to the chosen constructor. Apart from that, an internal message may bear some `value` in Grams and [other defined currencies](#3-1-6-representing-collections-of-arbitrary-currencies), and all messages generated inside the TON Blockchain have a [logical creation time](#1-4-6-logical-time-in-the-ton-blockchain) `created_lt` and creation unixtime `created_at`, both automatically set by the generating transaction. The creation unixtime equals the creation unixtime of the block containing the generating transaction.\n\n### 3.1.8. Forwarding and IHR fees. Total value of an internal message\n\nInternal messages define an `ihr_fee` in Grams, which is subtracted from the value attached to the message and awarded to the validators of the destination shardchain if they include the message by the IHR mechanism. The `fwd_fee` is the original total forwarding fee paid for using the HR mechanism; it is automatically computed from some configuration parameters and the size of the message at the time the message is generated.\n\nNotice that the total value carried by a newly-created internal outbound message equals the sum of `value`, `ihr_fee`, and `fwd_fee`. This sum is deducted from the balance of the source account. Of these components, only `value` is always credited to the destination account on message delivery. The `fwd_fee` is collected by the validators on the HR path from the source to the destination, and the `ihr_fee` is either collected by the validators of the destination shardchain (if the message is delivered via IHR), or credited to the destination account.\n\n### 3.1.9. Code and data portions contained in a message\n\nApart from the common message information stored in `info`, a message can contain portions of the destination smart contract's code and data. This feature is used, for instance, in the so-called [constructor messages](#1-7-3-initializing-smart-contracts-by-constructor-messages), which are simply internal or inbound external messages with `code` and possibly `data` fields defined in their `init` portions. If the hash of these fields is correct, and the destination smart contract has no code or data, the values from the message are used instead.<a id=\"ref-fn24\"></a><sup>[24](#fn24)</sup>\n\n### 3.1.10 Using `code` and `data` for other purposes\n\nWorkchains other than the masterchain and the basic workchain are free to use the trees of cells referred to in the `code`, `data`, and `library` fields for their own purposes. The messaging system itself makes no assumptions about their contents; they become relevant only when a message is processed by a transaction.\n\n### 3.1.11. Absence of an explicit gas price and gas limit\n\nNotice that messages do not have an explicit gas price and gas limit. Instead, the gas price is set globally by the validators for each workchain (it is a special configurable parameter), and the gas limit for each transaction has also a default value, which is a configurable parameter; the smart contract itself may lower the gas limit during its execution if so desired.\n\nFor internal messages, the initial gas limit cannot exceed the Gram value of the message divided by the current gas price. For inbound external messages, the initial gas limit is very small, and the true gas limit is set by the receiving smart contract itself, when it *accepts* the inbound message by the corresponding TVM primitive.\n\n### 3.1.12. Deserialization of a message payload\n\nThe payload, or body, of a message is deserialized by the receiving smart contract when executed by TVM. The messaging system itself makes no assumptions about the internal format of the payload. However, it makes sense to describe the serialization of supported inbound messages by TL or TL-B schemes with 32-bit constructor tags, so that the developers of other smart contracts will know the interface supported by a specific smart contract.\n\nA message is always serialized inside the blockchain as the last field in a cell. Therefore, the blockchain software may assume that whatever bits and references left unparsed after parsing the fields of a `Message` preceding `body` belong to the payload `body:X`, without knowing anything about the serialization of the type $X$.\n\n### 3.1.13. Messages with empty payloads\n\nThe payload of a message may happen to be an empty cell slice, having no data bits and no references. By convention, such messages are used for simple value transfers. The receiving smart contract is normally expected to process such messages quietly and to terminate successfully (with a zero exit code), although some smart contracts may perform non-trivial actions even when receiving a message with empty payload. For example, a smart contract may check the resulting balance, and, if it becomes sufficient for a previously postponed action, trigger this action. Alternatively, the smart contract might want to remember in its persistent storage the amount received and the corresponding sender, in order, for instance, to distribute some tokens later to each sender proportionally to the funds transferred.\n\nNotice that even if a smart contract makes no special provisions for messages with empty payloads and throws an exception while processing such messages, the received value (minus the gas payment) will still be added to the balance of the smart contract.\n\n### 3.1.14. Message source address and logical creation time determine its generating block\n\nNotice that *the source address and the logical creation time of an internal or an outbound external message uniquely determine the block in which the message has been generated*. Indeed, the source address determines the source shardchain, and the blocks of this shardchain are assigned non-intersecting logical time intervals, so only one of them may contain the indicated logical creation time. This is the reason why no explicit mention of the generating block is needed in messages.\n\n### 3.1.15. Enveloped messages\n\n[Message envelopes](#2-1-16-message-envelopes) are used for attaching routing information, such as the current (transit) address and the next-hop address, to inbound, transit, and outbound messages. The message itself is kept in a separate cell and referred to from the message envelope by a cell reference.\n\n```\ninterm_addr_regular$0 use_src_bits:(#<= 96) \n  = IntermediateAddress;\ninterm_addr_simple$10 workchain_id:int8 addr_pfx:(64 * Bit) \n  = IntermediateAddress;\ninterm_addr_ext$11 workchain_id:int32 addr_pfx:(64 * Bit)\n  = IntermediateAddress;\nmsg_envelope cur_addr:IntermediateAddress \n  next_addr:IntermediateAddress fwd_fee_remaining:Grams \n  msg:^(Message Any) = MsgEnvelope;\n```\n\nThe `IntermediateAddress` type is used to describe the intermediate addresses of a message—that is, its current (or transit) address `cur_addr`, and its next-hop address `next_addr`. The first constructor `interm_addr_regular` [represents](#2-1-15-representation-of-transit-and-next-hop-addresses) the intermediate address using the optimization, by storing the number of the first bits of the intermediate address that are the same as in the source address; the two other explicitly store the workchain identifier and the first 64 bits of the address inside that workchain (the remaining bits can be taken from the source address). The `fwd_fee_remaining` field is used to explicitly represent the maximum amount of message forwarding fees that can be deducted from the message value during the remaining HR steps; it cannot exceed the value of `fwd_fee` indicated in the message itself.\n\n---\n\n## 3.2   Inbound message descriptors\n\nThis section discusses *InMsgDescr*, the structure containing a description of all inbound messages imported into a block.<a id=\"ref-fn25\"></a><sup>[25](#fn25)</sup>\n\n### 3.2.1. Types and sources of inbound messages\n\nEach inbound message mentioned in *InMsgDescr* is described by a value of type *InMsg* (an \"inbound message descriptor\"), which specifies the source of the message, the reason for its being imported into this block, and some information about its \"fate\"—its processing by a transaction or forwarding inside the block.\n\nInbound messages may be classified as follows:\n\n- *Inbound external messages* — Need no additional reason for being imported into the block, but must be immediately processed by a transaction in the same block.  \n- *Internal IHR messages with destination addresses in this block* — The reason for their being imported into the block includes a Merkle proof of their generation (i.e., their inclusion in *OutMsgDescr* of their original block). Such a message must be immediately delivered to its final destination and processed by a transaction.  \n- *Internal messages with destinations in this block* — The reason for their inclusion is their presence in *OutMsgQueue* of the most recent state of a neighboring shardchain,<a id=\"ref-fn26\"></a><sup>[26](#fn26)</sup> or their presence in *OutMsgDescr* of this very block. This neighboring shardchain is completely determined by the transit address indicated in the forwarded message envelope, which is replicated in *InMsg* as well. The \"fate\" of this message is again described by a reference to the processing transaction inside the current block.  \n- *Immediately routed internal messages* — Essentially a subclass of the previous class of messages. In this case, the imported message is one of the outbound messages generated in this very block.  \n- *Transit internal messages* — Have the same reason for inclusion as the previous class of messages. However, they are not processed inside the block, but internally forwarded into *OutMsgDescr* and *OutMsgQueue*. This fact, along with a reference to the new envelope of the transit message, must be registered in *InMsg*.  \n- *Discarded internal messages with destinations in this block* — An internal message with a destination in this block may be imported and immediately discarded instead of being processed by a transaction if it has already been received and processed via IHR in a preceding block of this shardchain. In this case, a reference to the previous processing transaction must be provided.  \n- *Discarded transit internal messages* — Similarly, a transit message may be discarded immediately after import if it has already been delivered via IHR to its final destination. In this case, a Merkle proof of its processing in the final block (as an IHR message) is required.\n\n\n### 3.2.2. Descriptor of an inbound message\n\nEach [inbound message](#3-2-1-types-and-sources-of-inbound-messages) is described by an instance of the `InMsg` type, which has six constructors corresponding to the cases:\n\n```\nmsg_import_ext$000 msg:^(Message Any) transaction:^Transaction \n              = InMsg;\nmsg_import_ihr$010 msg:^(Message Any) transaction:^Transaction \n    ihr_fee:Grams proof_created:^Cell = InMsg;\nmsg_import_imm$011 in_msg:^MsgEnvelope\n    transaction:^Transaction fwd_fee:Grams = InMsg;\nmsg_import_fin$100 in_msg:^MsgEnvelope \n    transaction:^Transaction fwd_fee:Grams = InMsg;\nmsg_import_tr$101  in_msg:^MsgEnvelope out_msg:^MsgEnvelope \n    transit_fee:Grams = InMsg;\nmsg_discard_fin$110 in_msg:^MsgEnvelope transaction_id:uint64 \n    fwd_fee:Grams = InMsg;\nmsg_discard_tr$111 in_msg:^MsgEnvelope transaction_id:uint64 \n    fwd_fee:Grams proof_delivered:^Cell = InMsg;\n```\n\nNotice that the processing transaction is referred to in the first four constructors directly by a cell reference to `Transaction`, even though the logical time of the transaction `transaction_lt:uint64` would suffice for this purpose. Internal consistency conditions ensure that the transaction referred to does belong to the destination smart contract indicated in the message, and that the inbound message processed by that transaction is indeed the one being described in this *InMsg* instance.\n\nFurthermore, notice that `msg_import_imm` could be distinguished from `msg_import_fin` by observing that it is the only case when the logical creation time of the message being processed is greater than or equal to the (minimal) logical time of the block importing the message.\n\n### 3.2.3. Collecting forwarding and transit fees from imported messages\n\nThe *InMsg* structure is also used to indicate the forwarding and transit fees collected from inbound messages. The fee itself is indicated in `ihr_fee`, `fwd_fee`, or `transit_fee` fields; it is absent only in inbound external messages, which use other mechanisms to reward the validators for importing them. The fees must satisfy the following internal consistency conditions:\n\n- For external messages (`msg_import_ext`), there is no forwarding fee.\n- For IHR-imported internal messages (`msg_import_ihr`), the fee equals `ihr_fee`, which must coincide with the `ihr_fee` value indicated in the message itself. Notice that `fwd_fee` or `fwd_fee_remaining` are never collected from IHR-imported messages.\n- For internal messages delivered to their destination (`msg_import_fin` and `msg_import_imm`), the fee equals the `fwd_fee_remaining` of the enveloped inbound message `in_msg`. Note that it cannot exceed the `fwd_fee` value indicated in the message itself.\n- For transit messages (`msg_import_tr`), the fee equals the difference between the `fwd_fee_remaining` values indicated in the `in_msg` and `out_msg` envelopes.\n- For discarded messages, the fee also equals the `fwd_fee_remaining` indicated in `in_msg`.\n\n### 3.2.4. Imported value of an inbound message\n\nEach imported message imports some value—a certain amount of one or more cryptocurrencies—into the block. This imported value is computed as follows:\n\n- An external message imports no value.\n- An IHR-imported message imports its `value` plus its `ihr_fee`.\n- A delivered or transit internal message imports its `value` plus its `ihr_fee` plus the value of `fwd_fee_remaining` of its `in_msg` envelope.\n- A discarded message imports the `fwd_fee_remaining` of its `in_msg` envelope.\n\nNotice that the forwarding and transit fees collected from an imported message do not exceed its imported value.\n\n### 3.2.5. Augmented hashmaps, or dictionaries\n\nBefore continuing, let us discuss the serialization of *augmented* hashmaps, or dictionaries.\n\nAugmented hashmaps are key-value storage structures with $n$-bit keys and values of some type $X$, similar to the [ordinary hashmaps](/foundations/whitepapers/tvm#3-3-hashmaps,-or-dictionaries). However, each intermediate node of the Patricia tree representing an *augmented* hashmap is augmented by a value of type $Y$.\n\nThese augmentation values must satisfy certain *aggregation conditions*. Typically, $Y$ is an integer type, and the aggregation condition is that the augmentation value of a fork must equal the sum of the augmentation values of its two children. In general, a *fork evaluation function* $S:Y\\times Y\\to Y$ or $S:Y\\to Y\\to Y$ is used instead of the sum. The augmentation value of a leaf is usually computed from the value stored in that leaf by means of a *leaf evaluation function* $L:X\\to Y$. The augmentation value of a leaf may be stored explicitly in the leaf along with the value; however, in most cases there is no need for this, because the leaf evaluation function $L$ is very simple.\n\n### 3.2.6. Serialization of augmented hashmaps\n\nThe [serialization of augmented hashmaps](/foundations/whitepapers/tvm#3-3-3-serialization-of-hashmaps) with $n$-bit keys, values of type $X$, and augmentation values of type $Y$ is given by the following TL-B scheme, which is an extension:\n\n```\nahm_edge#_ {n:#} {X:Type} {Y:Type} {l:#} {m:#} \n  label:(HmLabel ~l n) {n = (~m) + l} \n  node:(HashmapAugNode m X Y) = HashmapAug n X Y;\nahmn_leaf#_ {X:Type} {Y:Type} extra:Y value:X \n  = HashmapAugNode 0 X Y;\nahmn_fork#_ {n:#} {X:Type} {Y:Type}\n    left:^(HashmapAug n X Y) right:^(HashmapAug n X Y) extra:Y \n  = HashmapAugNode (n + 1) X Y;\n\nahme_empty$0 {n:#} {X:Type} {Y:Type} extra:Y \n          = HashmapAugE n X Y;\nahme_root$1 {n:#} {X:Type} {Y:Type} root:^(HashmapAug n X Y)\n  extra:Y = HashmapAugE n X Y;\n```\n\n### 3.2.7. Augmentation of *InMsgDescr*\n\nThe collection of inbound message descriptors is augmented by a vector of two currency values, representing the imported value and the forwarding and transit fees collected from a message or a collection of messages:\n\n```\nimport_fees$_ fees_collected:Grams \n  value_imported:CurrencyCollection = ImportFees;\n```\n\n### 3.2.8. Structure of *InMsgDescr*\n\nNow the *InMsgDescr* itself is defined as an augmented hashmap, with 256-bit keys (equal to the representation hashes of imported messages), [values](#3-2-2-descriptor-of-an-inbound-message) of type `InMsg`, and [augmentation](#3-2-7-augmentation-of-inmsgdescr) values of type `ImportFees`:\n\n```\n_ (HashmapAugE 256 InMsg ImportFees) = InMsgDescr;\n```\n\nThis TL-B notation uses an anonymous constructor `_` to define `InMsgDescr` as a synonym for another type.\n\n### 3.2.9. Aggregation rules for *InMsgDescr*\n\nThe [fork evaluation](#3-2-5-augmented-hashmaps%2C-or-dictionaries) and leaf evaluation functions are not included explicitly in the above notation, because the dependent types of TL-B are not expressive enough for this purpose. In words, the fork evaluation function is just the componentwise addition of two `ImportFees` instances, and the leaf evaluation function is defined by the rules listed in [3.2.3](#3-2-3-collecting-forwarding-and-transit-fees-from-imported-messages) and [3.2.4](#3-2-4-imported-value-of-an-inbound-message). In this way, the root of the Patricia tree representing an instance of *InMsgDescr* contains an *ImportFees* instance with the total value imported by all inbound messages, and with the total forwarding fees collected from them.\n\n---\n\n## 3.3   Outbound message queue and descriptors\n\nThis section discusses *OutMsgDescr*, the structure representing all outbound messages of a block, along with their envelopes and brief descriptions of the reasons for including them into *OutMsgDescr*. This structure also describes all modifications of *OutMsgQueue*, which is a part of the shardchain state.\n\n### 3.3.1. Types of outbound messages\n\nOutbound messages may be classified as follows:\n\n- *External outbound messages*, or \"messages to nowhere\" — Generated by a transaction inside this block. The reason for including such a message into *OutMsgDescr* is simply a reference to its generating transaction.\n- *Immediately processed internal outbound messages* — Generated and processed in this very block, and not included into *OutMsgQueue*. The reason for including such a message is a reference to its generating transaction, and its \"fate\" is described by a reference to the corresponding entry in *InMsgDescr*.\n- *Ordinary (internal) outbound messages* — Generated in this block and included into *OutMsgQueue*.\n- *Transit (internal) outbound messages* — Imported into the *InMsgDescr* of the same block and routed via HR until a next-hop address outside the current shard is obtained.\n\n### 3.3.2. Message dequeueing records\n\nApart from the above types of outbound messages, *OutMsgDescr* can contain special \"message dequeueing records\", which indicate that a message has been removed from the *OutMsgQueue* in this block. The reason for this removal is indicated in the message deletion record; it consists of a reference to the enveloped message being deleted, and of the logical time of the neighboring shardchain block that has this enveloped message in its *InMsgDescr*.\n\nNotice that on some occasions a message may be imported from the *OutMsgQueue* of the current shardchain, internally routed, and then included into *OutMsgDescr* and *OutMsgQueue* again with a different envelope.<a id=\"ref-fn27\"></a><sup>[27](#fn27)</sup> In this case, a variant of the transit outbound message description is used, which doubles as a message dequeueing record.\n\n### 3.3.3. Descriptor of an outbound message\n\nEach outbound message is described by an instance of *OutMsg*:\n\n```\nmsg_export_ext$000 msg:^(Message Any)\n    transaction:^Transaction = OutMsg;\nmsg_export_imm$010 out_msg:^MsgEnvelope \n    transaction:^Transaction reimport:^InMsg = OutMsg;\nmsg_export_new$001 out_msg:^MsgEnvelope \n    transaction:^Transaction = OutMsg;\nmsg_export_tr$011  out_msg:^MsgEnvelope \n    imported:^InMsg = OutMsg;\nmsg_export_deq$110 out_msg:^MsgEnvelope \n    import_block_lt:uint64 = OutMsg;\nmsg_export_tr_req$111 out_msg:^MsgEnvelope \n    imported:^InMsg = OutMsg;\n```\n\nThe last two descriptions have the effect of removing (dequeueing) the message from *OutMsgQueue* instead of inserting it. The last one re-inserts the message into *OutMsgQueue* with a new envelope after performing the [internal routing](#2-1-11-internal-routing).\n\n### 3.3.4. Exported value of an outbound message\n\nEach outbound message described by an *OutMsg* exports some value—a certain amount of one or more cryptocurrencies—from the block. This exported value is computed as follows:\n\n- An external outbound message exports no value.\n- An internal message, generated in this block, exports its `value` plus its `ihr_fee` plus its `fwd_fee`. Notice that `fwd_fee` must be equal to the `fwd_fee_remaining` indicated in the `out_msg` envelope.\n- A transit message exports its `value` plus its `ihr_fee` plus the value of `fwd_fee_remaining` of its `out_msg` envelope.\n- The same holds for `msg_export_tr_req`, the constructor of *OutMsg* used for re-inserted dequeued messages.\n- A [message dequeueing record](#3-3-2-message-dequeueing-records) (`msg_export_deq`) exports no value.\n\n### 3.3.5. Structure of *OutMsgDescr*\n\nThe *OutMsgDescr* itself is simply an [augmented hashmap](#3-2-5-augmented-hashmaps%2C-or-dictionaries), with 256-bit keys (equal to the representation hash of the message), values of type *OutMsg*, and augmentation values of type *CurrencyCollection*:\n\n```\n_ (HashmapAugE 256 OutMsg CurrencyCollection) = OutMsgDescr;\n```\n\nThe augmentation is the [exported value](#3-3-4-exported-value-of-an-outbound-message) of the corresponding message, aggregated by means of the sum, and computed at the leaves. In this way, the total exported value appears near the root of the Patricia tree representing *OutMsgDescr*.\n\nThe most important consistency condition for *OutMsgDescr* is that its entry with key $k$ must be an *OutMsg* describing a message $m$ with representation hash $\\text{Hash}^\\flat(m)=k$.\n\n### 3.3.6. Structure of *OutMsgQueue*\n\nRecall that [OutMsgQueue](#1-2-7-outbound-message-queue-of-a-shardchain) is a part of the blockchain state, not of a block. Therefore, a block contains only hash references to its initial and final state, and its newly-created cells.\n\nThe structure of *OutMsgQueue* is simple: it is just an augmented hashmap with 352-bit keys and values of type *OutMsg*:\n```\n_ (HashmapAugE 352 OutMsg uint64) = OutMsgQueue;\n```\n\nThe key used for an outbound message $m$ is the concatenation of its 32-bit next-hop $\\mathit{workchain\\_id}$, the first 64 bits of the next-hop address inside that workchain, and the representation hash $\\text{Hash}^\\flat(m)$ of the message $m$ itself. The augmentation is by the logical creation time $\\text{Lt}(m)$ of message $m$ at the leaves, and by the minimum of the augmentation values of the children at the forks.\n\nThe most important consistency condition for *OutMsgQueue* is that the value at key $k$ must indeed contain an enveloped message with the expected next-hop address and representation hash.\n\n### 3.3.7. Consistency conditions for *OutMsg*\n\nSeveral internal consistency conditions are imposed on *OutMsg* instances present in *OutMsgDescr*. They include the following:\n\n- Each of the first three constructors of outbound message descriptions includes a reference to the generating transaction. This transaction must belong to the source account of the message, it must contain a reference to the specified message as one of its outbound messages, and it must be recoverable by looking it up by its `account_id` and `transaction_id`.\n- `msg_export_tr` and `msg_export_tr_req` must refer to an *InMsg* instance describing the same message (in a different original envelope).\n- If one of the first four constructors is used, the message must be absent in the initial *OutMsgQueue* of the block; otherwise, it must be present.\n- If `msg_export_deq` is used, the message must be absent in the final *OutMsgQueue* of the block; otherwise, it must be present.\n- If a message is not mentioned in *OutMsgDescr*, it must be the same in the initial and final *OutMsgQueues* of the block.\n\n---\n\n# 4   Accounts and transactions\n\nThis chapter discusses the layout of *accounts* (or *smart contracts*) and their state in the TON Blockchain. It also considers *transactions*, which are the only way to modify the state of an account, and to process inbound messages and generate new outbound messages.\n\n## 4.1  Accounts and their states\n\nRecall that a *smart contract* and an *account* are the same thing in the context of the TON Blockchain, and that these terms can be used interchangeably, at least as long as only small (or \"usual\") smart contracts are considered. A *large* smart contract may employ several accounts lying in different shardchains of the same workchain for load balancing purposes.\n\nAn account is *identified* by its full address, and is *completely described* by its state. In other words, there is nothing else in an account apart from its address and state.\n\n### 4.1.1. Account addresses\n\nIn general, an account is completely identified by its *full address*, consisting of a 32-bit $\\mathit{workchain\\_id}$, and the (usually 256-bit) *internal address* or *account identifier* $\\mathit{account\\_id}$ inside the chosen workchain. In the basic workchain ($\\mathit{workchain\\_id}=0$) and in the masterchain ($\\mathit{workchain\\_id}=-1$) the internal address is always 256-bit. In these workchains,<a id=\"ref-fn28\"></a><sup>[28](#fn28)</sup> $\\mathit{account\\_id}$ cannot be chosen arbitrarily, but must be equal to the hash of the initial code and data of the smart contract; otherwise, it will be impossible to [initialize the account](#1-7-3-initializing-smart-contracts-by-constructor-messages) with the intended code and data, and to do anything with the accumulated funds in the account balance.\n\n### 4.1.2. Zero account\n\nBy convention, the *zero account* or *account with zero address* accumulates the processing, forwarding, and transit fees, as well as any other payments collected by the validators of the masterchain or a workchain. Furthermore, the zero account is a \"large smart contract\", meaning that each shardchain has its instance of the zero account, with the most significant bits of the address adjusted to lie in the shard. Any funds transferred to the zero account, intentionally or by accident, are effectively a gift for the validators. For example, a smart contract might destroy itself by sending all its funds to the zero account.\n\n### 4.1.3. Small and large smart contracts\n\nBy default, smart contracts are \"small\", meaning that they have one account address belonging to exactly one shardchain at any given moment of time. However, one can create a \"large smart contract of splitting depth $d$\", meaning that up to $2^d$ instances of the smart contract may be created, with the first $d$ bits of the original address of the smart contract replaced by arbitrary bit sequences.<a id=\"ref-fn29\"></a><sup>[29](#fn29)</sup> One can send messages to such smart contracts using internal anycast [addresses](#3-1-2-tl-b-scheme-for-addresses) with `anycast` set to $d$. Furthermore, the instances of the large smart contract are allowed to use this anycast address as the source address of their generated messages.\n\nAn instance of a large smart contract is an account with non-zero *maximal splitting depth* $d$.\n\n### 4.1.4. The three kinds of accounts\n\nThere are three kinds of accounts:\n\n* *Uninitialized* — The account only has a balance; its code and data have not yet been initialized.\n* *Active* — The account's code and data have been initialized as well.\n* *Frozen* — The account's code and data have been replaced by a hash, but the balance is still stored explicitly. The balance of a frozen account may effectively become negative, reflecting due storage payments.\n\n\n### 4.1.5. Storage profile of an account\n\nThe *storage profile* of an account is a data structure describing the amount of persistent blockchain state storage used by that account. It describes the total amount of cells, data bits, and internal and external cell references used.\n\n```\nstorage_used$_ cells:(VarUInteger 7) bits:(VarUInteger 7) \n  ext_refs:(VarUInteger 7) int_refs:(VarUInteger 7) \n  public_cells:(VarUInteger 7) = StorageUsed;\n```\n\nThe same type `StorageUsed` may represent the storage profile of a message, as required, for instance, to compute `fwd_fee`, the total forwarding fee for Hypercube Routing. The storage profile of an account has some additional fields indicating the last time when the storage fees were exacted:\n\n```\nstorage_info$_ used:StorageUsed last_paid:uint32\n              due_payment:(Maybe Grams) = StorageInfo;\n```\n\nThe `last_paid` field contains either the unixtime of the most recent storage payment collected (usually this is the unixtime of the most recent transaction), or the unixtime when the account was created (again, by a transaction). The `due_payment` field, if present, accumulates the storage payments that could not be exacted from the balance of the account, represented by a strictly positive amount of nanograms; it can be present only for uninitialized or frozen accounts that have a balance of zero Grams (but may have non-zero balances in other cryptocurrencies). When `due_payment` becomes larger than the value of a configurable parameter of the blockchain, the account is destroyed altogether, and its balance, if any, is transferred to the zero account.\n\n### 4.1.6. Account balance\n\nThe state of an account is represented by an instance of type *Account*, described by the following TL-B scheme:<a id=\"ref-fn30\"></a><sup>[30](#fn30)</sup>\n```\naccount_none$0 = Account;\naccount$1 addr:MsgAddressInt storage_stat:StorageInfo\n          storage:AccountStorage = Account;\n\naccount_storage$_ last_trans_lt:uint64\n    balance:CurrencyCollection state:AccountState \n  = AccountStorage;\n\naccount_uninit$00 = AccountState;\naccount_active$1 _:StateInit = AccountState;\naccount_frozen$01 state_hash:uint256 = AccountState;\n\nacc_state_uninit$00 = AccountStatus;\nacc_state_frozen$01 = AccountStatus;\nacc_state_active$10 = AccountStatus;\nacc_state_nonexist$11 = AccountStatus;\n\ntick_tock$_ tick:Bool tock:Bool = TickTock;\n\n_ split_depth:(Maybe (## 5)) special:(Maybe TickTock)\n  code:(Maybe ^Cell) data:(Maybe ^Cell)\n  library:(Maybe ^Cell) = StateInit;\n```\n\nNotice that `account_frozen` contains the representation hash of an instance of *StateInit*, instead of that instance itself, which would otherwise be contained in an `account_active`; `account_uninit` is similar to `account_frozen`, but it does not contain an explicit `state_hash`, because it is assumed to be equal to the internal address of the account ($\\mathit{account\\_id}$), already present in the `addr` field. The `split_depth` field is present and non-zero only in instances of large smart contracts. The `special` field may be present only in the masterchain—and within the masterchain, only in some *fundamental* smart contracts required for the whole system to function.\n\nThe storage statistics kept in `storage_stat` reflect the total storage usage of cell slice `storage`. In particular, the bits and cells used to store the `balance` are also reflected in `storage_stat`.\n\nWhen a non-existent account needs to be represented, the `account_none` constructor is used.\n\n### 4.1.7. Account state as a message from an account to its future self\n\nNotice that the account state is very similar to a message sent from an account to its future self participating in the next transaction, for the following reasons:\n\n- The account state does not change between two consecutive transactions of the same account, so it is completely similar in this respect to a message sent from the earlier transaction to the later one.\n- When a transaction is processed, its inputs are an inbound message and the previous account state; its outputs are outbound messages generated and the next account state. If we treat the state as a special kind of message, we see that every transaction has exactly two inputs (the account state and an inbound message) and at least one output.\n- Both a message and the account state can carry code and data in an instance of *StateInit*, and some value in their `balance`.\n- An account is initialized by a *constructor message*, which essentially carries the future state and balance of the account.\n- On some occasions messages are converted into account states, and vice versa. For instance, when a shardchain [merge event](#4-2-11-merge-transactions) occurs, and two accounts that are instances of the same large contract need to be merged, one of them is converted into a message sent to the other one. Similarly, when a shardchain [split event](#4-2-10-split-transactions) occurs, and an instance of a large smart contract needs to be split into two, this is achieved by a special transaction that creates the new instance by means of a constructor message sent from the previously existing instance to the new one.\n- One may say that a message is involved in transferring some information *across space* (between different shardchains, or at least accountchains), while an account state transfers information *across time* (from the past to the future of the same account).\n\n### 4.1.8. Differences between messages and account states\n\nOf course, there are important differences, too. For example:\n\n- The account state is transferred only \"in time\" (for a shardchain block to its successor), but never \"in space\" (from one shardchain to another). As a consequence, this transfer is done implicitly, without creating complete copies of the account state anywhere in the blockchain.\n- Storage payments collected by the validators for keeping the account state usually are considerably smaller than message forwarding fees for the same amount of data.\n- When an inbound message is delivered to an account, it is the code from the account that is invoked, not the code from the message.\n\n### 4.1.9. The combined state of all accounts in a shard\n\nThe split part of the shardchain state ([1.2.1](#1-2-1-the-infinite-sharding-paradigm-isp-applied-to-blockchain-block-and-state) and [1.2.2](#1-2-2-split-and-non-split-part-of-the-shardchain-block-and-state)) is given by\n\n```\n_ (HashmapAugE 256 Account CurrencyCollection) = ShardAccounts;\n```\n\nThis is simply a dictionary with 256-bit $\\mathit{account\\_id}$s as keys and corresponding account states as values, sum-augmented by the balances of the accounts. In this way the sum of balances of all accounts in a shardchain is computed, so that one can easily check the total amount of cryptocurrency \"stored\" in a shard.\n\nInternal consistency conditions ensure that the address of an account referred to by key $k$ in *SmartAccounts* is indeed equal to $k$. An additional internal consistency condition requires that all keys $k$ begin with the shard prefix $s$.\n\n### 4.1.10. Account owner and interface descriptions\n\nOne may want to include some optional information in a controlled account. For example, an individual user or a company may want to add a text description field to their wallet account, with the user's or company's name or address (or their hash, if the information should not be made publicly available). Alternatively, a smart contract may offer a machine-readable or human-readable description of its supported methods and their intended application, which might be used by advanced wallet applications to construct drop-down menus and forms helping a human user to create valid messages to be sent to that smart contract.\n\nOne way of including such information is to reserve, say, the second reference in the `data` cell of the state of an account for a dictionary with 64-bit keys (corresponding to some identifiers of the standard types of extra data one might want to store) and corresponding values. Then a blockchain explorer would be able to extract the required value, along with a Merkle proof if necessary.\n\nA better way of doing this is by defining some *get methods* in the smart contract.\n\n### 4.1.11. Get methods of a smart contract\n\n*Get methods* are executed by a stand-alone instance of TVM with the account's code and data loaded into it. The required parameters are passed on the stack (say, a magic number indicating the field to be fetched or the specific get method to be invoked), and the results are returned on the TVM stack as well (say, a cell slice containing the serialization of a string with the account owner's name).\n\nAs a bonus, get methods may be used to get answers to more sophisticated queries than just fetching a constant object. For instance, TON DNS registry smart contracts provide get methods to look up a domain string in the registry and return the corresponding record, if found.\n\nBy convention, get methods use large *negative* 32-bit or 64-bit indices or magic numbers, and internal functions of a smart contract use consecutive *positive* indices, to be used in TVM's $\\texttt{CALLDICT}$ instruction. The `main()` function of a smart contract, used to process inbound messages in ordinary transactions, always has index zero.\n\n---\n\n## 4.2   Transactions\n\nAccording to the Infinite Sharding Paradigm and the actor model, the three principal components of the TON Blockchain are *accounts* (along with their states), *messages*, and *transactions*. Previous sections have already discussed the first two; this section considers transactions.\n\nIn contrast with messages, which have essentially the same headers throughout all workchains of the TON Blockchain, and accounts, which have at least some common parts (the address and the balance), our discussion of transactions is necessarily limited to the masterchain and the basic workchain. Other workchains may define completely different kinds of transactions.\n\n### 4.2.1. Logical time of a transaction\n\nEach transaction $t$ has a logical time interval $\\text{Lt}^\\bullet(t)=[\\text{Lt}^-(t),\\text{Lt}^+(t))$ assigned to it ([1.4.6](#1-4-6-logical-time-in-the-ton-blockchain) and [1.4.3](#1-4-3-logical-time-intervals)). By convention, a transaction $t$ generating $n$ outbound messages $m_1$, $\\ldots$, $m_n$ is assigned a logical time interval of length $n+1$, so that\n\n$$\n\\mathrm{L}{\\small\\mathrm{t}}^+(t) = \\mathrm{L}{\\small\\mathrm{t}}^-(t) + n + 1 \\quad . \\tag{16}\n$$\n\nWe also set $\\mathrm{L}{\\small\\mathrm{t}}(t) := \\mathrm{L}{\\small\\mathrm{t}}^-(t)$, and assign the logical creation time of message $m_i$, where $1 \\leq i \\leq n$, by\n\n$$\n\\mathrm{L}{\\small\\mathrm{t}}(m_i) = \\mathrm{L}{\\small\\mathrm{t}}^-(m_i) := \\mathrm{L}{\\small\\mathrm{t}}^-(t) + i, \\quad \\mathrm{L}{\\small\\mathrm{t}}^+(m_i) := \\mathrm{L}{\\small\\mathrm{t}}^-(m_i) + 1 \\quad . \\tag{17}\n$$\n\nIn this way, each generated outbound message is assigned its own unit interval inside the logical time interval $\\text{Lt}^\\bullet(t)$ of transaction $t$.\n\n### 4.2.2. Logical time uniquely identifies transactions and outbound messages of an account\n\nRecall that the conditions imposed on logical time imply that $\\text{Lt}^-(t)\\geq\\text{Lt}^+(t')$ for any preceding transaction $t'$ of the same account $\\xi$, and that $\\text{Lt}^-(t)>\\text{Lt}(m)$ if $m$ is the inbound message processed by transaction $t$. In this way, the logical time intervals of transactions of the same account do not intersect each other, and as a consequence, the logical time intervals of all outbound messages generated by an account do not intersect each other either. In other words, all $\\text{Lt}(m)$ are different, when $m$ runs through all outbound messages of the same account $\\xi$.\n\nIn this way, $\\text{Lt}(t)$ and $\\text{Lt}(m)$, when combined with an account identifier $\\xi$, uniquely determine a transaction $t$ or an outbound message $m$ of that account. Furthermore, if one has an ordered list of all transactions of an account along with their logical times, it is easy to find the transaction that generated a given outbound message $m$, simply by looking up the transaction $t$ with logical time $\\text{Lt}(t)$ nearest to $\\text{Lt}(m)$ from below.\n\n### 4.2.3. Generic components of a transaction\n\nEach transaction $t$ contains or indirectly refers to the following data:\n\n- The account $\\xi$ to which the transaction belongs.\n- The logical time $\\text{Lt}(t)$ of the transaction.\n- One or zero inbound messages $m$ processed by the transaction.\n- The number of generated outbound messages $n\\geq0$.\n- The outbound messages $m_1, \\ldots, m_n$.\n- The initial state of account $\\xi$ (including its balance).\n- The final state of account $\\xi$ (including its balance).\n- The total fees collected by the validators.\n- A detailed description of the transaction containing all or some data needed to validate it, including the [kind of the transaction](#4-2-4-kinds-of-transactions) and some of the intermediate steps performed.\n\nOf these components, all but the very last one are quite general and might appear in other workchains as well.\n\n### 4.2.4. Kinds of transactions\n\nThere are different kinds of transactions allowed in the masterchain and the shardchains. *Ordinary* transactions consist in the delivery of one inbound message to an account, and its processing by that account's code; this is the most common kind of transaction. Additionally, there are several kinds of *exotic* transactions.\n\nAltogether, there are six kinds of transactions:\n\n- *Ordinary transactions* — Belong to an account $\\xi$. They process exactly one inbound message $m$ (described in *InMsgDescr* of the encompassing block) with destination $\\xi$, compute the new state of the account, and generate several outbound messages (registered in *OutMsgDescr*) with source $\\xi$.\n- *Storage transactions* — Can be inserted by validators at their discretion. They do not process any inbound message and do not invoke any code. Their only effect is to collect storage payments from an account, affecting its storage statistics and its balance. If the resulting Gram balance of the account becomes less than a certain amount, the account may be frozen and its code and data replaced by their combined hash.\n- *Tick transactions* — Automatically invoked for certain special accounts (smart contracts) in the masterchain that have the `tick` flag set in their state, as the very first transactions in every masterchain block. They have no inbound message, but may generate outbound messages and change the account state. For instance, *validator elections* are performed by tick transactions of special smart contracts in the masterchain.\n- *Tock transactions* — Similarly automatically invoked as the very last transactions in every masterchain block for certain special accounts.\n- *Split transactions* — Invoked as the last transactions of shardchain blocks immediately preceding a shardchain split event. They are triggered automatically for instances of large smart contracts that need to produce a new instance after splitting.\n- *Merge transactions* — Similarly invoked as the first transactions of shardchain blocks immediately after a shardchain merge event, if an instance of a large smart contract needs to be merged with another instance of the same smart contract.\n\nNotice that out of these six kinds of transactions, only four can occur in the masterchain, and another subset of four can occur in the basic workchain.\n\n### 4.2.5. Phases of an ordinary transaction\n\nAn ordinary transaction is performed in several *phases*, which may be thought of as several \"sub-transactions\" tightly bound into one:\n\n- *Storage phase* — Collects due storage payments for the account state (including smart-contract code and data, if present) up to the present time. The smart contract may be *frozen* as a result. If the smart contract did not exist before, the storage phase is absent.\n- *Credit phase* — The account is credited with the value of the inbound message received.\n- *Computing phase* — The code of the smart contract is invoked inside an instance of TVM with adequate parameters, including a copy of the inbound message and of the persistent data, and terminates with an exit code, the new persistent data, and an *action list* (which includes, for instance, outbound messages to be sent). The processing phase may lead to the creation of a new account (uninitialized or active), or to the activation of a previously uninitialized or frozen account. The *gas payment*, equal to the product of the gas price and the gas consumed, is exacted from the account balance.\n- *Action phase* — If the smart contract has terminated successfully (with exit code 0 or 1), the actions from the list are performed. If it is impossible to perform all of them—for example, because of insufficient funds to transfer with an outbound message—then the transaction is aborted and the account state is rolled back. The transaction is also aborted if the smart contract did not terminate successfully, or if it was not possible to invoke the smart contract at all because it is uninitialized or frozen.\n- *Bounce phase* — If the transaction has been aborted, and the inbound message has its `bounce` flag set, then it is \"bounced\" by automatically generating an outbound message (with the `bounce` flag clear) to its original sender. Almost all value of the original inbound message (minus gas payments and forwarding fees) is transferred to the generated message, which otherwise has an empty body.\n\n### 4.2.6. Bouncing inbound messages to non-existent accounts\n\nNotice that if an inbound message with its `bounce` flag set is sent to a previously non-existent account, and the transaction is aborted (for instance, because there is no code and data with the correct hash in the inbound message, so the virtual machine could not be invoked at all), then the account is not created even as an uninitialized account, since it would have zero balance and no code and data anyways.<a id=\"ref-fn31\"></a><sup>[31](#fn31)</sup>\n\n### 4.2.7. Processing of an inbound message is split between computing and action phases\n\nNotice that the processing of an inbound message is in fact split into two phases: the *computing* phase and the *action* phase. During the computing phase, the virtual machine is invoked and the necessary computations are performed, but no actions outside the virtual machine are taken. In other words, *the execution of a smart contract in TVM has no side effects*; there is no way for a smart contract to interact with the blockchain directly during its execution. Instead, TVM primitives such as $\\texttt{SENDMSG}$ simply store the required action (e.g., the outbound message to be sent) into the action list being gradually accumulated in TVM control register $\\texttt{c5}$. The actions themselves are postponed until the action phase, during which the user smart contract is not invoked at all.\n\n### 4.2.8. Reasons for splitting the processing into computation and action phases\n\nSome reasons for such an arrangement are:\n\n- It is simpler to abort the transaction if the smart contract eventually terminates with an exit code other than 0 or 1.\n- The rules for processing output actions may be changed without modifying the virtual machine. (For instance, new output actions may be introduced.)\n- The virtual machine itself may be modified or even replaced by another one (for instance, in a new workchain) without changing the rules for processing output actions.\n- The execution of the smart contract inside the virtual machine is completely isolated from the blockchain and is a *pure computation*. As a consequence, this execution may be *virtualized* inside the virtual machine itself by means of TVM's $\\texttt{RUNVM}$ primitive, a useful feature for validator smart contracts and for smart contracts controlling payment channels and other sidechains. Additionally, the virtual machine may be *emulated* inside itself or a stripped-down version of itself, a useful feature for validating the execution of smart contracts inside TVM.<a id=\"ref-fn32\"></a><sup>[32](#fn32)</sup>\n\n### 4.2.9. Storage, tick, and tock transactions\n\nStorage transactions are very similar to a stand-alone storage phase of an ordinary transaction. Tick and tock transactions are similar to ordinary transactions without credit and bounce phases, because there is no inbound message.\n\n### 4.2.10. Split transactions\n\nSplit transactions in fact consist of two transactions. If an account $\\xi$ needs to be split into two accounts $\\xi$ and $\\xi'$:\n\n- First a *split prepare transaction*, similar to a tock transaction (but in a shardchain instead of the masterchain), is issued for account $\\xi$. It must be the last transaction for $\\xi$ in a shardchain block. The output of the processing stage of a split prepare transaction consists not only of the new state of account $\\xi$, but also of the new state of account $\\xi'$, represented by a [constructor message](#4-1-7-account-state-as-a-message-from-an-account-to-its-future-self) to $\\xi'$.\n- Then a *split install transaction* is added for account $\\xi'$, with a reference to the corresponding split prepare transaction. The split install transaction must be the only transaction for a previously non-existent account $\\xi'$ in the block. It effectively sets the state of $\\xi'$ as defined by the split prepare transaction.\n\n### 4.2.11. Merge transactions\n\nMerge transactions also consist of two transactions each. If an account $\\xi'$ needs to be merged into account $\\xi$:\n\n- First a *merge prepare transaction* is issued for $\\xi'$, which converts all of its persistent state and balance into a [special constructor message](#4-1-7-account-state-as-a-message-from-an-account-to-its-future-self) with destination $\\xi$.\n- Then a *merge install transaction* for $\\xi$, referring to the corresponding merge prepare transaction, processes that constructor message. The merge install transaction is similar to a tick transaction in that it must be the first transaction for $\\xi$ in a block, but it is located in a shardchain block, not in the masterchain, and it has a special inbound message.\n\n### 4.2.12. Serialization of a general transaction\n\nAny transaction contains the [fields](#4-2-3-generic-components-of-a-transaction). As a consequence, there are some common components in all transactions:\n\n```\ntransaction$_ account_addr:uint256 lt:uint64 outmsg_cnt:uint15\n  orig_status:AccountStatus end_status:AccountStatus\n  in_msg:(Maybe ^(Message Any)) \n  out_msgs:(HashmapE 15 ^(Message Any))\n  total_fees:Grams state_update:^(MERKLE_UPDATE Account)\n  description:^TransactionDescr = Transaction;\n\n!merkle_update#02 {X:Type} old_hash:uint256 new_hash:uint256\n  old:^X new:^X = MERKLE_UPDATE X;\n```\n\nThe exclamation mark in the TL-B declaration of a `merkle_update` indicates special processing required for such values. In particular, they must be kept in a separate cell, which must be marked as [*exotic*](/foundations/whitepapers/tvm#3-1-7-types-of-exotic-cells) by a bit in its header.\n\nA full explanation of the serialization of *TransactionDescr*, which describes one transaction according to its [kind](#4-2-4-kinds-of-transactions), can be found in [Transaction descriptions](#4-3-transaction-descriptions).\n\n### 4.2.13. Representation of outbound messages generated by a transaction\n\nThe outbound messages generated by a transaction $t$ are kept in a dictionary `out_msgs` with 15-bit keys equal to 0, 1, $\\ldots$, $n-1$, where $n$=`outmsg_cnt` is the number of generated outbound messages. Message $m_{i+1}$ with index $0\\leq i<n$ must have $\\mathrm{L}{\\small\\mathrm{t}}(m_{i+1})=\\mathrm{L}{\\small\\mathrm{t}}(t)+i+1$, and $\\mathrm{L}{\\small\\mathrm{t}}(t)=\\mathrm{L}{\\small\\mathrm{t}}^-(t)$ is explicitly stored in the `lt` field.\n\n### 4.2.14. Consistency conditions for transactions\n\nThe common serialization of the fields present in a *Transaction*, independent of its type and description, enables us to impose several \"external\" consistency conditions on any transaction. The most important of them involves the *value flow* inside the transaction: the sum of all inputs (the import value of the inbound message plus the original balance of the account) must equal the sum of all outputs (the resulting balance of the account, plus the sum of the export values of all outbound messages, plus all storage, processing, and forwarding fees collected by the validators). In this way, a surface inspection of a transaction, which processes an inbound message with an import value of 1 Gram received by an account with an initial balance of 10 Gram, generating an outbound message with an export value of 100 Gram in the process, will reveal its invalidity even before checking all the details of the TVM execution.\n\nOther consistency conditions may slightly depend on the description of the transaction. For instance, the inbound message processed by an ordinary transaction must be registered in the *InMsgDescr* of the encompassing block, and the corresponding record must contain a reference to this transaction. Similarly, all outbound messages generated by all transactions (with the exception of one special message generated by a split prepare or merge prepare transaction) must be registered in *OutMsgDescr*.\n\n### 4.2.15. Collection of all transactions of an account\n\nAll transactions in a block belonging to the same account $\\xi$ are collected into an \"accountchain block\" *AccountBlock*, which essentially is a dictionary `transactions` with 64-bit keys, each equal to the logical time of the corresponding transaction:\n\n```\nacc_trans$_ account_addr:uint256\n            transactions:(HashmapAug 64 ^Transaction Grams)\n            state_update:^(MERKLE_UPDATE Account)\n          = AccountBlock;\n```\n\nThe `transactions` dictionary is sum-augmented by a *Grams* value, which aggregates the total fees collected from these transactions.\n\nIn addition to this dictionary, an *AccountBlock* contains a [Merkle update](/foundations/whitepapers/tvm#3-1-7-types-of-exotic-cells) of the total state of the account. If an account did not exist before the block, its state is represented by an `account_none`.\n\n### 4.2.16. Consistency conditions for *AccountBlocks*\n\nThere are several general consistency conditions imposed on an *AccountBlock*. In particular:\n\n- The transaction appearing as a value in the augmented `transactions` dictionary must have its `lt` value equal to its key.\n- All transactions must belong to an account whose address `account_addr` is indicated in the *AccountBlock*.\n- If $t$ and $t'$ are two transactions with $\\text{Lt}(t)<\\text{Lt}(t')$, and their keys are consecutive in `transactions`, meaning that there is no transaction $t''$ with $\\text{Lt}(t)<\\text{Lt}(t'')<\\text{Lt}(t')$, then the final state of $t$ must correspond to the initial state of $t'$ (their hashes as explicitly indicated in the Merkle updates must be equal).\n- If $t$ is the transaction with minimal $\\text{Lt}(t)$, its initial state must coincide with the initial state as indicated in `state_update` of the *AccountBlock*.\n- If $t$ is the transaction with maximal $\\text{Lt}(t)$, its final state must coincide with the final state as indicated in `state_update` of the *AccountBlock*.\n- The list of transactions must be non-empty.\n\nThese conditions simply express the fact that the state of an account may change only as the result of performing a transaction.\n\n### 4.2.17. Collection of all transactions in a block\n\nAll transactions in a block are represented by [1.2.1](#1-2-1-the-infinite-sharding-paradigm-isp-applied-to-blockchain-block-and-state):\n\n```\n_ (HashmapAugE 256 AccountBlock Grams) = ShardAccountBlocks;\n```\n\n### 4.2.18. Consistency conditions for the collection of all transactions\n\nAgain, consistency conditions are imposed on this structure, requiring that the value at key $\\xi$ be an *AccountBlock* with address equal to $\\xi$. Further consistency conditions relate this structure with the initial and final states of the shardchain indicated in the block, requiring that:\n\n- If *ShardAccountBlock* has no key $\\xi$, then the state of account $\\xi$ in the initial and in the final state of the block must coincide (or it must be absent from both).\n- If $\\xi$ is present in *ShardAccountBlock*, its initial and final states as indicated in AccountBlock must match those indicated in the initial and final states of the shardchain block, expressed by instances of [ShardAccounts](#4-1-9-the-combined-state-of-all-accounts-in-a-shard).\n\nThese conditions express that the shardchain state is indeed composed out of the states of separate accountchains.\n\n---\n\n## 4.3   Transaction descriptions\n\nThis section presents the specific TL-B schemes for transaction descriptions according to the [classification](#4-2-4-kinds-of-transactions).\n\n### 4.3.1. Reasons for omitting data from a transaction description\n\nA transaction description for a blockchain featuring a Turing-complete virtual machine for smart-contract execution is necessarily incomplete. Indeed, a truly complete description would contain all the intermediate states of the virtual machine after each instruction is executed, something that cannot fit into a blockchain block of a reasonable size. Therefore, the description of such a transaction is likely to contain only the total number of steps and the hashes of the initial and final states of the virtual machine. The validation of such a transaction will necessarily involve the execution of the smart contract to reproduce all the intermediate steps and the final result.\n\nIf we compress the sequence of all intermediate steps of the virtual machine into just the hashes of the initial and final states, then no transaction details at all need to be included: a validator able to check the execution of the virtual machine by itself would also be able to check all the other actions of the transaction starting from its initial data without these details.\n\n### 4.3.2. Reasons for including data into a transaction description\n\nThe above considerations notwithstanding, there are still several reasons to introduce some details in the transaction description:\n\n- We want to impose external [consistency conditions](#4-2-14-consistency-conditions-for-transactions) on the transaction, so that at least the validity of the value flow inside the transaction and the validity of inbound and outbound messages can be quickly checked without invoking the virtual machine. This at least guarantees the invariance of the total amount of each cryptocurrency in the blockchain, even if it does not guarantee the correctness of its distribution.\n- We want to be able to trace principal state changes of an account (such as its being created, activated, or frozen) by inspecting the data stored in the transaction description, without figuring out the missing details of the transaction. This simplifies the verification of the consistency conditions between the accountchain and shardchain states in a block.\n- Finally, certain information—such as the total steps of the virtual machine, the hashes of its initial and final states, the total gas consumed, and the exit code—might considerably simplify the debugging and implementation of the TON Blockchain software. (This information would help a human programmer understand what has happened in a particular blockchain block.)\n\nOn the other hand, we want to minimize the size of each transaction, because we want to maximize the number of transactions that can fit into each (bounded-size) block. Therefore, all information not required for one of the above reasons is omitted.\n\n### 4.3.3. Description of a storage phase\n\nThe storage phase is present in several kinds of transactions, so a common representation for this phase is used:\n\n```\ntr_phase_storage$_ storage_fees_collected:Grams \n  storage_fees_due:(Maybe Grams)\n  status_change:AccStatusChange\n  = TrStoragePhase;\n\nacst_unchanged$0 = AccStatusChange;  // x -> x\nacst_frozen$10 = AccStatusChange;    // init -> frozen\nacst_deleted$11 = AccStatusChange;   // frozen -> deleted\n```\n\n### 4.3.4. Description of a credit phase\n\nThe credit phase can result in the collection of some due payments:\n\n```\ntr_phase_credit$_ due_fees_collected:(Maybe Grams)\n  credit:CurrencyCollection = TrCreditPhase;\n```\n\nThe sum of `due_fees_collected` and `credit` must equal the value of the message received, plus its `ihr_fee` if the message has not been received via IHR (otherwise the `ihr_fee` is awarded to the validators).\n\n### 4.3.5. Description of a computing phase\n\nThe computing phase consists in invoking TVM with correct inputs. On some occasions, TVM cannot be invoked at all (e.g., if the account is absent, not initialized, or frozen, and the inbound message being processed has no code or data fields or these fields have an incorrect hash); this is reflected by corresponding constructors.\n\n```\ntr_phase_compute_skipped$0 reason:ComputeSkipReason\n  = TrComputePhase;\ntr_phase_compute_vm$1 success:Bool msg_state_used:Bool \n  account_activated:Bool gas_fees:Grams\n  _:^[ gas_used:(VarUInteger 7)\n  gas_limit:(VarUInteger 7) gas_credit:(Maybe (VarUInteger 3))\n  mode:int8 exit_code:int32 exit_arg:(Maybe int32)\n  vm_steps:uint32\n  vm_init_state_hash:uint256 vm_final_state_hash:uint256 ]\n  = TrComputePhase;\ncskip_no_state$00 = ComputeSkipReason;\ncskip_bad_state$01 = ComputeSkipReason;\ncskip_no_gas$10 = ComputeSkipReason;\n```\n\nThe TL-B construct `_:^[...]` describes a reference to a cell containing the fields listed inside the square brackets. In this way, several fields can be moved from a cell containing a large record into a separate subcell.\n\n### 4.3.6. Skipped computing phase\n\nIf the computing phase has been skipped, possible reasons include:\n\n- The absence of funds to buy gas.\n- The absence of a state (i.e., smart-contract code and data) in both the account (non-existing, uninitialized, or frozen) and the message.\n- An invalid state passed in the message (i.e., the state's hash differs from the expected value) to a frozen or uninitialized account.\n\n### 4.3.7. Valid computing phase\n\nIf there is no reason to skip the computing phase, TVM is invoked and the results of the computation are logged. Possible parameters are as follows:\n\n- The `success` flag is set if and only if `exit_code` is either 0 or 1.\n- The `msg_state_used` parameter reflects whether the state passed in the message has been used. If it is set, the `account_activated` flag reflects whether this has resulted in the activation of a previously frozen, uninitialized or non-existent account.\n- The `gas_fees` parameter reflects the total gas fees collected by the validators for executing this transaction. It must be equal to the product of `gas_used` and `gas_price` from the current block header.\n- The `gas_limit` parameter reflects the gas limit for this instance of TVM. It equals the lesser of either the Grams credited in the credit phase from the value of the inbound message divided by the current gas price, or the global per-transaction gas limit.\n- The `gas_credit` parameter may be non-zero only for external inbound messages. It is the lesser of either the amount of gas that can be paid from the account balance or the maximum gas credit.\n- The `exit_code` and `exit_args` parameters represent the status values returned by TVM.\n- The `vm_init_state_hash` and `vm_final_state_hash` parameters are the representation hashes of the original and resulting states of TVM, and `vm_steps` is the total number of steps performed by TVM (usually equal to two plus the number of instructions executed, including implicit RETs).<a id=\"ref-fn33\"></a><sup>[33](#fn33)</sup>\n\n### 4.3.8. Description of the action phase\n\nThe action phase occurs after a valid computation phase. It attempts to perform the actions stored by TVM during the computing phase into the *action list*. It may fail, because the action list may turn out to be too long, contain invalid actions, or contain actions that cannot be completed (for instance, because of insufficient funds to create an outbound message with the required value).\n\n```\ntr_phase_action$_ success:Bool valid:Bool no_funds:Bool\n  status_change:AccStatusChange\n  total_fwd_fees:(Maybe Grams) total_action_fees:(Maybe Grams)\n  result_code:int32 result_arg:(Maybe int32) tot_actions:int16\n  spec_actions:int16 msgs_created:int16 \n  action_list_hash:uint256 tot_msg_size:StorageUsed \n  = TrActionPhase;\n```\n\n### 4.3.9. Description of the bounce phase\n\n```\ntr_phase_bounce_negfunds$00 = TrBouncePhase;\ntr_phase_bounce_nofunds$01 msg_size:StorageUsed\n  req_fwd_fees:Grams = TrBouncePhase;\ntr_phase_bounce_ok$1 msg_size:StorageUsed \n  msg_fees:Grams fwd_fees:Grams = TrBouncePhase;\n```\n\n### 4.3.10. Description of an ordinary transaction\n\n```\ntrans_ord$0000 storage_ph:(Maybe TrStoragePhase)\n  credit_ph:(Maybe TrCreditPhase)\n  compute_ph:TrComputePhase action:(Maybe ^TrActionPhase)\n  aborted:Bool bounce:(Maybe TrBouncePhase)\n  destroyed:Bool\n  = TransactionDescr;\n```\n\nSeveral consistency conditions are imposed on this structure:\n\n- `action` is absent if and only if the computing phase was unsuccessful.\n- The `aborted` flag is set either if there is no action phase or if the action phase was unsuccessful.\n- The bounce phase occurs only if the `aborted` flag is set and the inbound message was bounceable.\n\n### 4.3.11. Description of a storage transaction\n\nA storage transaction consists just of one stand-alone storage phase:\n\n```\ntrans_storage$0001 storage_ph:TrStoragePhase\n  = TransactionDescr;\n```\n\n### 4.3.12. Description of tick and tock transactions\n\nTick and tock transactions are similar to ordinary transactions without an inbound message, so there are no credit or bounce phases:\n\n```\ntrans_tick_tock$001 is_tock:Bool storage:TrStoragePhase\n  compute_ph:TrComputePhase action:(Maybe ^TrActionPhase)\n  aborted:Bool destroyed:Bool = TransactionDescr;\n```\n\n### 4.3.13. Split prepare and install transactions\n\nA split prepare transaction is similar to a tock transaction in a masterchain, but it must generate exactly one special constructor message; otherwise, the action phase is aborted.\n\n```\nsplit_merge_info$_ cur_shard_pfx_len:(## 6)\n  acc_split_depth:(## 6) this_addr:uint256 sibling_addr:uint256\n  = SplitMergeInfo;\ntrans_split_prepare$0100 split_info:SplitMergeInfo\n  compute_ph:TrComputePhase action:(Maybe ^TrActionPhase)\n  aborted:Bool destroyed:Bool\n  = TransactionDescr;\ntrans_split_install$0101 split_info:SplitMergeInfo\n  prepare_transaction:^Transaction\n  installed:Bool = TransactionDescr;\n```\n\nNotice that the split install transaction for the new sibling account $\\xi'$ refers to its corresponding split prepare transaction of the previously existing account $\\xi$.\n\n### 4.3.14. Merge prepare and install transactions\n\nA merge prepare transaction converts the state and balance of an account into a message, and a subsequent merge install transaction processes this state:\n\n```\ntrans_merge_prepare$0110 split_info:SplitMergeInfo\n  storage_ph:TrStoragePhase aborted:Bool\n  = TransactionDescr;\ntrans_merge_install$0111 split_info:SplitMergeInfo\n  prepare_transaction:^Transaction\n  credit_ph:(Maybe TrCreditPhase)\n  compute_ph:TrComputePhase action:(Maybe ^TrActionPhase)\n  aborted:Bool destroyed:Bool\n  = TransactionDescr;\n```\n\n---\n\n## 4.4  Invoking smart contracts in TVM\n\nThis section describes the exact parameters with which TVM is invoked during the computing phase of ordinary and other transactions.\n\n### 4.4.1 Smart-contract code\n\nThe *code* of a smart contract is normally a part of the account's persistent state, at least if the account is [active](#4-1-6-account-balance). However, a frozen or uninitialized (or non-existent) account has no persistent state, with the possible exception of the account's balance and the hash of its intended state (equal to the account address for uninitialized accounts). In this case, the code must be supplied in the `init` [field](#3-1-7-message-layout) of the inbound message being processed by the transaction.\n\n### 4.4.2. Smart-contract persistent data\n\nThe *persistent data* of a smart contract is kept alongside its code, and remarks similar to those made [above](#4-4-1-smart-contract-code) apply. In this respect, the code and persistent data of a smart contract are just two parts of its persistent state, which differ only in the way they are treated by TVM during smart-contract execution.\n\n### 4.4.3. Smart-contract library environment\n\nThe *library environment* of a smart contract is a hashmap mapping 256-bit cell (representation) hashes into the corresponding cells themselves. When an external cell reference is accessed during the execution of a smart contract, the cell referred to is looked up in the library environment and the external cell reference is transparently replaced by the cell found.\n\nThe library environment for an invocation of a smart contract is computed as follows:\n\n1. The global library environment for the workchain in question is taken from the current state of the masterchain.<a id=\"ref-fn34\"></a><sup>[34](#fn34)</sup>\n2. Next, it is augmented by the local library environment of the smart contract, stored in the `library` field of the smart contract's state. Only 256-bit keys equal to the hashes of the corresponding value cells are taken into account. If a key is present in both the global and local library environments, the local environment takes precedence while merging the two library environments.\n3. Finally, the message library stored in the `library` field of the init field of the inbound message is similarly taken into account. Notice, however, that if the account is frozen or uninitialized, the `library` field of the message is part of the suggested state of the account, and is used instead of the local library environment in the previous step. The message library has lower precedence than both the local and the global library environments.\n\n### 4.4.4. The initial state of TVM\n\nA new instance of TVM is initialized prior to the execution of a smart contract as follows:\n\n- The original $\\texttt{cc}$ (current continuation) is initialized using the cell slice created from the cell $\\texttt{code}$, containing the code of the [smart contract](#4-4-1-smart-contract-code).\n- The $\\texttt{cp}$ (TVM codepage) is set to zero. If the smart contract wants to use another TVM codepage $x$, it must switch to it by using $\\texttt{SETCODEPAGE}$ $x$ as the first instruction of its code.\n- Control register $\\texttt{c0}$ (return continuation) is initialized by extraordinary continuation `ec_quit` with parameter 0. When executed, this continuation leads to a termination of TVM with exit code 0.\n- Control register $\\texttt{c1}$ (alternative return continuation) is initialized by extraordinary continuation `ec_quit` with parameter 1. When invoked, it leads to a termination of TVM with exit code 1. (Notice that terminating with exit code 0 or 1 is considered a successful termination.)\n- Control register $\\texttt{c2}$ (exception handler) is initialized by extraordinary continuation `ec_quit_exc`. When invoked, it takes the top integer from the stack (equal to the exception number) and terminates TVM with exit code equal to that integer. In this way, by default all exceptions terminate the smart-contract execution with exit code equal to the exception number.\n- Control register $\\texttt{c3}$ (code dictionary) is initialized by the cell with the smart-contract code, similarly to the initial current continuation ($\\texttt{cc}$).\n- Control register $\\texttt{c4}$ (root of persistent data) is initialized by the persistent data of the smart contract.<a id=\"ref-fn35\"></a><sup>[35](#fn35)</sup>\n- Control register $\\texttt{c5}$ (root of actions) is initialized by an empty cell. The \"output action\" primitives of TVM, such as $\\texttt{SENDMSG}$, use $\\texttt{c5}$ to accumulate the list of actions (e.g., outbound messages) to be performed upon successful termination of the smart contract ([4.2.7](#4-2-7-processing-of-an-inbound-message-is-split-between-computing-and-action-phases) and [4.2.8](#4-2-8-reasons-for-splitting-the-processing-into-computation-and-action-phases)).\n- Control register $\\texttt{c7}$ (root of temporary data) is initialized by a singleton *Tuple*, the only component of which is a *Tuple* containing an instance of *SmartContractInfo* with smart contract balance and other [useful information](#4-4-10-smart-contract-information). The smart contract may replace the temporary data, especially all components of the *Tuple* at $\\texttt{c7}$ but the first one, with whatever other temporary data it may require. However, the original content of the *SmartContractInfo* at the first component of the *Tuple* held in $\\texttt{c7}$ is inspected and sometimes modified by $\\texttt{SENDMSG}$ TVM primitives and other \"output action\" primitives of TVM.\n- The *gas limits* $\\texttt{gas}=(g_m,g_l,g_c,g_r)$ are initialized as follows:\n  - The *maximal gas limit* $g_m$ is set to the lesser of either the total Gram balance of the smart contract (after the the credit phase—i.e., combined with the value of the inbound message) divided by the current gas price, or the per-execution global gas limit.<a id=\"ref-fn36\"></a><sup>[36](#fn36)</sup>\n  - The c*urrent gas limit* $g_l$ is set to the lesser of either the Gram value of the inbound message divided by the gas price, or the global per-execution gas limit. In this way, always $g_l\\leq g_m$. For inbound external messages $g_l=0$, since they cannot carry any value.\n  - The *gas credit* $g_c$ is set to zero for inbound internal messages, and to the lesser of either $g_m$ or a fixed small value (the default external message gas credit, a configurable parameter) for inbound external messages.\n  - Finally, the *remaining gas* limit $g_r$ is automatically initialized by $g_l+g_c$.\n\n### 4.4.5. The initial stack of TVM for processing an internal message\n\nAfter [TVM is initialized](#4-4-4-the-initial-state-of-tvm), its stack is initialized by pushing the arguments to the main() function of the smart contract as follows:\n\n- The Gram balance $b$ of the smart contract (after crediting the value of the inbound message) is passed as an *Integer* amount of nanograms.\n- The Gram balance $b_m$ of inbound message $m$ is passed as an *Integer* amount of nanograms.\n- The inbound message $m$ is passed as a cell, which contains a serialized value of type *Message* $X$, where $X$ is the type of the message body.\n- The body $m_b:X$ of the inbound message, equal to the value of field body of $m$, is passed as a cell slice.\n- Finally, the function selector $s$, an *Integer* normally equal to zero, is pushed into the stack.\n\nAfter that, the code of the smart contract, equal to its initial value of $\\texttt{c3}$, is executed. It selects the correct function according to $s$, which is expected to process the remaining arguments to the function and terminate afterwards.\n\n### 4.4.6. Processing an inbound external message\n\nAn inbound external message is processed similarly to [4.4.4](#4-4-4-the-initial-state-of-tvm) and [4.4.5](#4-4-5-the-initial-stack-of-tvm-for-processing-an-internal-message), with the following modifications:\n\n- The function selector $s$ is set to $-1$, not to 0.\n- The Gram balance $b_m$ of inbound message is always 0.\n- The initial current gas limit $g_l$ is always 0. However, the initial gas credit $g_c>0$.\n\nThe smart contract must terminate with $g_c=0$ or $g_r\\geq g_c$; otherwise, the transaction and the block containing it are invalid. Validators or collators suggesting a block candidate must never include transactions processing inbound external messages that are invalid.\n\n### 4.4.7. Processing tick and tock transactions\n\nThe TVM stack for processing [tick and tock transactions](#4-2-4-kinds-of-transactions) is initialized by pushing the following values:\n\n- The Gram balance $b$ of the current account in nanograms (an *Integer*).\n- The 256-bit address $\\xi$ of the current account inside the masterchain, represented by an unsigned *Integer*.\n- An integer equal to $0$ for tick transactions and to $-1$ for tock transactions.\n- The function selector $s$, equal to $-2$.\n\n### 4.4.8. Processing split prepare transactions\n\nFor processing [split prepare transactions](#4-3-13-split-prepare-and-install-transactions), the TVM stack is initialized by pushing the following values:\n\n- The Gram balance $b$ of the current account.\n- A Slice containing [SplitMergeInfo](#4-3-13-split-prepare-and-install-transactions).\n- The 256-bit address $\\xi$ of the current account.\n- The 256-bit address $\\tilde\\xi$ of the sibling account.\n- An integer $0\\leq d\\leq 63$, equal to the position of the only bit in which $\\xi$ and $\\tilde\\xi$ differ.\n- The function selector $s$, equal to $-3$.\n\n### 4.4.9. Processing merge install transactions\n\nFor processing [merge install transactions](#4-3-14-merge-prepare-and-install-transactions), the TVM stack is initialized by pushing the following values:\n\n- The Gram balance $b$ of the current account (already combined with the Gram balance of the sibling account).\n- The Gram balance $b'$ of the sibling account, taken from the inbound message $m$.\n- The message $m$ from the sibling account, automatically generated by a merge prepare transaction. Its `init` field contains the final state $\\tilde S$ of the sibling account.\n- The state $\\tilde S$ of the sibling account, represented by a [StateInit](#3-1-7-message-layout).\n- A *Slice* containing [SplitMergeInfo](#4-3-13-split-prepare-and-install-transactions).\n- The 256-bit address $\\xi$ of the current account.\n- The 256-bit address $\\tilde\\xi$ of the sibling account.\n- An integer $0\\leq d\\leq 63$, equal to the position of the only bit in which $\\xi$ and $\\tilde\\xi$ differ.\n- The function selector $s$, equal to $-4$.\n\n### 4.4.10. Smart-contract information\n\nThe smart-contract information structure *SmartContractInfo*, passed in the first component of the *Tuple* contained in control register $\\texttt{c7}$, is also a *Tuple* containing the following data:\n\n```\n[ magic:0x076ef1ea actions:Integer msgs_sent:Integer\n  unixtime:Integer block_lt:Integer trans_lt:Integer \n  rand_seed:Integer balance_remaining:[Integer (Maybe Cell)]\n  myself:MsgAddressInt global_config:(Maybe Cell) \n] = SmartContractInfo;\n```\n\nIn other words, the first component of this tuple is an *Integer* `magic` always equal to `0x076ef1ea`, the second component is an *Integer* `actions`, originally initialized by zero, but incremented by one whenever an output action is installed by a non-`RAW` output action primitive of the TVM, and so on. The remaining balance is represented by a pair, i.e., a two-component *Tuple*: the first component is the nanogram balance, and the second component is a dictionary with 32-bit keys representing [all other currencies](#3-1-6-representing-collections-of-arbitrary-currencies), if any.\n\nThe `rand_seed` field (an unsigned 256-bit integer) here is initialized deterministically starting from the `rand_seed` of the block, the account address, the hash of the inbound message being processed (if any), and the transaction logical time `trans_lt`.\n\n### 4.4.11. Serialization of output actions\n\nThe *output actions* of a smart contract are accumulated in a linked list stored in control register $\\texttt{c5}$. The list of output actions is serialized as a value of type *OutList* $n$, where $n$ is the length of the list:\n\n```\nout_list_empty$_ = OutList 0;\nout_list$_ {n:#} prev:^(OutList n) action:OutAction\n  = OutList (n + 1);\naction_send_msg#0ec3c86d out_msg:^(Message Any) = OutAction;\naction_set_code#ad4de08e new_code:^Cell = OutAction;\n```\n---\n\n# 5   Block layout\n\nThis chapter presents the block layout used by the TON Blockchain, combining the data structures described separately in previous chapters to produce a complete description of a shardchain block. In addition to the TL-B schemes that define the representation of a shardchain block by a tree of cells, this chapter describes exact serialization formats for the resulting bags (collections) of cells, which are necessary to represent a shardchain block as a file.\n\nMasterchain blocks are similar to shardchain blocks, but have some additional fields. The necessary modifications are discussed separately in [Masterchain block layout](#5-2-masterchain-block-layout).\n\n## 5.1   Shardchain block layout\n\nThis section lists the data structures that must be contained in a shardchain block and in the shardchain state, and concludes by presenting a formal TL-B scheme for a shardchain block.\n\n### 5.1.1. Components of the shardchain state\n\nThe shardchain state consists of:\n\n- *ShardAccounts*, the [split](#1-2-2-split-and-non-split-part-of-the-shardchain-block-and-state) part of the shardchain state containing the state of [all accounts](#4-1-9-the-combined-state-of-all-accounts-in-a-shard) assigned to this shard.\n- [OutMsgQueue](#3-3-6-structure-of-outmsgqueue), the output message queue of the shardchain.\n- *SharedLibraries*, the description of all shared libraries of the shardchain (for now, non-empty only in the masterchain).\n- The logical time and the unixtime of the last modification of the state.\n- The total balance of the shard.\n- A hash reference to the most recent masterchain block, indirectly describing the state of the masterchain and, through it, the [state](#1-5-2-total-state-defined-by-a-shardchain-block) of all other shardchains of the TON Blockchain.\n\n### 5.1.2. Components of a shardchain block\n\nA shardchain block must contain:\n\n- A list of [validator signatures](#1-2-6-validator-signatures%2C-signed-and-unsigned-blocks), which is external with respect to all other contents of the block.\n- [BlockHeader](#1-2-5-block-header), containing general information about the block\n- Hash references to the immediately preceding block or blocks of the same shardchain, and to the most recent masterchain block.\n- [InMsgDescr](#3-2-8-structure-of-inmsgdescr) and [OutMsgDescr](#3-3-5-structure-of-outmsgdescr), the inbound and outbound message descriptors.\n- *ShardAccountBlocks*, the [collection](#4-2-17-collection-of-all-transactions-in-a-block) of all transactions processed in the block along with all updates of the states of the accounts assigned to the shard. This is the *split* part of the [shardchain block](#1-2-2-split-and-non-split-part-of-the-shardchain-block-and-state).\n- The *value flow*, describing the total value imported from the preceding blocks of the same shardchain and from inbound messages, the total value exported by outbound message, the total fees collected by validators, and the total value remaining in the shard.\n- A [Merkle update](/foundations/whitepapers/tvm#3-1-7-types-of-exotic-cells) of the shardchain state. Such a Merkle update contains the hashes of the initial and final shardchain states with respect to the block, along with all new cells of the final state that have been created while processing the block.<a id=\"ref-fn37\"></a><sup>[37](#fn37)</sup>\n\n### 5.1.3. Common parts of the block layout for all workchains\n\nRecall that different workchains may define their own rules for processing messages, other types of transactions, other components of the state, and other ways to serialize all this data. However, some components of the block and its state must be common for all workchains in order to maintain the interoperability between different workchains. Such common components include:\n\n- *OutMsgQueue*, the outbound message queue of a shardchain, which is scanned by neighboring shardchains for messages addressed to them.\n- The outer structure of *InMsgDescr* as a hashmap with 256-bit keys equal to the hashes of the imported messages. (The inbound message descriptors themselves need not have the same structure.)\n- Some fields in the block header identifying the shardchain and the block, along with the paths from the block header to the other information indicated in this list.\n- The value flow information.\n\n### 5.1.4. TL-B scheme for the shardchain state\n\nThe shardchain state [1.2.1](#1-2-1-the-infinite-sharding-paradigm-isp-applied-to-blockchain-block-and-state) and [5.1.1](#5-1-1-components-of-the-shardchain-state) is serialized according to the following TL-B scheme:\n\n```\next_blk_ref$_ start_lt:uint64 end_lt:uint64\n  seq_no:uint32 hash:uint256 = ExtBlkRef;\n\nmaster_info$_ master:ExtBlkRef = BlkMasterInfo;\n\nshard_ident$00 shard_pfx_bits:(## 6) \n  workchain_id:int32 shard_prefix:uint64 = ShardIdent;\n\nshard_state shard_id:ShardIdent \n  out_msg_queue:OutMsgQueue\n  total_balance:CurrencyCollection\n  total_validator_fees:CurrencyCollection\n  accounts:ShardAccounts\n  libraries:(HashmapE 256 LibDescr)\n  master_ref:(Maybe BlkMasterInfo)\n  custom:(Maybe ^McStateExtra)\n  = ShardState;\n```\n\nThe field `custom` is usually present only in the masterchain and contains all the masterchain-specific data. However, other workchains may use the same cell reference to refer to their specific state data.\n\n### 5.1.5. Shared libraries description\n\nShared libraries currently can be present only in masterchain blocks. They are described by an instance of $\\textit{HashmapE}(256,\\textit{LibDescr})$, where the 256-bit key is the representation hash of the library, and $\\textit{LibDescr}$ describes one library:\n\n```\nshared_lib_descr$00 lib:^Cell publishers:(Hashmap 256 True)\n  = LibDescr;\n```\n\nHere `publishers` is a hashmap with keys equal to the addresses of all accounts that have published the corresponding shared library. The shared library is preserved as long as at least one account keeps it in its published libraries collection.\n\n### 5.1.6. TL-B scheme for an unsigned shardchain block\n\nThe precise format of an [unsigned](#1-2-6-validator-signatures%2C-signed-and-unsigned-blocks) shardchain block is given by the following TL-B scheme:\n\n```\nblock_info version:uint32 \n  not_master:(## 1) \n  after_merge:(## 1) before_split:(## 1) flags:(## 13)\n  seq_no:# vert_seq_no:# \n  shard:ShardIdent gen_utime:uint32\n  start_lt:uint64 end_lt:uint64\n  master_ref:not_master?^BlkMasterInfo \n  prev_ref:seq_no?^(BlkPrevInfo after_merge)\n  prev_vert_ref:vert_seq_no?^(BlkPrevInfo 0)\n  = BlockInfo;\n\nprev_blk_info#_ {merged:#} prev:ExtBlkRef\n  prev_alt:merged?ExtBlkRef = BlkPrevInfo merged;\n\nunsigned_block info:^BlockInfo value_flow:^ValueFlow\n  state_update:^(MERKLE_UPDATE ShardState) \n  extra:^BlockExtra = Block;\n\nblock_extra in_msg_descr:^InMsgDescr\n  out_msg_descr:^OutMsgDescr\n  account_blocks:ShardAccountBlocks\n  rand_seed:uint256\n  custom:(Maybe ^McBlockExtra) = BlockExtra;\n```\n\nThe field `custom` is usually present only in the masterchain and contains all the masterchain-specific data. However, other workchains may use the same cell reference to refer to their specific block data.\n\n### 5.1.7. Description of total value flow through a block\n\nThe total value flow through a block is serialized according to the following TL-B scheme:\n\n```\nvalue_flow _:^[ from_prev_blk:CurrencyCollection \n  to_next_blk:CurrencyCollection\n  imported:CurrencyCollection\n  exported:CurrencyCollection ]\n  fees_collected:CurrencyCollection\n  _:^[\n  fees_imported:CurrencyCollection\n  created:CurrencyCollection\n  minted:CurrencyCollection\n  ] = ValueFlow;\n```\n\nRecall that `_:^[`...`]` is a TL-B construction indicating that a group of fields has been moved into a separate cell. The last three fields may be non-zero only in masterchain blocks.\n\n### 5.1.8. Signed shardchain block\n\nA signed shardchain block is just an unsigned block augmented by a collection of validator signatures:\n\n```\ned25519_signature#5 R:uint256 s:uint256 = CryptoSignature; \n\nsigned_block block:^Block blk_serialize_hash:uint256\n  signatures:(HashmapE 64 CryptoSignature)\n  = SignedBlock;\n```\n\nThe *serialization hash* `blk_serialize_hash` of the unsigned block `block` is essentially a hash of a specific [serialization](#5-3-12-the-serialization-hash-of-a-block) of the block into an octet string. The signatures collected in `signatures` are [Ed25519-signatures](#a-3-ed25519-cryptography) made with a validator's private keys of the SHA-256 of the concatenation of the 256-bit representation hash of the block `block` and of its 256-bit serialization hash `blk_serialize_hash`. The 64-bit keys in dictionary `signatures` represent the first 64 bits of the public keys of the corresponding validators.\n\n### 5.1.9. Serialization of a signed block\n\nThe overall procedure of serializing and signing a block may be described as follows:\n\n1. An unsigned block $B$ is generated, transformed into a [complete bag of cells](#5-3-2-complete-bags-of-cells), and serialized into an octet string $S_B$.\n\n2. Validators sign the 256-bit combined hash\n\n   $$\n   H_B:=\\text{Sha256}\\bigl(\\text{Hash}_\\infty(B).\\text{Hash}_M(S_B)\\bigr) \\tag{18}\n   $$\n\n   of the representation hash of $B$ and of the Merkle hash of its serialization $S_B$.\n\n3. A [signed shardchain block](#5-1-8-signed-shardchain-block) $\\tilde B$ is generated from $B$ and these validator signatures.\n\n4. This signed block $\\tilde B$ is transformed into an incomplete bag of cells, which contains only the validator signatures, but the unsigned block itself is absent from this bag of cells, being its only absent cell.\n\n5. This incomplete bag of cells is serialized, and its serialization is prepended to the previously constructed serialization of the unsigned block.\n\nThe result is the serialization of the signed block into an octet string. It may be propagated by network or stored into a disk file.\n\n---\n\n## 5.2   Masterchain block layout\n\nMasterchain blocks are very similar to shardchain blocks of the basic workchain. This section lists some of the modifications needed to obtain the description of a masterchain block from the description of a [shardchain block](#5-1-shardchain-block-layout).\n\n### 5.2.1 Additional components present in the masterchain state\n\nIn addition to the [components of the shardchain state](#5-1-1-components-of-the-shardchain-state), the masterchain state must contain:\n\n- *ShardHashes* — Describes the current shard configuration, and contains the hashes of the latest blocks of the corresponding shardchains.\n- *ShardFees* — Describes the total fees collected by the validators of each shardchain.\n- *ShardSplitMerge* — Describes future shard split/merge events. It is serialized as a part of *ShardHashes*.\n- *ConfigParams* — Describes the values of all configurable parameters of the TON Blockchain.\n\n### 5.2.2. Additional components present in masterchain blocks\n\nIn addition to the [components of the shardchain block](#5-1-2-components-of-a-shardchain-block), each masterchain block must contain:\n\n- *ShardHashes* — Describes the current shard configuration, and contains the hashes of the latest blocks of the corresponding shardchains. (Notice that this component is also present in the masterchain state.)\n\n### 5.2.3. Description of *ShardHashes*\n\n*ShardHashes* is represented by a dictionary with 32-bit $\\mathit{workchain\\_id}$s as keys, and \"shard binary trees\", represented by TL-B type *BinTree ShardDescr*, as values. Each leaf of this shard binary tree contains a value of type *ShardDescr*, which describes a single shard by indicating the sequence number `seq_no`, the logical time `lt`, and the hash `hash` of the latest (signed) block of the corresponding shardchain.\n```\nbt_leaf$0 {X:Type} leaf:X = BinTree X;\nbt_fork$1 {X:Type} left:^(BinTree X) right:^(BinTree X) \n          = BinTree X;\n\nfsm_none$0 = FutureSplitMerge;\nfsm_split$10 mc_seqno:uint32 = FutureSplitMerge;\nfsm_merge$11 mc_seqno:uint32 = FutureSplitMerge;\n\nshard_descr$_ seq_no:uint32 lt:uint64 hash:uint256 \n  split_merge_at:FutureSplitMerge = ShardDescr;\n\n_ (HashmapE 32 ^(BinTree ShardDescr)) = ShardHashes;\n```\n\nFields `mc_seqno` of `fsm_split` and `fsm_merge` are used to signal future shard merge or split events. Shardchain blocks referring to masterchain blocks with sequence numbers up to, but not including, the one indicated in `mc_seqno` are generated in the usual way. Once the indicated sequence number is reached, a shard merge or split event must occur.\n\nNotice that the masterchain itself is omitted from *ShardHashes* (i.e., 32-bit index $-1$ is absent from this dictionary).\n\n### 5.2.4. Description of *ShardFees*\n\n*ShardFees* is a masterchain structure used to reflect the total fees collected so far by the validators of a shardchain. The total fees reflected in this structure are accumulated in the masterchain by crediting them to a special account, whose address is a configurable parameter. Typically this account is the smart contract that computes and distributes the rewards to all validators.\n\n```\nbta_leaf$0 {X:Type} {Y:Type} leaf:X extra:Y = BinTreeAug X Y;\nbta_fork$1 {X:Type} {Y:Type} left:^(BinTreeAug X Y) \n           right:^(BinTreeAug X Y) extra:Y = BinTreeAug X Y;\n\n_ (HashmapAugE 32 ^(BinTreeAug True CurrencyCollection)\n  CurrencyCollection) = ShardFees;\n```\n\nThe structure of *ShardFees* is similar to that of [ShardHashes](#5-2-3-description-of-shardhashes), but the dictionary and binary trees involved are augmented by currency values, equal to the `total_validator_fees` values of the final states of the corresponding shardchain blocks. The value aggregated at the root of *ShardFees* is added together with the `total_validator_fees` of the masterchain state, yielding the total TON Blockchain validator fees. The increase of the value aggregated at the root of *ShardFees* from the initial to the final state of a masterchain block is reflected in the `fees_imported` in the value flow of that masterchain block.\n\n### 5.2.5. Description of *ConfigParams*\n\nRecall that the [configurable parameters](#1-6-configurable-parameters-and-smart-contracts) or the *configuration dictionary* is a dictionary `config` with 32-bit keys kept inside the first cell reference of the persistent data of the configuration smart contract $\\gamma$. The address $\\gamma$ of the configuration smart contract and a copy of the configuration dictionary are duplicated in fields `config_addr` and `config` of a *ConfigParams* structure, explicitly included into masterchain state to [facilitate access](#1-6-3-quick-access-through-the-header-of-masterchain-blocks) to the current values of the configurable parameters:\n\n```\n_ config_addr:uint256 config:^(Hashmap 32 ^Cell) \n  = ConfigParams;\n```\n\n### 5.2.6. Masterchain state data\n\nThe data specific to the [masterchain state](#5-1-4-tl-b-scheme-for-the-shardchain-state) is collected into *McStateExtra*:\n\n```\nmasterchain_state_extra#cc1f\n  shard_hashes:ShardHashes\n  shard_fees:ShardFees\n  config:ConfigParams\n= McStateExtra;\n```\n\n### 5.2.7. Masterchain block data\n\nSimilarly, the data specific to the masterchain blocks is collected into *McBlockExtra*:\n\n```\nmasterchain_block_extra#cc9f\n  shard_hashes:ShardHashes\n= McBlockExtra;\n```\n\n---\n\n## 5.3   Serialization of a bag of cells\n\nThe description provided in the previous section defines the way a shardchain block is represented as a tree of cells. However, this tree of cells needs to be serialized into a file, suitable for disk storage or network transfer. This section discusses the standard ways of serializing a tree, a DAG, or a bag of cells into an octet string.\n\n### 5.3.1. Transforming a tree of cells into a bag of cells\n\nRecall that values of arbitrary (dependent) algebraic data types are represented in the TON Blockchain by *trees of cells*. Such a tree of cells is transformed into a directed acyclic graph, or *DAG*, of cells, by identifying identical cells in the tree. After that, we might replace each of the references of each cell by the 32-byte representation hash of the cell referred to and obtain a *bag of cells*. By convention, the root of the original tree of cells is a marked element of the resulting bag of cells, so that anybody receiving this bag of cells and knowing the marked element can reconstruct the original DAG of cells, hence also the original tree of cells.\n\n### 5.3.2. Complete bags of cells\n\nLet us say that a bag of cells is *complete* if it contains all cells referred to by any of its cells. In other words, a complete bag of cells does not have any \"unresolved\" hash references to cells outside that bag of cells. In most cases, we need to serialize only complete bags of cells.\n\n### 5.3.3. Internal references inside a bag of cells\n\nLet us say that a reference of a cell $c$ belonging to a bag of cells $B$ is *internal (with respect to* $B$) if the cell $c_i$ referred to by this reference belongs to $B$ as well. Otherwise, the reference is called *external*. A bag of cells is complete if and only if all references of its constituent cells are internal.\n\n### 5.3.4. Assigning indices to the cells from a bag of cells\n\nLet $c_0$, ..., $c_{n-1}$ be the $n$ distinct cells belonging to a bag of cells $B$. We can list these cells in some order, and then assign indices from $0$ to $n-1$, so that cell $c_i$ gets index $i$. Some options for ordering cells are:\n\n- Order cells by their representation hash. Then $\\text{Hash}(c_i)<\\text{Hash}(c_j)$ whenever $i<j$.\n- Topological order: if cell $c_i$ refers to cell $c_j$, then $i<j$. In general, there is more than one topological order for the same bag of cells. There are two standard ways for constructing topological orders:\n  - Depth-first order: apply a depth-first search to the directed acyclic graph of cells starting from its root (i.e., marked cell), and list cells in the order they are visited.\n  - Breadth-first order: same as above, but applying a breadth-first search.\n\nNotice that the topological order always assigns index $0$ to the root cell of a bag of cells constructed from a tree of cells. In most cases, we opt to use a topological order, or the depth-first order if we want to be more specific.\n\nIf cells are listed in a topological order, then the verification that there are no cyclic references in a bag of cells is immediate. On the other hand, ordering cells by their representation hash simplifies the verification that there are no duplicates in a serialized bag of cells.\n\n### 5.3.5. Outline of serialization process\n\nThe serialization process of a bag of cells $B$ consisting of $n$ cells can be outlined as follows:\n\n1. List the cells from $B$ in a topological order: $c_0$, $c_1$, ..., $c_{n-1}$. Then $c_0$ is the root cell of $B$.\n2. Choose an integer $s$, such that $n\\leq 2^s$. Represent each cell $c_i$ by an integral number of octets in the standard way ([1.1.3](#1-1-3-the-layout-of-a-single-cell) or [4, 3.1.4](/foundations/whitepapers/tvm#3-1-4-standard-cell-representation)), but using unsigned big-endian $s$-bit integer $j$ instead of hash $\\text{Hash}(c_j)$ to [represent](#5-3-6-serialization-of-one-cell-from-a-bag-of-cells) internal references to cell $c_j$.\n3. Concatenate the representations of cells $c_i$ thus obtained in the increasing order of $i$.\n4. Optionally, an index can be constructed that consists of $n+1$ $t$-bit integer entries $L_0$, ..., $L_n$, where $L_i$ is the total length (in octets) of the representations of cells $c_j$ with $j\\leq i$, and integer $t\\geq0$ is chosen so that $L_n\\leq 2^t$.\n5. The serialization of the bag of cells now consists of a magic number indicating the precise format of the serialization, followed by integers $s\\geq 0$, $t\\geq0$, $n\\leq 2^s$, an optional index consisting of $\\lceil(n+1)t/8\\rceil$ octets, and $L_n$ octets with the cell representations.\n6. An optional CRC32 may be appended to the serialization for integrity verification purposes.\n\nIf an index is included, any cell $c_i$ in the serialized bag of cells may be easily accessed by its index $i$ without deserializing all other cells, or even without loading the entire serialized bag of cells in memory.\n\n### 5.3.6. Serialization of one cell from a bag of cells\n\nMore precisely, each individual cell $c=c_i$ is serialized as follows, provided $s$ is a multiple of eight (usually $s=8$, $16$, $24$, or $32$):\n\n1. Two descriptor bytes $d_1$ and $d_2$ are computed similarly to [Standard cell representation](/foundations/whitepapers/tvm#3-1-4-standard-cell-representation) by setting $d_1=r+8s+16h+32l$ and $d_2=\\lfloor b/8\\rfloor+\\lceil b/8\\rceil$, where:\n   - $0\\leq r\\leq 4$ is the number of cell references present in cell $c$; if $c$ is absent from the bag of cells being serialized and is represented by its hashes only, then $r=7$.<a id=\"ref-fn38\"></a><sup>[38](#fn38)</sup>\n   - $0\\leq b\\leq 1023$ is the number of data bits in cell $c$.\n   - $0\\leq l\\leq 3$ is the [level of cell](/foundations/whitepapers/tvm#3-1-3-the-level-of-a-cell) $c$.\n   - $s=1$ for exotic cells and $s=0$ for ordinary cells.\n   - $h=1$ if the cell's hashes are explicitly included into the serialization; otherwise, $h=0$. (When $r=7$, we must always have $h=1$.)\n\nFor absent cells (i.e., external references), only $d_1$ is present, always equal to $23+32l$.\n\n2. Two bytes $d_1$ and $d_2$ (if $r<7$) or one byte $d_1$ (if $r=7$) begin the serialization of cell $c$.\n3. If $h=1$, the serialization is continued by $l+1$ 32-byte [higher hashes](/foundations/whitepapers/tvm#3-1-6-the-higher-hashes-of-a-cell) of $c$: $\\text{Hash}_1(c)$, ..., $\\text{Hash}_{l+1}(c)=\\text{Hash}_\\infty(c)$.\n4. After that, $\\lceil b/8\\rceil$ data bytes are serialized, by splitting $b$ data bits into 8-bit groups and interpreting each group as a big-endian integer in the range $0\\ldots255$. If $b$ is not divisible by $8$, then the data bits are first augmented by one binary $1$ and up to six binary $0$, so as to make the number of data bits divisible by eight.<a id=\"ref-fn39\"></a><sup>[39](#fn39)</sup>\n5. Finally, $r$ cell references to cells $c_{j_1}$, ..., $c_{j_r}$ are encoded by means of $r$ $s$-bit big-endian integers $j_1$, ..., $j_r$.<a id=\"ref-fn40\"></a><sup>[40](#fn40)</sup>\n\n### 5.3.7. A classification of serialization schemes for bags of cells\n\nA serialization scheme for a bag of cells must specify the following parameters:\n\n- The 4-byte magic number prepended to the serialization.\n- The number of bits $s$ used to represent cell indices. Usually $s$ is a multiple of eight (e.g., $8$, $16$, $24$, or $32$).\n- The number of bits $t$ used to represent offsets of [cell serializations](#5-3-5-outline-of-serialization-process). Usually $t$ is also a multiple of eight.\n- A flag indicating whether an index with offsets $L_0$, ..., $L_n$ of cell serializations is present. This flag may be combined with $t$ by setting $t=0$ when the index is absent.\n- A flag indicating whether the CRC32-C of the whole serialization is appended to it for integrity verification purposes.\n\n### 5.3.8. Fields present in the serialization of a bag of cells\n\nIn addition to the [values](#5-3-7-a-classification-of-serialization-schemes-for-bags-of-cells) fixed by the choice of a serialization scheme for bags of cells, the serialization of a specific bag of cells must specify the following parameters:\n\n- The total number of cells $n$ present in the serialization.\n- The number of \"root cells\" $k\\leq n$ present in the serialization. The root cells themselves are $c_0$, ..., $c_{k-1}$. All other cells present in the bag of cells are expected to be reachable by chains of references starting from the root cells.\n- The number of \"absent cells\" $l\\leq n-k$, which represent cells that are actually absent from this bag of cells, but are referred to from it. The absent cells themselves are represented by $c_{n-l}$, ..., $c_{n-1}$, and only these cells may (and also must) have $r=7$. Complete bags of cells have $l=0$.\n- The total length in bytes $L_n$ of the serialization of all cells. If the index is present, $L_n$ might not be stored explicitly since it can be recovered as the last entry of the index.\n\n### 5.3.9. TL-B scheme for serializing bags of cells\n\nSeveral TL-B constructors can be used to serialize bags of cells into octet (i.e., 8-bit byte) sequences. The only one that is currently used to serialize new bags of cell is\n\n```\nserialized_boc#b5ee9c72 has_idx:(## 1) has_crc32c:(## 1) \n  has_cache_bits:(## 1) flags:(## 2) { flags = 0 }\n  size:(## 3) { size <= 4 }\n  off_bytes:(## 8) { off_bytes <= 8 } \n  cells:(##(size * 8)) \n  roots:(##(size * 8)) { roots >= 1 }\n  absent:(##(size * 8)) { roots + absent <= cells }\n  tot_cells_size:(##(off_bytes * 8))\n  root_list:(roots * ##(size * 8))\n  index:has_idx?(cells * ##(off_bytes * 8))\n  cell_data:(tot_cells_size * [ uint8 ])\n  crc32c:has_crc32c?uint32\n  = BagOfCells;\n```\n\nField `cells` is $n$, `roots` is $k$, `absent` is $l$, and `tot_cells_size` is $L_n$ (the total size of the serialization of all cells in bytes). If an index is present, parameters $s/8$ and $t/8$ are serialized separately as `size` and `off_bytes`, respectively, and the flag `has_idx` is set. The index itself is contained in `index`, present only if `has_idx` is set. The field `root_list` contains the (zero-based) indices of the root nodes of the bag of cells.\n\nTwo older constructors are still supported in the bag-of-cells deserialization functions:\n\n```\nserialized_boc_idx#68ff65f3 size:(## 8) { size <= 4 }\n  off_bytes:(## 8) { off_bytes <= 8 } \n  cells:(##(size * 8)) \n  roots:(##(size * 8)) { roots = 1 }\n  absent:(##(size * 8)) { roots + absent <= cells }\n  tot_cells_size:(##(off_bytes * 8))\n  index:(cells * ##(off_bytes * 8))\n  cell_data:(tot_cells_size * [ uint8 ])\n  = BagOfCells;\n\nserialized_boc_idx_crc32c#acc3a728 size:(## 8) { size <= 4 }\n  off_bytes:(## 8) { off_bytes <= 8 } \n  cells:(##(size * 8)) \n  roots:(##(size * 8)) { roots = 1 }\n  absent:(##(size * 8)) { roots + absent <= cells }\n  tot_cells_size:(##(off_bytes * 8))\n  index:(cells * ##(off_bytes * 8))\n  cell_data:(tot_cells_size * [ uint8 ])\n  crc32c:uint32 = BagOfCells;\n```\n\n### 5.3.10. Storing compiled TVM code in files\n\nNotice that the above procedure for serializing bags of cells may be used to serialize compiled smart contracts and other TVM code. One must define a TL-B constructor similar to the following:\n\n```\ncompiled_smart_contract\n  compiled_at:uint32 code:^Cell data:^Cell\n  description:(Maybe ^TinyString)\n  _:^[ source_file:(Maybe ^TinyString)\n       compiler_version:(Maybe ^TinyString) ]\n  = CompiledSmartContract;\n\ntiny_string#_ len:(#<= 126) str:(len * [ uint8 ]) = TinyString; \n```\n\nThen a compiled smart contract may be represented by a value of type *CompiledSmartContract*, transformed into a tree of cells and then into a bag of cells, and then serialized using one of the [constructors](#5-3-9-tl-b-scheme-for-serializing-bags-of-cells). The resulting octet string may be then written into a file with suffix `.tvc` (\"TVM smart contract\"), and this file may be used to distribute the compiled smart contract, download it into a wallet application for deploying into the TON Blockchain, and so on.\n\n### 5.3.11. Merkle hashes for an octet string\n\nOn some occasions, we must define a Merkle hash $\\text{Hash}_M(s)$ of an arbitrary octet string $s$ of length $|s|$. We do this as follows:\n\n- If $|s|\\leq 256$ octets, then the Merkle hash of $s$ is just its SHA-256:\n\n$$\n\\text{Hash}_M(s):=\\text{Sha256}(s)\\quad\\text{if }|s|\\leq 256. \\tag{19}\n$$\n\n- If $|s|>256$, let $n=2^k$ be the largest power of two less than $|s|$ (i.e., $k:=\\lfloor\\log_2(|s|-1)\\rfloor$, $n:=2^k$). If $s'$ is the prefix of $s$ of length $n$, and $s''$ is the suffix of $s$ of length $|s|-n$, so that $s$ is the concatenation $s'.s''$ of $s'$ and $s''$, we define\n\n$$\n\\text{Hash}_M(s):=\\text{Sha256}\\bigl(\\text{Int}_{64}(|s|).\\text{Hash}_M(s').\\text{Hash}_M(s'')\\bigr) \\tag{20}\n$$\n\nIn other words, we concatenate the 64-bit big-endian representation of $|s|$ and the recursively computed Merkle hashes of $s'$ and $s''$, and compute SHA-256 of the resulting string.\n\nOne can check that $\\text{Hash}_M(s)=\\text{Hash}_M(t)$ for octet strings $s$ and $t$ of length less than $2^{64}-2^{56}$ implies $s=t$ unless a hash collision for SHA-256 has been found.\n\n### 5.3.12. The serialization hash of a block\n\nThe construction of [Merkle hashes for an octet string](#5-3-11-merkle-hashes-for-an-octet-string) is applied in particular to the serialization of the bag of cells representing an unsigned shardchain or masterchain block. The validators sign not only the representation hash of the unsigned block, but also the \"serialization hash\" of the unsigned block, defined as $\\text{Hash}_M$ of the serialization of the unsigned block. In this way, the validators certify that this octet string is indeed a serialization of the corresponding block.\n\n---\n\n# A  Elliptic curve cryptography\n\nThis appendix contains a formal description of the elliptic curve cryptography currently used in TON, particularly in the TON Blockchain and the TON Network.\n\nTON uses two forms of elliptic curve cryptography: Ed25519 is used for cryptographic Schnorr signatures, while Curve25519 is used for asymmetric cryptography. These curves are used in the standard way (as defined in the original articles <sup>[[1](#references)]</sup> and <sup>[[2](#references)]</sup> by D. Bernstein and RFCs 7748 and 8032); however, some serialization details specific to TON must be explained. One unique adaptation of these curves for TON is that TON supports automatic conversion of Ed25519 keys into Curve25519 keys, so that the same keys can be used for signatures and for asymmetric cryptography.\n\n## A.1   Elliptic curves\n\nSome general facts on elliptic curves over finite fields, relevant for elliptic curve cryptography, are collected in this section.\n\n### A.1.1. Finite fields\n\nWe consider elliptic curves over finite fields. For the purposes of the Curve25519 and Ed25519 algorithms, we will be mostly concerned with elliptic curves over the finite prime field $k:=\\mathbb{F}_p$ of residues modulo $p$, where $p=2^{255}-19$ is a prime number, and over finite extensions $\\mathbb{F}_q$ of $\\mathbb{F}_p$, especially the quadratic extension $\\mathbb{F}_{p^2}$.<sup>[41](#fn41)</sup>\n\n### A.1.2. Elliptic curves\n\nAn _elliptic curve_ $E=(E,O)$ over a field $k$ is a geometrically integral smooth projective curve $E/k$ of genus $g=1$, along with a marked $k$-rational point $O\\in E(k)$. It is well-known that an elliptic curve $E$ over a field $k$ can be represented in (generalized) Weierstrass form:\n\n$$\ny^2+a_1xy+a_3y=x^3+a_2x^2+a_4x+a_6\\quad\\text{for some }a_1, \\ldots, a_6\\in k. \\quad (21)\n$$\n\nMore precisely, this is only the affine part of the elliptic curve, written in coordinates $(x,y)$. For any field extension $K$ of $k$, $E(K)$ consists of all solutions $(x,y)\\in K^2$ of equation ([21](#a-1-2-elliptic-curves)), called finite points of $E(K)$, along with a point at infinity, which is the marked point $O$.\n\n### A.1.3. Weierstrass form in homogeneous coordinates\n\nIn homogeneous coordinates $[X:Y:Z]$, ([21](#a-1-2-elliptic-curves)) corresponds to\n\n$$\nY^2Z+a_1XYZ+a_3YZ^2=X^3+a_2X^2Z+a_4XZ^2+a_6Z^3 \\quad (22)\n$$\n\nWhen $Z\\neq0$, we can set $x:=X/Z$, $y:=Y/Z$, and obtain a solution $(x,y)$ of ([21](#a-1-2-elliptic-curves)) (i.e., a finite point of $E$). On the other hand, the only solution (up to proportionality) of ([22](#a-1-3-weierstrass-form-in-homogeneous-coordinates)) with $Z=0$ is $[0:1:0]$; this is the point at infinity $O$.\n\n### A.1.4. Standard Weierstrass form\n\nWhen the characteristic $\\text{char }k$ of field $k$ is $\\neq2$, $3$, the Weierstrass form of ([21](#a-1-2-elliptic-curves)) or ([22](#a-1-3-weierstrass-form-in-homogeneous-coordinates)) can be simplified with the aid of linear transformations $y':=y+a_1x/2+a_3/2$, $x':=x+a_2/3$, thus making $a_1=a_3=a_2=0$ and obtaining\n\n$$\ny^2=x^3+a_4x+a_6 \\quad (23)\n$$\n\nand\n\n$$\nY^2Z=X^3+a_4XZ^2+a_6Z^3 \\quad (24)\n$$\n\nSuch an equation defines an elliptic curve if and only if the cubic polynomial $P(x):=x^3+a_4x+a_6$ has no multiple roots, i.e., if the discriminant $D:=-4a_4^3-27a_6^2$ is non-zero.\n\n### A.1.5. Addition of points on elliptic curve $E$\n\nLet $K$ be a field extension of field $k$, and let $E=(E,O)$ be any elliptic curve in Weierstrass form defined over $k$. Then any line $l\\subset\\mathbb{P}^2_K$ intersects the elliptic curve $E_{(K)}$ (which is the base change of curve $E$ to field $K$, i.e., the curve defined by the same equations over a larger field $K$) at exactly three points $P$, $Q$, $R$, considered with multiplicities. We define the *addition of points* on elliptic curve $E$ (or rather the addition of its $K$-valued points $E(K)$) by requiring that\n\n$$\nP+Q+R=O\\quad\\text{whenever }\\{P,Q,R\\}=l\\cap E\\text{ for some line }l\\subset\\mathbb{P}^2_K. \\quad (25)\n$$\n\nIt is well-known that this requirement defines a unique commutative law $[+]:E\\times_k E\\to E$ on the points of the elliptic curve $E$, having $O$ as its neutral element. When elliptic curve $E$ is represented by its Weierstrass form ([21](#a-1-2-elliptic-curves)), one can write explicit formulas expressing the coordinates $x_{P+Q}$, $y_{P+Q}$ of the sum $P+Q$ of two $K$-valued points $P$, $Q\\in E(K)$ of elliptic curve $E$ as rational functions of the coordinates $x_P$, $y_P$, $x_Q$, $y_Q\\in K$ of points $P$ and $Q$ and of the coefficients $a_i\\in k$ of ([21](#a-1-2-elliptic-curves)).\n\n### A.1.6. Power maps\n\nSince $E(K)$ is an abelian group, one can define *multiples or powers* $[n]X$ for any point $X\\in E(K)$ and any integer $n\\in\\mathbb{Z}$. If $n=0$, then $[0]X=O$; if $n>0$, then $[n]X=[n-1]X+X$; if $n<0$, then $[n]X=-[-n]X$. The map $[n]=[n]_E:E\\to E$ for $n\\neq0$ is an *isogeny*, meaning that it is a non-constant homomorphism for the group law of $E$:\n\n$$\n[n](P+Q)=[n]P+[n]Q\\quad\\text{for any }P, Q\\in E(K)\\text{ and }n\\in\\mathbb{Z}. \\quad (26)\n$$\n\nIn particular, $[-1]_E:E\\to E$, $P\\mapsto -P$, is an involutive automorphism of elliptic curve $E$. If $E$ is in Weierstrass form, $[-1]_E$ maps $(x,y)\\mapsto(x,-y)$, and two points $P$, $Q\\in E(\\mathbb{F}_q)$ have equal $x$-coordinates if and only if $Q=\\pm P$.\n\n### A.1.7. The order of the group of rational points of E\n\nLet $E$ be an elliptic curve defined over a finite base field $k$, and let $K=\\mathbb{F}_q$ be a finite extension of $k$. Then $E(\\mathbb{F}_q)$ is a finite abelian group. By a well-known result of Hasse, the order $n$ of this group is not too distant from $q$:\n\n$$\nn=|E(\\mathbb{F}_q)|=q-t+1\\quad\\text{where }t^2\\leq 4q\\text{, i.e., }|t|\\leq2\\sqrt{q}. \\quad (27)\n$$\n\nWe will be mostly interested in the case $K=k=\\mathbb{F}_p$, with $q=p$ a prime number.\n\n### A.1.8. Cyclic subgroups of large prime order\n\nElliptic curve cryptography is usually performed using elliptic curves that admit a (necessarily cyclic) subgroup $C\\subset E(\\mathbb{F}_q)$ of prime order $\\ell$. Equivalently, a rational point $G\\in E(\\mathbb{F}_q)$ of prime order $\\ell$ may be given; then $C$ can be recovered as the cyclic subgroup $\\langle G\\rangle$ generated by $G$. In order to verify that a point $G\\in E(\\mathbb{F}_q)$ generates a cyclic group of prime order $\\ell$, one can check that $G\\neq O$, but $[\\ell]G=O$.\n\nBy the Legendre theorem, $\\ell$ is necessarily a divisor of the order $n=|E(\\mathbb{F}_q)|$ of the finite abelian group $E(\\mathbb{F}_q)$:\n\n$$\nn=|E(\\mathbb{F}_q)|=c\\ell\\quad\\text{for some integer }c\\geq1 \\quad (28)\n$$\n\nThe integer $c$ is called the *cofactor*; one usually wants the cofactor to be as small as possible, so as to make $\\ell=n/c$ as large as possible. Recall that $n$ always has the same order of magnitude as $q$ by ([27](#a-1-7-the-order-of-the-group-of-rational-points-of-e)), so it cannot be changed much by varying $E$ once $q$ is fixed.\n\n### A.1.9. Data for elliptic curve cryptography\n\nIn order to define specific elliptic curve cryptography, one must fix a finite base field $\\mathbb{F}_q$ (if $q=p$ is a prime, it is sufficient to fix prime $p$), an elliptic curve $E/\\mathbb{F}_q$ (usually represented by the coefficients of its Weierstrass form ([23](#a-1-4-standard-weierstrass-form)) or ([21](#a-1-2-elliptic-curves))), the base point $O$ (which usually is the point at infinity of an elliptic curve written in Weierstrass form), and the generator $G\\in E(\\mathbb{F}_q)$ (usually determined by its coordinates $(x,y)$ with respect to the equation of the elliptic curve) of a cyclic subgroup of large prime order $\\ell$. Prime number $\\ell$ and the cofactor $c$ are usually also part of the elliptic cryptography data.\n\n### A.1.10. Main operations of elliptic curve cryptography\n\nElliptic curve cryptography usually deals with a fixed cyclic subgroup $C$ of a large prime order $\\ell$ inside the group of points of an elliptic curve $E$ over a finite field $\\mathbb{F}_q$. A generator $G$ of $C$ is usually fixed. It is usually assumed that, given a point $X$ of $C$, one cannot find its \"discrete logarithm base $G$\" (i.e., a residue $n$ modulo $\\ell$ such that $X=[n]G$) faster than in $O(\\sqrt\\ell)$ operations. The most important operations used in elliptic curve cryptography are the addition of points from $C\\subset E(\\mathbb{F}_q)$ and the computation of their powers, or multiples.\n\n### A.1.11. Private and public keys for elliptic curve cryptography\n\nUsually a private key for [elliptic curve cryptography](#a-1-9-data-for-elliptic-curve-cryptography) data is a \"random\" integer $0<a<\\ell$, called the *secret exponent*, and the corresponding public key is the point $A:=[a]G$ (or just its $x$-coordinate $x_A$), suitably serialized.\n\n### A.1.12. Montgomery curves\n\nElliptic curves with the specific Weierstrass equation\n\n$$\ny^2=x^3+Ax^2+x\\quad\\text{where }A=4a-2\\text{ for some }a\\in k, a\\neq0, a\\neq1 \\quad (29)\n$$\n\nare called *Montgomery curves*. They have the convenient property that $x_{P+Q}x_{P-Q}$ can be expressed as a simple rational function of $x_P$ and $x_Q$:\n\n$$\nx_{P+Q}x_{P-Q}=\\left(\\frac{x_Px_Q-A}{x_P-x_Q}\\right)^2 \\quad (30)\n$$\n\nThis means that $x_{P+Q}$ can be computed provided $x_{P-Q}$, $x_P$, and $x_Q$ are known. In particular, if $x_P$, $x_{[n]P}$, and $x_{[n+1]P}$ are known, then $x_{[2n]P}$, $x_{[2n+1]P}$, and $x_{[2n+2]P}$ can be computed. Using the binary representation of $0<n<2^s$, one can compute $x_{[\\lfloor n/2^{s-i}\\rfloor]P}$, $x_{[\\lfloor n/2^{s-i}\\rfloor+1]P}$ for $i=0$, $1$, ..., $s$, thus obtaining $x_{[n]P}$ (this algorithm for quickly computing $x_{[n]P}$ starting from $x_P$ on Montgomery curves is called a *Montgomery ladder*). Hence we see the importance of Montgomery curves for elliptic curve cryptography.\n\n---\n\n## A.2  Curve25519 cryptography\n\nThis section describes the well-known Curve25519 cryptography proposed by Daniel Bernstein <sup>[[1]](#references)]</sup> and its usage in TON.\n\n### A.2.1. Curve25519\n\n*Curve25519* is defined as the Montgomery curve\n\n$$\ny^2=x^3+Ax^2+x\\quad\\text{over }\\mathbb{F}_p\\text{, where }p=2^{255}-19\\text{ and }A=486662. \\quad (31)\n$$\n\nThe order of this curve is $8\\ell$, where $\\ell$ is a prime number, and $c=8$ is the cofactor. The cyclic subgroup of order $\\ell$ is generated by a point $G$ with $x_G=9$ (this determines $G$ up to the sign of $y_G$, which is unimportant). The order of the quadratic twist $2y^2=x^3+Ax^2+x$ of Curve25519 is $4\\ell'$ for another prime number $\\ell'$.<sup>[42](#fn42)</sup>\n\n### A.2.2. Parameters of Curve25519\n\nThe parameters of Curve25519 are as follows:\n\n- Base field: Prime finite field $\\mathbb{F}_p$ for $p=2^{255}-19$.\n- Equation: $y^2=x^3+Ax^2+x$ for $A=486662$.\n- Base point $G$: Characterized by $x_G=9$ (nine is the smallest positive integer $x$-coordinate of a generator of the subgroup of large prime order of $E(\\mathbb{F}_p)$).\n- Order of $E(\\mathbb{F}_p)$:\n\n$$\n|E(\\mathbb{F}_p)|=p-t+1=8\\ell,\\quad\\text{where} \\quad (32)\n$$\n\n$$\n\\ell=2^{252}+27742317777372353535851937790883648493\\quad\\text{is prime.} \\quad (33)\n$$\n\n- Order of $\\tilde E(\\mathbb{F}_p)$, where $\\tilde E$ is the quadratic twist of $E$:\n\n$$\n|\\tilde E(\\mathbb{F}_p)|=p+t+1=2p+2-8\\ell=4\\ell',\\quad\\text{where} \\quad (34)\n$$\n\n$$\n\\ell'=2^{253}-55484635554744707071703875581767296995\\quad\\text{is prime.} \\quad (35)\n$$\n\n### A.2.3. Private and public keys for standard Curve25519 cryptography\n\nA private key for Curve25519 cryptography is usually defined as a *secret exponent* $a$, while the corresponding public key is $x_A$, the $x$-coordinate of point $A:=[a]G$. This is usually sufficient for performing ECDH (elliptic curve Diffie--Hellman key exchange) and asymmetric elliptic curve cryptography, as follows:\n\nIf a party wants to send a message $M$ to another party, which has public key $x_A$ (and private key $a$), the following computations are performed. A one-time random secret exponent $b$ is generated, and $x_B:=x_{[b]G}$ and $x_{[b]A}$ are computed using a Montgomery ladder. After that, the message $M$ is encrypted by a symmetric cypher such as AES using the 256-bit \"shared secret\" $S:=x_{[b]A}$ as a key, and 256-bit integer (\"one-time public key\") $x_B$ is prepended to the encrypted message. Once the party with public key $x_A$ receives this message, it can compute $x_{[a]B}$ starting from $x_B$ (transmitted with the encrypted message) and the private key $a$. Since $x_{[a]B}=x_{[ab]G}=x_{[b]A}=S$, the receiving party recovers the shared secret $S$ and is able to decrypt the remainder of the message.\n\n### A.2.4. Public and private keys for TON Curve25519 cryptography\n\nTON uses another form for public and private keys of Curve25519 cryptography, borrowed from Ed25519 cryptography.\n\nA private key for TON Curve25519 cryptography is just a random 256-bit string $k$. It is used by computing $\\text{Sha512}(k)$, taking the first 256 bits of the result, interpreting them as a little-endian 256-bit integer $a$, clearing bits $0$, $1$, $2$, and $255$ of $a$, and setting bit $254$ so as to obtain a value $2^{254}\\leq a<2^{255}$, divisible by eight. The value $a$ thus obtained is the *secret exponent* corresponding to $k$; meanwhile, the remaining 256 bits of $\\text{Sha512}(k)$ constitute the *secret salt* $k''$.\n\nThe public key corresponding to $k$—or to the secret exponent $a$—is just the $x$-coordinate $x_A$ of the point $A:=[a]G$. Once $a$ and $x_A$ are computed, they are used in exactly the [same way](#a-2-3-private-and-public-keys-for-standard-curve25519-cryptography). In particular, if $x_A$ needs to be serialized, it is serialized into 32 octets as an unsigned little-endian 256-bit integer.\n\n### A.2.5. Curve25519 is used in the TON Network\n\nNotice that the asymmetric [Curve25519 cryptography](#a-2-4-public-and-private-keys-for-ton-curve25519-cryptography) is extensively used by the TON Network, especially the ADNL (Abstract Datagram Network Layer) protocol. However, TON Blockchain needs elliptic curve cryptography mostly for signatures. For this purpose, Ed25519 signatures described in the next section are used.\n\n---\n\n## A.3  Ed25519 cryptography\n\nEd25519 cryptography is extensively used for fast cryptographic signatures by both the TON Blockchain and the TON Network. This section describes the variant of Ed25519 cryptography used by TON. An important difference from the standard approaches (as defined by D. Bernstein et al. in <sup>[[2]](#references)</sup>) is that TON provides automatic conversion of private and public Ed25519 keys into Curve25519 keys, so that the same keys could be used both for encrypting/decrypting and for signing messages.\n\n### A.3.1. Twisted Edwards curves\n\nA *twisted Edwards curve* $E_{a,d}$ with parameters $a\\neq 0$ and $d\\neq0,a$ over a field $k$ is given by equation\n\n$$\nE_{a,d}:\\, ax^2+y^2=1+dx^2y^2\\quad\\text{over }k \\quad (36)\n$$\n\nIf $a=1$, this equation defines an (untwisted) Edwards curve. Point $O(0,1)$ is usually chosen as the marked point of $E_{a,d}$.\n\n### A.3.2. Twisted Edwards curves are birationally equivalent to Montgomery curves\n\nA twisted Edwards curve $E_{a,d}$ is birationally equivalent to a Montgomery elliptic curve\n\n$$\nM_A:\\, v^2=u^3+Au^2+u \\quad (37)\n$$\n\nwhere $A=2(a+d)/(a-d)$ and $d/a=(A-2)/(A+2)$. The birational equivalence $\\phi:E_{a,d}\\dashrightarrow M_A$ and its inverse $\\phi^{-1}$ are given by\n\n$$\n\\phi:(x,y)\\mapsto\\Biggl(\\frac{1+y}{1-y},\\frac{c(1+y)}{x(1-y)}\\Biggr) \\quad (38)\n$$\n\nand\n\n$$\n\\phi^{-1}:(u,v)\\mapsto\\Biggl(\\frac{cu}{v},\\frac{u-1}{u+1}\\Biggr) \\quad (39)\n$$\n\nwhere\n\n$$\nc=\\sqrt{\\frac{A+2}{a}} \\quad (40)\n$$\n\nNotice that $\\phi$ transforms the marked point $O(0,1)$ of $E_{a,d}$ into the marked point of $M_A$ (i.e., its point at infinity).\n\n### A.3.3. Addition of points on a twisted Edwards curve\n\nSince $E_{a,d}$ is birationally equivalent to an elliptic curve $M_A$, the addition of points on $M_A$ can be transferred to $E_{a,d}$ by setting\n\n$$\nP+Q:=\\phi^{-1}\\bigl(\\phi(P)+\\phi(Q)\\bigr)\\quad\\text{for any }P, Q\\in E_{a,d}(k). \\quad (41)\n$$\n\nNotice that the marked point $O(0,1)$ is the neutral element with respect to this addition, and that $-(x_P,y_P)=(-x_P,y_P)$.\n\n### A.3.4. Formulas for adding points on a twisted Edwards curve\n\nThe coordinates $x_{P+Q}$ and $y_{P+Q}$ admit simple expressions as rational functions of $x_P$, $y_P$, $x_Q$, $y_Q$:\n\n$$\nx_{P+Q}=\\frac{x_Py_Q+x_Qy_P}{1+dx_Px_Qy_Py_Q} \\quad (42)\n$$\n\n$$\ny_{P+Q}=\\frac{y_Py_Q-ax_Px_Q}{1-dx_Px_Qy_Py_Q} \\quad (43)\n$$\n\nThese expressions can be efficiently computed, especially if $a=-1$. This is the reason twisted Edwards curves are important for fast elliptic curve cryptography.\n\n### A.3.5. Ed25519 twisted Edwards curve\n\nEd25519 is the twisted Edwards curve $E_{-1,d}$ over $\\mathbb{F}_p$, where $p=2^{255}-19$ is the same prime number as that used for Curve25519, and $d=-(A-2)/(A+2)=-121665/121666$, where $A=486662$ is the same as in the equation ([31](#a-2-1-curve25519)):\n\n$$\n-x^2+y^2=1-\\frac{121665}{121666}x^2y^2\\quad\\text{for }x, y\\in\\mathbb{F}_p, p=2^{255}-19. \\quad (44)\n$$\n\nIn this way, Ed25519-curve $E_{-1,d}$ is birationally equivalent to Curve25519 ([31](#a-2-1-curve25519)), and one can use $E_{-1,d}$ and formulas ([42](#a-3-4-formulas-for-adding-points-on-a-twisted-edwards-curve))–([43](#a-3-4-formulas-for-adding-points-on-a-twisted-edwards-curve)) for point addition on either Ed25519 or Curve25519, using ([38](#a-3-2-twisted-edwards-curves-are-birationally-equivalent-to-montgomery-curves)) and ([39](#a-3-2-twisted-edwards-curves-are-birationally-equivalent-to-montgomery-curves)) to convert points on Ed25519 into corresponding points on Curve25519, and vice versa.\n\n### A.3.6. Generator of Ed25519\n\nThe generator of Ed25519 is the point $G'$ with $y(G')=4/5$ and $0\\leq x(G')<p$ even. According to ([38](#a-3-2-twisted-edwards-curves-are-birationally-equivalent-to-montgomery-curves)), it corresponds to the point $(u,v)$ of Curve25519 with $u=(1+4/5)/(1-4/5)=9$ (i.e., to the generator $G$ of [Curve25519](#a-2-2-parameters-of-curve25519)). In particular, $G=\\phi(G')$, $G'$ generates a cyclic subgroup of the same large prime order $\\ell$ given in ([32](#a-2-2-parameters-of-curve25519)), and for any integer $a$,\n\n$$\n\\phi([a]G')=[a]G \\quad . \\quad (45)\n$$\n\nIn this way, we can perform computations with Curve25519 and its generator $G$, or with Ed25519 and generator $G'$, and obtain essentially the same results.\n\n### A.3.7. Standard representation of points on Ed25519\n\nA point $P(x,y)$ on Ed25519 may be represented by its two coordinates $x_P$ and $y_P$, residues modulo $p=2^{255}-19$. In their turn, both these coordinates may be represented by unsigned 255- or 256-bit integers $0\\leq x_P,y_P<p<2^{255}$.\n\nHowever, a more compact representation of $P$ by one little-endian unsigned 256-bit integer $\\tilde P$ is commonly used (and is used by TON as well). Namely, the 255 lower-order bits of $\\tilde P$ contain $y_P$, $0\\leq y_P<p<2^{255}$, and bit 255 is used to store $x_P\\bmod 2$, the lower-order bit of $x_P$. Since $y_P$ always determines $x_P$ up to sign (i.e., up to replacing $x_P$ with $p-x_P$), $x_P$ and $p-x_P$ can always be distinguished by their lower-order bit, $p$ being odd.\n\nIf it is sufficient to know $\\pm P$ up to sign, one can ignore $x_P\\bmod 2$ and consider only the little-endian 255-bit integer $y_P$, setting the bit 255 arbitrarily, ignoring its previously defined value, or clearing it.\n\n### A.3.8. Private key for Ed25519\n\nA *private key* for Ed25519 is just an arbitrary 256-bit string $k$. A *secret exponent* $a$ and *secret salt* $k''$ are derived from $k$ by first computing $\\texttt{Sha512}(k)$, and then taking the first 256 bits of this $\\texttt{Sha512}$ as the little-endian representation of $a$ (but with bits 255, 2, 1, and 0 cleared, and bit 254 set); the last 256 bits of $\\texttt{Sha512}(k)$ then constitute $k''$.\n\nThis is essentially the [same procedure](#a-2-4-public-and-private-keys-for-ton-curve25519-cryptography) but with Curve25519 replaced by the birationally equivalent curve Ed25519. (In fact, it is the other way around: this procedure is standard for Ed25519-based elliptic curve cryptography, and TON extends the procedure to Curve25519.)\n\n### A.3.9. Public key for Ed25519\n\nA *public key* corresponding to a private key $k$ for Ed25519 is the [standard representation](#a-3-7-standard-representation-of-points-on-ed25519) of the point $A=[a]G'$, where $a$ is the [secret exponent](#a-3-8-private-key-for-ed25519) defined by the private key $k$.\n\nNotice that $\\phi(A)$ is the public key for Curve25519 defined by the same [private key](#a-2-4-public-and-private-keys-for-ton-curve25519-cryptography) $k$ and ([45](#a-3-6-generator-of-ed25519)). In this way, we can convert public keys for Ed25519 into corresponding public keys for Curve25519, and vice versa. Private keys do not need to be transformed at all.\n\n### A.3.10. Cryptographic Ed25519-signatures\n\nIf a message (octet string) $M$ needs to be signed by a private key $k$ defining secret exponent $a$ and secret salt $k''$, the following computations are performed:\n\n- $r:=\\texttt{Sha512}(k''|M)$, interpreted as a little-endian 512-bit integer. Here $s|t$ denotes the concatenation of octet strings $s$ and $t$.\n- $R:=[r]G'$ is a point on Ed25519.\n- $\\tilde R$ is the [standard representation](#a-3-7-standard-representation-of-points-on-ed25519) of point $R$ as a 32-octet string.\n- $s:=r+a\\cdot\\texttt{Sha512}(\\tilde R|\\tilde A|M)\\bmod\\ell$, encoded as a little-endian 256-bit integer. Here $\\tilde A$ is the standard representation of point $A=[a]G'$, the public key corresponding to $k$.\n\nThe (Schnorr) signature is a 64-octet string $(\\tilde R,s)$, consisting of the standard representation of the point $R$ and of the 256-bit integer $s$.\n\n### A.3.11. Checking Ed25519-signatures\n\nIn order to verify signature $(\\tilde R,s)$ of a message $M$, supposedly made by the owner of the private key $k$ corresponding to a known public key $A$, the following steps are performed:\n\n- Points $[s]G'$ and $R+[\\texttt{Sha512}(\\tilde R|\\tilde A|M)]A$ of Ed25519 are computed.\n- If these two points coincide, the signature is correct.\n\n\n## References\n\n[1] Daniel J. Bernstein, *Curve25519: New Diffie--Hellman Speed Records*...\n\n[2] Daniel J. Bernstein, Niels Duif, Tanja Lange et al., *High-speed high-security signatures*...\n\n[3] N. Durov, *Telegram Open Network*, 2017.\n\n[4] N. Durov, *Telegram Open Network Virtual Machine*, 2018.\n\n\n## Footnotes\n\n<span id=\"fn1\">**1**</span> As of August 2018, this document does not include a detailed description of serialized invalidity proofs, because they are likely to change significantly during the development of the validator software. Only the general design principles for consistency conditions and serialized invalidity proofs are discussed. [Back ↑](#ref-fn1)\n\n<span id=\"fn2\">**2**</span> This is not included in the present version of this document, but will be provided in a separate appendix to a future revision. [Back ↑](#ref-fn2)\n\n<span id=\"fn3\">**3**</span> Completely identical cells are often identified in memory and in disk storage; this is the reason why trees of cells are transparently transformed into DAGs of cells. From this perspective, a DAG is just a storage optimization of the underlying tree of cells, irrelevant for most considerations. [Back ↑](#ref-fn3)\n\n<span id=\"fn4\">**4**</span> [[4](#ref-4), 3.3.3–4], where an example is given and explained, pending a more complete reference. [Back ↑](#ref-fn4)\n\n<span id=\"fn5\">**5**</span> If there are no transactions related to an account, the corresponding virtual block is empty and is omitted in the shardchain block. [Back ↑](#ref-fn5)\n\n<span id=\"fn6\">**6**</span> Recall that TON Blockchain supports *dynamic* sharding, so the shard configuration may change from block to block because of shard merge and split events. Therefore, we cannot simply say that each shardchain corresponds to a fixed set of accountchains. [Back ↑](#ref-fn6)\n\n<span id=\"fn7\">**7**</span> This condition applies if there is exactly one immediate antecessor (i.e., if a shardchain merge event did not occur immediately before the block in question); otherwise, this condition becomes more convoluted. [Back ↑](#ref-fn7)\n\n<span id=\"fn8\">**8**</span> This example is a bit simplified since it does not take into account the presence of transit messages in InMsgDescr, which are not processed by any explicit transaction. [Back ↑](#ref-fn8)\n\n<span id=\"fn9\">**9**</span> It is interesting to note that this part of the work can be done almost automatically. [Back ↑](#ref-fn9)\n\n<span id=\"fn10\">**10**</span> In order to express this condition correctly in the presence of dynamic sharding, one should fix some account $\\xi$, and consider the latest blocks $S$ and $S'$ of the shardchains containing $\\xi$ in the shard configurations of both $B$ and $B'$, since the shards containing $\\xi$ might be different in $B$ and $B'$. [Back ↑](#ref-fn10)\n\n<span id=\"fn11\">**11**</span> Value-bearing messages with the `bounce` flag set will not be accepted by an uninitialized account, but will be \"bounced\" back. [Back ↑](#ref-fn11)\n\n<span id=\"fn12\">**12**</span> \"Messages to nowhere\" may have some special fields in their body indicating their destination outside the TON Blockchain—for instance, an account in some other blockchain, or an IP address and port—which may be interpreted by the third-party software appropriately. Such fields are ignored by the TON Blockchain. [Back ↑](#ref-fn12)\n\n<span id=\"fn13\">**13**</span> The problem of bypassing possible validator censorship—which could happen, for instance, if all validators conspire not to include external messages sent to accounts belonging to some set of blacklisted accounts—is dealt with separately elsewhere. The main idea is that the validators may be forced to promise to include a message with a known hash in a future block, without knowing anything about the identity of the sender or the receiver; they will have to keep this promise afterwards when the message itself with pre-agreed hash is presented. [Back ↑](#ref-fn13)\n\n<span id=\"fn14\">**14**</span> However, the internal routing process described in [Internal routing](#2-1-11-internal-routing) is applied immediately after that, which may further modify the transit address. [Back ↑](#ref-fn14)\n\n<span id=\"fn15\">**15**</span> When the addresses involved are of different lengths (e.g., because they belong to different workchains), one should consider only the first 96 bits of the addresses in the above formula. [Back ↑](#ref-fn15)\n\n<span id=\"fn16\">**16**</span> Instead of Hamming optimality, we might have considered the equivalent property of Kademlia optimality, written for the Kademlia (or weighted $L_1$) distance as given by $\\|\\xi-\\eta\\|_K:=\\sum_i2^{-i}|\\xi_i-\\eta_i|$ instead of the Hamming distance. [Back ↑](#ref-fn16)\n\n<span id=\"fn17\">**17**</span> Notice that the next-hop and internal-routing computations are still applied to such messages, since the current shardchain may be split before the message is processed. In this case, the new sub-shardchain containing the destination address will inherit the message. [Back ↑](#ref-fn17)\n\n<span id=\"fn18\">**18**</span> We may define the (virtual) output queue of an account(chain) as the subset of the OutMsgQueue of the shard currently containing that account that consists of messages with transit addresses equal to the address of the account. [Back ↑](#ref-fn18)\n\n<span id=\"fn19\">**19**</span> In particular, if the hash of a recent block of a neighboring shardchain is not yet reflected in the latest masterchain block, its modifications to OutMsgQueue must not be taken into account. [Back ↑](#ref-fn19)\n\n<span id=\"fn20\">**20**</span> This statement is not as trivial as it seems at first, because some of the shardchains involved may split or merge during the routing. A correct proof may be obtained by adopting the ISP perspective to HR as explained in [Hypercube Routing and the ISP](#2-1-14-hypercube-routing-and-the-isp) and observing that $m'$ will always be behind $m$, either in terms of the intermediate accountchain reached or, if they happen to be in the same accountchain, in terms of logical creation time. [Back ↑](#ref-fn20)\n\n<span id=\"fn21\">**21**</span> One must not only look up the key $\\text{Hash}(m)$ in the InMsgDescr of these blocks, but also check the intermediate addresses in the envelope of the corresponding entry, if found. [Back ↑](#ref-fn21)\n\n<span id=\"fn22\">**22**</span> A description of an older version of TL may be found at https://core.telegram.org/mtproto/TL. Alternatively, an informal introduction to TL-B schemes may be found in <sup>[[4]](#references)</sup>. [Back ↑](#ref-fn22)\n\n<span id=\"fn23\">**23**</span> Address rewriting is a feature used to implement \"anycast addresses\" employed by the so-called large or global smart contracts (see <sup>[[3]](#references)</sup>), which can have instances in several shardchains. When address rewriting is enabled, a message may be routed to and processed by a smart contract with an address coinciding with the destination address up to the first $d$ bits, where $d\\leq 32$ is the \"splitting depth\" of the smart contract indicated in the `anycast.depth` field ([Support for anycast addresses](#2-1-6-support-for-anycast-addresses)). Otherwise, the addresses must match exactly. [Back ↑](#ref-fn23)\n\n<span id=\"fn24\">**24**</span> More precisely, the information from the `init` field of an inbound message is used either when the receiving account is uninitialized or frozen with the hash of StateInit equal to the one expected by the account, or when the receiving account is active, and its code or data is an external hash reference matching the hash of the code or data received in the StateInit of the message. [Back ↑](#ref-fn24)\n\n<span id=\"fn25\">**25**</span> Strictly speaking, InMsgDescr is the type of this structure; we deliberately use the same notation to describe the only instance of this type in a block. [Back ↑](#ref-fn25)\n\n<span id=\"fn26\">**26**</span> Recall that a shardchain is considered a neighbor of itself. [Back ↑](#ref-fn26)\n\n<span id=\"fn27\">**27**</span> This situation is rare and occurs only after shardchain merge events. Normally the messages imported from the OutMsgQueue of the same shardchain have destinations inside this shardchain, and are processed accordingly instead of being re-queued. [Back ↑](#ref-fn27)\n\n<span id=\"fn28\">**28**</span> For simplicity, we sometimes treat the masterchain as just another workchain with $\\mathit{workchain\\_id}=-1$. [Back ↑](#ref-fn28)\n\n<span id=\"fn29\">**29**</span> In fact, up to the first $d$ bits are replaced in such a way that each shard contains at most one instance of the large smart contract, and that shards $(w,s)$ with prefix $s$ of length $|s|\\leq d$ contain exactly one instance. [Back ↑](#ref-fn29)\n\n<span id=\"fn30\">**30**</span> This scheme uses anonymous constructors and anonymous fields, both represented by an underscore `_`. [Back ↑](#ref-fn30)\n\n<span id=\"fn31\">**31**</span> In particular, if a user mistakenly sends some funds to a non-existent address in a bounceable message, the funds will not be wasted, but rather will be returned (bounced) back. Therefore, a user wallet application should set the bounce flag in all generated messages by default unless explicitly instructed otherwise. However, non-bounceable messages are indispensable in some situations ([Using non-bounceable messages](#1-7-6-using-non-bounceable-messages)). [Back ↑](#ref-fn31)\n\n<span id=\"fn32\">**32**</span> A reference implementation of a TVM emulator running in a stripped-down version of TVM may be committed into the masterchain to be used when a disagreement between the validators on a specific run of TVM arises. In this way, flawed implementations of TVM may be detected. The reference implementation then serves as an authoritative source on the operational semantics of TVM. (<sup>[[2]](#references)</sup> B.2) [Back ↑](#ref-fn32)\n\n<span id=\"fn33\">**33**</span> Notice that this record does not represent a change in the state of the account, because the transaction may still be aborted during the action phase. In that case, the new persistent data indirectly referenced by vm_final_state_hash will be discarded. [Back ↑](#ref-fn33)\n\n<span id=\"fn34\">**34**</span> The most common way of creating shared libraries for TVM is to publish a reference to the root cell of the library in the masterchain. [Back ↑](#ref-fn34)\n\n<span id=\"fn35\">**35**</span> The persistent data of the smart contract need not be loaded in its entirety for this to occur. Instead the root is loaded, and TVM may load other cells by their references from the root only when they are accessed, thus providing a form of virtual memory. [Back ↑](#ref-fn35)\n\n<span id=\"fn36\">**36**</span> Both the global gas limit and the gas price are configurable parameters determined by the current state of the masterchain. [Back ↑](#ref-fn36)\n\n<span id=\"fn37\">**37**</span> In principle, an experimental version of TON Blockchain might choose to keep only the hashes of the initial and final states of the shardchain. The Merkle update increases the block size, but it is handy for full nodes that want to keep and update their copy of the shardchain state. Otherwise, the full nodes would have to repeat all the computations contained in a block to compute the updated state of the shardchain by themselves. [Back ↑](#ref-fn37)\n\n<span id=\"fn38\">**38**</span> Notice that these \"absent cells\" are different from the library reference and external reference cells, which are kinds of exotic cells (<sup>[[4]](#references)</sup>, 3.1.7). Absent cells, by contrast, are introduced only for the purpose of serializing incomplete bags of cells, and can never be processed by TVM. [Back ↑](#ref-fn38)\n\n<span id=\"fn39\">**39**</span> Notice that exotic cells (with $s=1$) always have $b\\geq8$, with the cell type encoded in the first eight data bits (<sup>[[4]](#references)</sup>, 3.1.7). [Back ↑](#ref-fn39)\n\n<span id=\"fn40\">**40**</span> If the bag of cells is not complete, some of these cell references may refer to cells $c'$ absent from the bag of cells. In that case, special \"absent cells\" with $r=7$ are included into the bag of cells and are assigned some indices $j$. These indices are then used to represent references to absent cells. [Back ↑](#ref-fn40)\n\n<span id=\"fn41\">**41**</span> Arithmetic modulo $p$ for a modulus $p$ near a power of two can be implemented very efficiently. On the other hand, residues modulo $2^{255}-19$ can be represented by 255-bit integers. This is the reason this particular value of $p$ has been chosen by D. Bernstein. [Back ↑](#ref-fn41)\n\n<span id=\"fn42\">**42**</span> Actually, D. Bernstein chose $A=486662$ because it is the smallest positive integer $A\\equiv 2\\pmod 4$ such that both the corresponding Montgomery curve ([31](#a-2-1-curve25519)) over $\\mathbb{F}_p$ for $p=2^{255}-19$ and the quadratic twist of this curve have small cofactors. Such an arrangement avoids the necessity to check whether an $x$-coordinate $x_P\\in\\mathbb{F}_p$ of a point $P$ defines a point $(x_P,y_P)\\in\\mathbb{F}_p^2$ lying on the Montgomery curve itself or on its quadratic twist. [Back ↑](#ref-fn42)\n"
  },
  {
    "path": "foundations/whitepapers/ton.mdx",
    "content": "---\ntitle: \"The Open Network\"\nsidebarTitle: \"The Open Network\"\ndescription: \"Whitepaper by Dr. Nikolai Durov\"\n---\n\n**Authors**: Nikolai Durov, TON Core <br />\n**Date**: July 26, 2021 <br />\n<Icon icon=\"file-pdf\" size={16} />: [Original whitepaper, PDF](/resources/pdfs/ton.pdf)\n\n## Abstract\n\nThe aim of this text is to provide a first description of the Telegram Open Network (TON) and related blockchain, peer-to-peer, distributed storage and service hosting technologies. To reduce the size of this document to reasonable proportions, we focus mainly on the unique and defining features of the TON platform that are important for it to achieve its stated goals.\n\n---\n\n## Introduction\n\nThe *Telegram Open Network (TON)* is a fast, secure and scalable blockchain and network project, capable of handling millions of transactions per second if necessary, and both user-friendly and service provider-friendly. We aim for it to be able to host all reasonable applications currently proposed and conceived. One might think about TON as a huge distributed supercomputer, or rather a huge \"superserver\", intended to host and provide a variety of services.\n\nThis text is not intended to be the ultimate reference with respect to all implementation details. Some particulars are likely to change during the development and testing phases.\n\n---\n\n## 1  Brief Description of TON Components\n\nThe *Telegram Open Network (TON)* is a combination of the following components:\n\n- A flexible multi-blockchain platform (*TON Blockchain*; cf. [Chapter 2](#2-ton-blockchain)), capable of processing millions of transactions per second, with Turing-complete smart contracts, upgradable formal blockchain specifications, multi-cryptocurrency value transfer, support for micropayment channels and off-chain payment networks. *TON Blockchain* presents some new and unique features, such as the \"self-healing\" vertical blockchain mechanism (cf. [2.1.17](#2-1-17-correcting-invalid-shardchain-blocks)) and Instant Hypercube Routing (cf. [2.4.20](#2-4-20-instant-hypercube-routing%3A-“fast-path”-for-messages)), which enable it to be fast, reliable, scalable and self-consistent at the same time.\n\n- A peer-to-peer network (*TON P2P Network*, or just *TON Network*; cf. [Chapter 3](#3-ton-networking)), used for accessing the TON Blockchain, sending transaction candidates, and receiving updates about only those parts of the blockchain a client is interested in (e.g., those related to the client's accounts and smart contracts), but also able to support arbitrary distributed services, blockchain-related or not.\n\n- A distributed file storage technology (*TON Storage*; cf. [4.1.8](#4-1-8-example%3A-keeping-files-off-chain%3B-ton-storage)), accessible through *TON Network*, used by the TON Blockchain to store archive copies of blocks and status data (snapshots), but also available for storing arbitrary files for users or other services running on the platform, with torrent-like access technology.\n\n- A network proxy/anonymizer layer (*TON Proxy*; cf. [4.1.11](#4-1-11-example%3A-ton-proxy-is-a-fog-service) and [3.1.6](#3-1-6-channel-as-a-tunnel-identifier)), similar to the $I^2P$ (Invisible Internet Project), used to hide the identity and IP addresses of *TON Network* nodes if necessary (e.g., nodes committing transactions from accounts with large amounts of cryptocurrency, or high-stake blockchain validator nodes who wish to hide their exact IP address and geographical location as a measure against DDoS attacks).\n\n- A Kademlia-like distributed hash table (*TON DHT*; cf. [3.2](#3-2-ton-dht%3A-kademlia-like-distributed-hash-table)), used as a \"torrent tracker\" for *TON Storage* (cf. [3.2.10](#3-2-10-distributed-“torrent-trackers”-and-“network-interest-groups”-in-ton-dht)), as an \"input tunnel locator\" for *TON Proxy* (cf. [3.2.14](#3-2-14-locating-abstract-addresses)), and as a service locator for *TON Services* (cf. [3.2.12](#3-2-12-locating-services)).\n\n- A platform for arbitrary services (*TON Services*; cf. [Chapter 4](#4-ton-services-and-applications)), residing in and available through *TON Network* and *TON Proxy*, with formalized interfaces (cf. [4.3.14](#4-3-14-public-interfaces-of-a-smart-contract)) enabling browser-like or smartphone application interaction. These formal interfaces and persistent service entry points can be published in the TON Blockchain (cf. [4.3.17](#4-3-17-locating-user-interfaces-via-ton-dns)); actual nodes providing service at any given moment can be looked up through the *TON DHT* starting from information published in the TON Blockchain (cf. [3.2.12](#3-2-12-locating-services)). Services may create smart contracts in the TON Blockchain to offer some guarantees to their clients (cf. [4.1.7](#4-1-7-mixed-services%3A-partly-off-chain%2C-partly-on-chain)).\n\n- *TON DNS* (cf. [4.3.1](#4-3-1-ton-dns%3A-a-mostly-on-chain-hierarchical-domain-name-service)), a service for assigning human-readable names to accounts, smart contracts, services and network nodes.\n\n- *TON Payments* (cf. [Chapter 5](#5-ton-payments)), a platform for micropayments, micropayment channels and a micropayment channel network. It can be used for fast off-chain value transfers, and for paying for services powered by *TON Services*.\n\n- TON will allow easy integration with third-party messaging and social networking applications, thus making blockchain technologies and distributed services finally available and accessible to ordinary users (cf. [4.3.24](#4-3-24-ton-www)), rather than just to a handful of early cryptocurrency adopters. We will provide an example of such an integration in another of our projects, the Telegram Messenger (cf. [4.3.19](#4-3-19-a-light-wallet-and-ton-entity-explorer-can-be-built-into-telegram-messenger-clients)).\n\nWhile the TON Blockchain is the core of the TON project, and the other components might be considered as playing a supportive role for the blockchain, they turn out to have useful and interesting functionality by themselves. Combined, they allow the platform to host more versatile applications than it would be possible by just using the TON Blockchain (cf. [2.9.13](#2-9-13-is-it-possible-to-upload-facebook-into-a-blockchain%3F) and [4.1](#4-1-ton-service-implementation-strategies)).\n\n---\n\n## 2  TON Blockchain\n\nWe start with a description of the Telegram Open Network (TON) Blockchain, the core component of the project. Our approach here is \"top-down\": we give a general description of the whole first, and then provide more detail on each component.\n\nFor simplicity, we speak here about *the* TON Blockchain, even though in principle several instances of this blockchain protocol may be running independently (for example, as a result of hard forks). We consider only one of them.\n\n### 2.1  TON Blockchain as a Collection of 2-Blockchains\n\nThe TON Blockchain is actually a *collection* of blockchains (even a collection of *blockchains of blockchains*, or *2-blockchains*—this point will be clarified later in [2.1.17](#2-1-17-correcting-invalid-shardchain-blocks)), because no single blockchain project is capable of achieving our goal of processing millions of transactions per second, as opposed to the now-standard dozens of transactions per second.\n\n#### 2.1.1. List of blockchain types\n\nThe blockchains in this collection are:\n\n- The unique *master blockchain*, or *masterchain* for short, containing general information about the protocol and the current values of its parameters, the set of validators and their stakes, the set of currently active workchains and their \"shards\", and, most importantly, the set of hashes of the most recent blocks of all workchains and shardchains.\n\n- Several (up to $2^{32}$) *working blockchains*, or *workchains* for short, which are actually the \"workhorses\", containing the value-transfer and smart-contract transactions. Different workchains may have different \"rules\", meaning different formats of account addresses, different formats of transactions, different virtual machines (VMs) for smart contracts, different basic cryptocurrencies and so on. However, they all must satisfy certain basic interoperability criteria to make interaction between different workchains possible and relatively simple. In this respect, the TON Blockchain is *heterogeneous* (cf. [2.8.8](#2-8-8-blockchain-types%3A-homogeneous-and-heterogeneous-systems)), similarly to the EOS (cf. [2.9.7](#2-9-7-eos)) and PolkaDot (cf. [2.9.8](#2-9-8-polkadot)) projects.\n\n- Each workchain is in turn subdivided into up to $2^{60}$ *shard blockchains*, or *shardchains* for short, having the same rules and block format as the workchain itself, but responsible only for a subset of accounts, depending on several first (most significant) bits of the account address. In other words, a form of sharding is built into the system (cf. [2.8.12](#2-8-12-sharding-support)). Because all these shardchains share a common block format and rules, the TON Blockchain is *homogeneous* in this respect (cf. [2.8.8](#2-8-8-blockchain-types%3A-homogeneous-and-heterogeneous-systems)), similarly to what has been discussed in one of Ethereum scaling proposals.<sup>[1](#fn1)</sup>\n\n- Each block in a shardchain (and in the masterchain) is actually not just a block, but a small blockchain. Normally, this \"block blockchain\" or \"vertical blockchain\" consists of exactly one block, and then we might think this is just the corresponding block of the shardchain (also called \"horizontal blockchain\" in this situation). However, if it becomes necessary to fix incorrect shardchain blocks, a new block is committed into the \"vertical blockchain\", containing either the replacement for the invalid \"horizontal blockchain\" block, or a \"block difference\", containing only a description of those parts of the previous version of this block that need to be changed. This is a TON-specific mechanism to replace detected invalid blocks without making a true fork of all shardchains involved; it will be explained in more detail in [2.1.17](#2-1-17-correcting-invalid-shardchain-blocks). For now, we just remark that each shardchain (and the masterchain) is not a conventional blockchain, but a *blockchain of blockchains*, or *2D-blockchain*, or just a *2-blockchain*.\n\n#### 2.1.2. Infinite Sharding Paradigm\n\nAlmost all blockchain sharding proposals are \"top-down\": one first imagines a single blockchain, and then discusses how to split it into several interacting shardchains to improve performance and achieve scalability.\n\nThe TON approach to sharding is \"bottom-up\", explained as follows.\n\nImagine that sharding has been taken to its extreme, so that exactly one account or smart contract remains in each shardchain. Then we have a huge number of \"account-chains\", each describing the state and state transitions of only one account, and sending value-bearing messages to each other to transfer value and information.\n\nOf course, it is impractical to have hundreds of millions of blockchains, with updates (i.e., new blocks) usually appearing quite rarely in each of them. In order to implement them more efficiently, we group these \"account-chains\" into \"shardchains\", so that each block of the shardchain is essentially a collection of blocks of account-chains that have been assigned to this shard. Thus the \"account-chains\" have only a purely virtual or logical existence inside the \"shardchains\".\n\nWe call this perspective the *Infinite Sharding Paradigm*. It explains many of the design decisions for the TON Blockchain.\n\n#### 2.1.3. Messages. Instant Hypercube Routing\n\nThe Infinite Sharding Paradigm instructs us to regard each account (or smart contract) as if it were in its own shardchain by itself. Then the only way one account might affect the state of another is by sending a *message* to it (this is a special instance of the so-called Actor model, with accounts as Actors; cf. [2.4.2](#2-4-2-accounts-as-processes-or-actors-actor-model)). Therefore, a system of messages between accounts (and shardchains, because the source and destination accounts are, generally speaking, located in different shardchains) is of paramount importance to a scalable system such as the TON Blockchain. In fact, a novel feature of the TON Blockchain, called *Instant Hypercube Routing* (cf. [2.4.20](#2-4-20-instant-hypercube-routing%3A-fast-path-for-messages)), enables it to deliver and process a message created in a block of one shardchain into the very next block of the destination shardchain, *regardless of the total number of shardchains in the system.*\n\n#### 2.1.4. Quantity of masterchains, workchains and shardchains\n\nA TON Blockchain contains exactly one masterchain. However, the system can potentially accommodate up to $2^{32}$ workchains, each subdivided into up to $2^{60}$ shardchains.\n\n#### 2.1.5. Workchains can be virtual blockchains, not true blockchains\n\nBecause a workchain is usually subdivided into shardchains, the existence of the workchain is \"virtual\", meaning that it is not a true blockchain in the sense of the general definition provided in [2.2.1](#2-2-1-general-blockchain-definition) below, but just a collection of shardchains. When only one shardchain corresponds to a workchain, this unique shardchain may be identified with the workchain, which in this case becomes a \"true\" blockchain, at least for some time, thus gaining a superficial similarity to customary single-blockchain design. However, the Infinite Sharding Paradigm (cf. [2.1.2](#2-1-2-infinite-sharding-paradigm)) tells us that this similarity is indeed superficial: it is just a coincidence that the potentially huge number of \"account-chains\" can temporarily be grouped into one blockchain.\n\n#### 2.1.6. Identification of workchains\n\nEach workchain is identified by its *number* or *workchain identifier* ($\\mathit{workchain\\_id}:\\mathit{uint}_{32}$), which is simply an unsigned 32-bit integer. Workchains are created by special transactions in the masterchain, defining the (previously unused) workchain identifier and the formal description of the workchain, sufficient at least for the interaction of this workchain with other workchains and for superficial verification of this workchain's blocks.\n\n#### 2.1.7. Creation and activation of new workchains\n\nThe creation of a new workchain may be initiated by essentially any member of the community, ready to pay the (high) masterchain transaction fees required to publish the formal specification of a new workchain. However, in order for the new workchain to become active, a two-thirds consensus of validators is required, because they will need to upgrade their software to process blocks of the new workchain, and signal their readiness to work with the new workchain by special masterchain transactions. The party interested in the activation of the new workchain might provide some incentive for the validators to support the new workchain by means of some rewards distributed by a smart contract.\n\n#### 2.1.8. Identification of shardchains\n\nEach shardchain is identified by a couple $(w,s)=(\\mathit{workchain\\_id}, \\mathit{shard\\_prefix})$, where $\\mathit{workchain\\_id}:\\text{uint}_{32}$ identifies the corresponding workchain, and $\\mathit{shard\\_prefix}:\\mathbf{2}^{0\\ldots 60}$ is a bit string of length at most 60, defining the subset of accounts for which this shardchain is responsible. Namely, all accounts with $\\mathit{account\\_id}$ starting with $\\mathit{shard\\_prefix}$ (i.e., having $\\mathit{shard\\_prefix}$ as most significant bits) will be assigned to this shardchain.\n\n#### 2.1.9. Identification of account-chains\n\nRecall that account-chains have only a virtual existence (cf. [2.1.2](#2-1-2-infinite-sharding-paradigm)). However, they have a natural identifier—namely, $(\\mathit{workchain\\_id},\\mathit{account\\_id})$—because any account-chain contains information about the state and updates of exactly one account (either a simple account or smart contract—the distinction is unimportant here).\n\n#### 2.1.10. Dynamic splitting and merging of shardchains; cf 2.7.\n\nA less sophisticated system might use *static sharding*—for example, by using the top eight bits of the $\\mathit{account\\_id}$ to select one of 256 pre-defined shards.\n\nAn important feature of the TON Blockchain is that it implements *dynamic sharding*, meaning that the number of shards is not fixed. Instead, shard $(w,s)$ can be automatically subdivided into shards $(w,s.0)$ and $(w,s.1)$ if some formal conditions are met (essentially, if the transaction load on the original shard is high enough for a prolonged period of time). Conversely, if the load stays too low for some period of time, the shards $(w,s.0)$ and $(w,s.1)$ can be automatically merged back into shard $(w,s)$.\n\nInitially, only one shard $(w,\\emptyset)$ is created for workchain $w$. Later, it is subdivided into more shards, if and when this becomes necessary (cf. [2.7.6](#2-7-6-determining-the-necessity-of-split-operations) and [2.7.8](#2-7-8-determining-the-necessity-of-merge-operations)).\n\n#### 2.1.11. Basic workchain or Workchain Zero\n\nWhile up to $2^{32}$ workchains can be defined with their specific rules and transactions, we initially define only one, with $\\mathit{workchain\\_id}=0$. This workchain, called Workchain Zero or the basic workchain, is the one used to work with *TON smart contracts* and transfer *TON coins*, also known as *Grams* (cf. [Appendix A](#appendix-the-ton-coin-or-the-gram)). Most applications are likely to require only Workchain Zero. Shardchains of the basic workchain will be called *basic shardchains*.\n\n#### 2.1.12. Block generation intervals\n\nWe expect a new block to be generated in each shardchain and the masterchain approximately once every five seconds. This will lead to reasonably small transaction confirmation times. New blocks of all shardchains are generated approximately simultaneously; a new block of the masterchain is generated approximately one second later, because it must contain the hashes of the latest blocks of all shardchains.\n\n#### 2.1.13. Using the masterchain to make workchains and shardchains tightly coupled\n\nOnce the hash of a block of a shardchain is incorporated into a block of the masterchain, that shardchain block and all its ancestors are considered \"canonical\", meaning that they can be referenced from the subsequent blocks of all shardchains as something fixed and immutable. In fact, each new shardchain block contains a hash of the most recent masterchain block, and all shardchain blocks referenced from that masterchain block are considered immutable by the new block.\n\nEssentially, this means that a transaction or a message committed in a shardchain block may be safely used in the very next blocks of the other shardchains, without needing to wait for, say, twenty confirmations (i.e., twenty blocks generated after the original block in the same blockchain) before forwarding a message or taking other actions based on a previous transaction, as is common in most proposed \"loosely-coupled\" systems (cf. [2.8.14](#2-8-14-interaction-between-blockchains%3A-loosely-coupled-and-tightly-coupled-systems)), such as EOS. This ability to use transactions and messages in other shardchains a mere five seconds after being committed is one of the reasons we believe our \"tightly-coupled\" system, the first of its kind, will be able to deliver unprecedented performance (cf. [2.8.12](#2-8-12-sharding-support) and [2.8.14](#2-8-14-interaction-between-blockchains%3A-loosely-coupled-and-tightly-coupled-systems)).\n\n#### 2.1.14. Masterchain block hash as a global state\n\nAccording to [2.1.13](#2-1-13-using-the-masterchain-to-make-workchains-and-shardchains-tightly-coupled), the hash of the last masterchain block completely determines the overall state of the system from the perspective of an external observer. One does not need to monitor the state of all shardchains separately.\n\n#### 2.1.15. Generation of new blocks by validators; cf 2.6\n\nThe TON Blockchain uses a Proof-of-Stake (PoS) approach for generating new blocks in the shardchains and the masterchain. This means that there is a set of, say, up to a few hundred *validators*—special nodes that have deposited *stakes* (large amounts of TON coins) by a special masterchain transaction to be eligible for new block generation and validation.\n\nThen a smaller subset of validators is assigned to each shard $(w,s)$ in a deterministic pseudorandom way, changing approximately every 1024 blocks. This subset of validators suggests and reaches consensus on what the next shardchain block would be, by collecting suitable proposed transactions from the clients into new valid block candidates. For each block, there is a pseudorandomly chosen order on the validators to determine whose block candidate has the highest priority to be committed at each turn.\n\nValidators and other nodes check the validity of the proposed block candidates; if a validator signs an invalid block candidate, it may be automatically punished by losing part or all of its stake, or by being suspended from the set of validators for some time. After that, the validators should reach consensus on the choice of the next block, essentially by an efficient variant of the BFT (Byzantine Fault Tolerant; cf. [2.8.4](#2-8-4-variants-of-proof-of-stake-dpos-vs-bft)) consensus protocol, similar to PBFT \\[[4](#ref-4)] or Honey Badger BFT \\[[11](#ref-11)]. If consensus is reached, a new block is created, and validators divide between themselves the transaction fees for the transactions included, plus some newly-created (\"minted\") coins.\n\nEach validator can be elected to participate in several validator subsets; in this case, it is expected to run all validation and consensus algorithms in parallel.\n\nAfter all new shardchain blocks are generated or a timeout is passed, a new masterchain block is generated, including the hashes of the latest blocks of all shardchains. This is done by BFT consensus of *all* validators.<sup>[2](#fn2)</sup>\n\nMore detail on the TON PoS approach and its economical model is provided in section [2.6](#2-6-creating-and-validating-new-blocks).\n\n#### 2.1.16. Forks of the masterchain\n\nA complication that arises from our tightly-coupled approach is that switching to a different fork in the masterchain will almost necessarily require switching to another fork in at least some of the shardchains. On the other hand, as long as there are no forks in the masterchain, no forks in the shardchain are even possible, because no blocks in the alternative forks of the shardchains can become \"canonical\" by having their hashes incorporated into a masterchain block.\n\nThe general rule is that *if masterchain block $B'$ is a predecessor of $B$, $B'$ includes hash $\\text{Hash}(B'_{w,s})$ of $(w,s)$-shardchain block $B'_{w,s}$, and $B$ includes hash $\\text{Hash}(B_{w,s})$, then $B'_{w,s}$ **must** be a predecessor of $B_{w,s}$; otherwise, the masterchain block $B$ is invalid.*\n\nWe expect masterchain forks to be rare, next to non-existent, because in the BFT paradigm adopted by the TON Blockchain they can happen only in the case of incorrect behavior by a majority of validators (cf. [2.6.1](#2-6-1-validators) and [2.6.15](#2-6-15-generation-of-new-masterchain-blocks)), which would imply significant stake losses by the offenders. Therefore, no true forks in the shardchains should be expected. Instead, if an invalid shardchain block is detected, it will be corrected by means of the \"vertical blockchain\" mechanism of the 2-blockchain (cf. [2.1.17](#2-1-17-correcting-invalid-shardchain-blocks)), which can achieve this goal without forking the \"horizontal blockchain\" (i.e., the shardchain). The same mechanism can be used to fix non-fatal mistakes in the masterchain blocks as well.\n\n#### 2.1.17. Correcting invalid shardchain blocks\n\nNormally, only valid shardchain blocks will be committed, because validators assigned to the shardchain must reach a two-thirds Byzantine consensus before a new block can be committed. However, the system must allow for detection of previously committed invalid blocks and their correction.\n\nOf course, once an invalid shardchain block is found—either by a validator (not necessarily assigned to this shardchain) or by a \"fisherman\" (any node of the system that made a certain deposit to be able to raise questions about block validity; cf. [2.6.4](#2-6-4-fishermen%3A-obtaining-money-by-pointing-out-others%E2%80%99-mistakes))—the invalidity claim and its proof are committed into the masterchain, and the validators that have signed the invalid block are punished by losing part of their stake and/or being temporarily suspended from the set of validators (the latter measure is important for the case of an attacker stealing the private signing keys of an otherwise benign validator).\n\nHowever, this is not sufficient, because the overall state of the system (TON Blockchain) turns out to be invalid because of the invalid shardchain block previously committed. This invalid block must be replaced by a newer valid version.\n\nMost systems would achieve this by \"rolling back\" to the last block before the invalid one in this shardchain and the last blocks unaffected by messages propagated from the invalid block in each of the other shardchains, and creating a new fork from these blocks. This approach has the disadvantage that a large number of otherwise correct and committed transactions are suddenly rolled back, and it is unclear whether they will be included later at all.\n\nThe TON Blockchain solves this problem by making each \"block\" of each shardchain and of the masterchain (\"horizontal blockchains\") a small blockchain (\"vertical blockchain\") by itself, containing different versions of this \"block\", or their \"differences\". Normally, the vertical blockchain consists of exactly one block, and the shardchain looks like a classical blockchain. However, once the invalidity of a block is confirmed and committed into a masterchain block, the \"vertical blockchain\" of the invalid block is allowed to grow by a new block in the vertical direction, replacing or editing the invalid block. The new block is generated by the current validator subset for the shardchain in question.\n\nThe rules for a new \"vertical\" block to be valid are quite strict. In particular, if a virtual \"account-chain block\" (cf. [2.1.2](#2-1-2-infinite-sharding-paradigm)) contained in the invalid block is valid by itself, it must be left unchanged by the new vertical block.\n\nOnce a new \"vertical\" block is committed on top of the invalid block, its hash is published in a new masterchain block (or rather in a new \"vertical\" block, lying above the original masterchain block where the hash of the invalid shardchain block was originally published), and the changes are propagated further to any shardchain blocks referring to the previous version of this block (e.g., those having received messages from the incorrect block). This is fixed by committing new \"vertical\" blocks in vertical blockchains for all blocks previously referring to the \"incorrect\" block; new vertical blocks will refer to the most recent (corrected) versions instead. Again, strict rules forbid changing account-chains that are not really affected (i.e., that receive the same messages as in the previous version). In this way, fixing an incorrect block generates \"ripples\" that are ultimately propagated towards the most recent blocks of all affected shardchains; these changes are reflected in new \"vertical\" masterchain blocks as well.\n\nOnce the \"history rewriting\" ripples reach the most recent blocks, the new shardchain blocks are generated in one version only, being successors of the newest block versions only. This means that they will contain references to the correct (most recent) vertical blocks from the very beginning.\n\nThe masterchain state implicitly defines a map transforming the hash of the first block of each \"vertical\" blockchain into the hash of its latest version. This enables a client to identify and locate any vertical blockchain by the hash of its very first (and usually the only) block.\n\n#### 2.1.18. TON coins and multi-currency workchains\n\nThe TON Blockchain supports up to $2^{32}$ different \"cryptocurrencies\", \"coins\", or \"tokens\", distinguished by a 32-bit $\\mathit{currency\\_id}$. New cryptocurrencies can be added by special transactions in the masterchain. Each workchain has a basic cryptocurrency, and can have several additional cryptocurrencies.\n\nThere is one special cryptocurrency with $\\mathit{currency\\_id}=0$, namely, the *TON coin*, also known as the *Gram* (cf. [Appendix A](#appendix-the-ton-coin-or-the-gram)). It is the basic cryptocurrency of Workchain Zero. It is also used for transaction fees and validator stakes.\n\nIn principle, other workchains may collect transaction fees in other tokens. In this case, some smart contract for automated conversion of these transaction fees into Grams should be provided.\n\n#### 2.1.19. Messaging and value transfer\n\nShardchains belonging to the same or different workchains may send *messages* to each other. While the exact form of the messages allowed depends on the receiving workchain and receiving account (smart contract), there are some common fields making inter-workchain messaging possible. In particular, each message may have some *value* attached, in the form of a certain amount of Grams (TON coins) and/or other registered cryptocurrencies, provided they are declared as acceptable cryptocurrencies by the receiving workchain.\n\nThe simplest form of such messaging is a value transfer from one (usually not a smart-contract) account to another.\n\n#### 2.1.20. TON Virtual Machine\n\nThe *TON Virtual Machine*, also abbreviated as *TON VM* or *TVM*, is the virtual machine used to execute smart-contract code in the masterchain and in the basic workchain. Other workchains may use other virtual machines alongside or instead of the TVM.\n\nHere we list some of its features. They are discussed further in [2.3.12](#2-3-12-peculiarities-of-ton-vm), [2.3.14](#2-3-14-tvm-cells) and elsewhere:\n\n• TVM represents all data as a collection of *(TVM) cells* (cf. [2.3.14](#2-3-14-tvm-cells)). Each cell contains up to 128 data bytes and up to 4 references to other cells. As a consequence of the \"everything is a bag of cells\" philosophy (cf. [2.5.14](#2-5-14-everything-is-a-bag-of-cells-philosophy)), this enables TVM to work with all data related to the TON Blockchain, including blocks and blockchain global state if necessary.\n\n• TVM can work with values of arbitrary algebraic data types (cf. [2.3.12](#2-3-12-peculiarities-of-ton-vm)), represented as trees or directed acyclic graphs of TVM cells. However, it is agnostic towards the existence of algebraic data types; it just works with cells.\n\n• TVM has built-in support for hashmaps (cf. [2.3.7](#2-3-7-denition-of-hashmap-type-as-a-patricia-tree)).\n\n• TVM is a stack machine. Its stack keeps either 64-bit integers or cell references.\n\n• 64-bit, 128-bit and 256-bit arithmetic is supported. All $n$-bit arithmetic operations come in three flavors: for unsigned integers, for signed integers and for integers modulo $2^n$ (no automatic overflow checks in the latter case).\n\n• TVM has unsigned and signed integer conversion from $n$-bit to $m$-bit, for all $0 \\leq m, n \\leq 256$, with overflow checks.\n\n• All arithmetic operations perform overflow checks by default, greatly simplifying the development of smart contracts.\n\n• TVM has \"multiply-then-shift\" and \"shift-then-divide\" arithmetic operations with intermediate values computed in a larger integer type; this simplifies implementing fixed-point arithmetic.\n\n• TVM offers support for bit strings and byte strings.\n\n• Support for 256-bit Elliptic Curve Cryptography (ECC) for some predefined curves, including Curve25519, is present.\n\n• Support for Weil pairings on some elliptic curves, useful for fast implementation of zk-SNARKs, is also present.\n\n• Support for popular hash functions, including SHA-256, is present.\n\n• TVM can work with Merkle proofs (cf. [5.1.9](#5-1-9-ton-vm-support-for-smart-payment-channels)).\n\n• TVM offers support for \"large\" or \"global\" smart contracts. Such smart contracts must be aware of sharding (cf. [2.3.18](#2-3-18-local-and-global-smart-contracts%3B-smart-contract-instances) and [2.3.16](#2-3-16-support-for-sharding-in-ton-vm-data-structures)). Usual (local) smart contracts can be sharding-agnostic.\n\n• TVM supports closures.\n\n• A \"spineless tagless G-machine\" [[13]](#ref-13) can be easily implemented inside TVM.\n\nSeveral high-level languages can be designed for TVM, in addition to the \"TVM assembly\". All these languages will have static types and will support algebraic data types. We envision the following possibilities:\n\n- A Java-like imperative language, with each smart contract resembling a separate class.\n- A lazy functional language (think of Haskell).\n- An eager functional language (think of ML).\n\n#### 2.1.21. Configurable parameters\n\nAn important feature of the TON Blockchain is that many of its parameters are *configurable*. This means that they are part of the masterchain state, and can be changed by certain special proposal/vote/result transactions in the masterchain, without any need for hard forks. Changing such parameters will require collecting two-thirds of validator votes and more than half of the votes of all other participants who would care to take part in the voting process in favor of the proposal.\n\n---\n\n### 2.2  Generalities on Blockchains\n\n#### 2.2.1. General blockchain definition\n\nIn general, any *(true) blockchain* is a sequence of *blocks*, each block $B$ containing a reference $\\text{Blk-Prev}(B)$ to the previous block (usually by including the hash of the previous block into the header of the current block), and a list of *transactions*. Each transaction describes some transformation of the *global blockchain state*; the transactions listed in a block are applied sequentially to compute the new state starting from the old state, which is the resulting state after the evaluation of the previous block.\n\n#### 2.2.2. Relevance for the TON Blockchain\n\nRecall that the *TON Blockchain* is not a true blockchain, but a collection of 2-blockchains (i.e., of blockchains of blockchains; cf. [2.1.1](#2-1-1-list-of-blockchain-types)), so the above is not directly applicable to it. However, we start with these generalities on true blockchains to use them as building blocks for our more sophisticated constructions.\n\n#### 2.2.3. Blockchain instance and blockchain type\n\nOne often uses the word *blockchain* to denote both a general *blockchain type* and its specific *blockchain instances*, defined as sequences of blocks satisfying certain conditions. For example, [2.2.1](#2-2-1-general-blockchain-definition) refers to blockchain instances.\n\nIn this way, a blockchain type is usually a \"subtype\" of the type $\\text{Block}^*$ of lists (i.e., finite sequences) of blocks, consisting of those sequences of blocks that satisfy certain compatibility and validity conditions:\n\n$$\n\\text{Blockchain} \\subset \\text{Block}^* \\tag{1}\n$$\n\nA better way to define $\\text{Blockchain}$ would be to say that $\\text{Blockchain}$ is a *dependent couple type*, consisting of couples $(\\mathbb{B}, v)$, with first component $\\mathbb{B} : \\text{Block}^*$ being of type $\\text{Block}^*$ (i.e., a list of blocks), and the second component $v : \\text{isValidBc}(\\mathbb{B})$ being a proof or a witness of the validity of $\\mathbb{B}$. In this way,\n\n$$\n\\text{Blockchain} \\equiv \\Sigma_{(\\mathbb{B} : \\text{Block}^*)} \\text{isValidBc}(\\mathbb{B}) \\tag{2}\n$$\n\nWe use here the notation for dependent sums of types borrowed from \\[[16](#ref-16)].\n\n#### 2.2.4. Dependent type theory, Coq and TL\n\nNote that we are using (Martin-Löf) dependent type theory here, similar to that used in the Coq<sup>[3](#fn3)</sup> proof assistant. A simplified version of dependent type theory is also used in *TL (Type Language)*,<sup>[4](#fn4)</sup> which will be used in the formal specification of the TON Blockchain to describe the serialization of all data structures and the layouts of blocks, transactions, and the like.\n\nIn fact, dependent type theory gives a useful formalization of what a proof is, and such formal proofs (or their serializations) might become handy when one needs to provide proof of invalidity for some block, for example.\n\n#### 2.2.5. TL, or the Type Language\n\nSince TL (Type Language) will be used in the formal specifications of TON blocks, transactions, and network datagrams, it warrants a brief discussion.\n\nTL is a language suitable for description of dependent algebraic *types*, which are allowed to have numeric (natural) and type parameters. Each type is described by means of several *constructors*. Each constructor has a (human-readable) identifier and a *name,* which is a bit string (32-bit integer by default). Apart from that, the definition of a constructor contains a list of fields along with their types.\n\nA collection of constructor and type definitions is called a *TL-scheme*. It is usually kept in one or several files with the suffix `.tl`.\n\nAn important feature of TL-schemes is that they determine an unambiguous way of serializing and deserializing values (or objects) of algebraic types defined. Namely, when a value needs to be serialized into a stream of bytes, first the name of the constructor used for this value is serialized. Recursively computed serializations of each field follow.\n\nThe description of a previous version of TL, suitable for serializing arbitrary objects into sequences of 32-bit integers, is available at https://core.telegram.org/mtproto/TL. A new version of TL, called *TL-B*, is being developed for the purpose of describing the serialization of objects used by the TON Project. This new version can serialize objects into streams of bytes and even bits (not just 32-bit integers), and offers support for serialization into a tree of TVM cells (cf. [2.3.14](#2-3-14-tvm-cells)). A description of TL-B will be a part of the formal specification of the TON Blockchain.\n\n\n#### 2.2.6. Blocks and transactions as state transformation operators\n\nNormally, any blockchain (type) *Blockchain* has an associated global state (type) *State*, and a transaction (type) *Transaction*. The semantics of a blockchain are to a large extent determined by the transaction application function:\n\n$$\n\\mathit{ev\\_trans}':\\mathit{Transaction}\\times\\mathit{State}\\to\\mathit{State}^? \\tag{3}\n$$\n\nHere $X^?$ denotes $\\text{Maybe}$ $X$, the result of applying the $\\text{Maybe}$ monad to type $X$. This is similar to our use of $X^*$ for $\\text{List}$ $X$. Essentially, a value of type $X^?$ is either a value of type $X$ or a special value $\\bot$ indicating the absence of an actual value (think about a null pointer). In our case, we use $\\mathit{State}^?$ instead of $\\mathit{State}$ as the result type because a transaction may be invalid if invoked from certain original states (think about attempting to withdraw from an account more money than it is actually there).\n\nWe might prefer a curried version of $\\mathit{ev\\_trans}'$:\n\n$$\n\\mathit{ev\\_trans}:\\mathit{Transaction}\\to\\mathit{State}\\to\\mathit{State}^? \\tag{4}\n$$\n\nBecause a block is essentially a list of transactions, the block evaluation function\n\n$$\n\\mathit{ev\\_block}:\\mathit{Block}\\to\\mathit{State}\\to\\mathit{State}^? \\tag{5}\n$$\n\ncan be derived from $\\mathit{ev\\_trans}$. It takes a block $B$:*Block* and the previous blockchain state $s$:*State* (which might include the hash of the previous block) and computes the next blockchain state $s'=\\mathit{ev\\_block}(B)(s)$:*State*, which is either a true state or a special value $\\bot$ indicating that the next state cannot be computed (i.e., that the block is invalid if evaluated from the starting state given—for example, the block includes a transaction trying to debit an empty account.)\n\n#### 2.2.7. Block sequence numbers\n\nEach block $B$ in the blockchain can be referred to by its *sequence number* $\\text{Blk-Seqno}(B)$, starting from zero for the very first block, and incremented by one whenever passing to the next block. More formally,\n\n$$\n\\text{Blk-Seqno}(B) = \\text{Blk-Seqno}\\bigl(\\text{Blk-Prev}(B)\\bigr) + 1 \\tag{6}\n$$\n\nNotice that the sequence number does not identify a block uniquely in the presence of *forks*.\n\n#### 2.2.8. Block hashes\n\nAnother way of referring to a block $B$ is by its hash $\\text{Blk-Hash}(B)$, which is actually the hash of the *header* of block $B$ (however, the header of the block usually contains hashes that depend on all content of block $B$). Assuming that there are no collisions for the hash function used (or at least that they are very improbable), a block is uniquely identified by its hash.\n\n#### 2.2.9. Hash assumption\n\nDuring formal analysis of blockchain algorithms, we assume that there are no collisions for the $k$-bit hash function $\\text{Hash} : \\text{Bytes}^* \\to \\mathbf{2}^k$ used:\n\n$$\n\\text{Hash}(s) = \\text{Hash}(s') \\Rightarrow s = s' \\quad \\text{for any } s, s' \\in \\text{Bytes}^* \\tag{7}\n$$\n\nHere $\\text{Bytes} = \\{0\\ldots255\\} = \\mathbf{2}^8$ is the type of bytes, or the set of all byte values, and $\\text{Bytes}^*$ is the type or set of arbitrary (finite) lists of bytes; while $\\mathbf{2} = \\{0,1\\}$ is the bit type, and $\\mathbf{2}^k$ is the set (or actually the type) of all $k$-bit sequences (i.e., of $k$-bit numbers).\n\nOf course, ([7](#2-2-9-hash-assumption)) is impossible mathematically, because a map from an infinite set to a finite set cannot be injective. A more rigorous assumption would be\n\n$$\n\\forall s, s': s \\neq s', P\\bigl(\\text{Hash}(s) = \\text{Hash}(s')\\bigr) = 2^{-k} \\tag{8}\n$$\n\nHowever, this is not so convenient for the proofs. If ([8](#2-2-9-hash-assumption)) is used at most $N$ times in a proof with $2^{-k}N < \\epsilon$ for some small $\\epsilon$ (say, $\\epsilon = 10^{-18}$), we can reason as if ([7](#2-2-9-hash-assumption)) were true, provided we accept a failure probability $\\epsilon$ (i.e., the final conclusions will be true with probability at least $1 - \\epsilon$).\n\nFinal remark: in order to make the probability statement of ([8](#2-2-9-hash-assumption)) really rigorous, one must introduce a probability distribution on the set $\\text{Bytes}^*$ of all byte sequences. A way of doing this is by assuming all byte sequences of the same length $l$ equiprobable, and setting the probability of observing a sequence of length $l$ equal to $p^l - p^{l+1}$ for some $p \\to 1^-$. Then ([8](#2-2-9-hash-assumption)) should be understood as a limit of conditional probability $P\\bigl(\\text{Hash}(s) = \\text{Hash}(s') | s \\neq s'\\bigr)$ when $p$ tends to one from below.\n\n#### 2.2.10. Hash used for the TON Blockchain\n\nWe are using the 256-bit SHA-256 hash for the TON Blockchain for the time being. If it turns out to be weaker than expected, it can be replaced by another hash function in the future. The choice of the hash function is a configurable parameter of the protocol, so it can be changed without hard forks as explained in [2.1.21](#2-1-21-configurable-parameters).\n\n---\n\n### 2.3   Blockchain State, Accounts and Hashmaps\n\nWe have noted above that any blockchain defines a certain global state, and each block and each transaction defines a transformation of this global state. Here we describe the global state used by TON blockchains.\n\n#### 2.3.1. Account IDs\n\nThe basic account IDs used by TON blockchains—or at least by its masterchain and Workchain Zero—are 256-bit integers, assumed to be public keys for 256-bit Elliptic Curve Cryptography (ECC) for a specific elliptic curve. In this way,\n\n$$\n\\mathit{account\\_id}:\\mathit{Account}=\\mathit{uint}_{256}=\\mathbf{2}^{256} \\tag{9}\n$$\n\nHere $\\mathit{Account}$ is the account *type*, while $\\mathit{account\\_id}:\\mathit{Account}$ is a specific variable of type $\\mathit{Account}$.\n\nOther workchains can use other account ID formats, 256-bit or otherwise. For example, one can use Bitcoin-style account IDs, equal to SHA-256 of an ECC public key.\n\nHowever, the bit length $l$ of an account ID must be fixed during the creation of the workchain (in the masterchain), and it must be at least 64, because the first 64 bits of $\\mathit{account\\_id}$ are used for sharding and message routing.\n\n#### 2.3.2. Main component: *Hashmaps*\n\nThe principal component of the TON blockchain state is a *hashmap*. In some cases we consider (partially defined) \"maps\" $h:\\mathbf{2}^n\\dashrightarrow \\mathbf{2}^m$. More generally, we might be interested in hashmaps $h:\\mathbf{2}^n\\dashrightarrow X$ for a composite type $X$. However, the source (or index) type is almost always $\\mathbf{2}^n$.\n\nSometimes, we have a \"default value\" $\\mathit{empty}:X$, and the hashmap $h:\\mathbf{2}^n\\to X$ is \"initialized\" by its \"default value\" $i\\mapsto\\mathit{empty}$.\n\n#### 2.3.3. Example: TON account balances\n\nAn important example is given by TON account balances. It is a hashmap\n\n$$\n\\mathit{balance} : \\mathit{Account} \\to \\mathit{uint}_{128} \\tag{10}\n$$\n\nmapping $\\mathit{Account} = \\mathbf{2}^{256}$ into a Gram (TON coin) balance of type $\\mathit{uint}_{128} = \\mathbf{2}^{128}$. This hashmap has a default value of zero, meaning that initially (before the first block is processed) the balance of all accounts is zero.\n\n#### 2.3.4. Example: smart-contract persistent storage\n\nAnother example is given by smart-contract persistent storage, which can be (very approximately) represented as a hashmap\n\n$$\n\\mathit{storage} : \\mathbf{2}^{256} \\dashrightarrow \\mathbf{2}^{256} \\tag{11}\n$$\n\nThis hashmap also has a default value of zero, meaning that uninitialized cells of persistent storage are assumed to be zero.\n\n#### 2.3.5. Example: persistent storage of all smart contracts\n\nBecause we have more than one smart contract, distinguished by $\\mathit{account\\_id}$, each having its separate persistent storage, we must actually have a hashmap\n\n$$\n\\mathit{Storage}:\\mathit{Account}\\dashrightarrow(\\mathbf{2}^{256}\\dashrightarrow \\mathbf{2}^{256}) \\tag{12}\n$$\n\nmapping $\\mathit{account\\_id}$ of a smart contract into its persistent storage.\n\n#### 2.3.6. Hashmap type\n\nThe hashmap is not just an abstract (partially defined) function $\\mathbf{2}^n\\dashrightarrow X$; it has a specific representation. Therefore, we suppose that we have a special hashmap type\n\n$$\n\\mathit{Hashmap}(n,X):\\mathit{Type} \\tag{13}\n$$\n\ncorresponding to a data structure encoding a (partial) map $\\mathbf{2}^n\\dashrightarrow X$. We can also write\n\n$$\n\\mathit{Hashmap}(n:\\mathit{nat})(X:\\mathit{Type}):\\mathit{Type} \\tag{14}\n$$\n\nor\n\n$$\n\\mathit{Hashmap}:\\mathit{nat}\\to\\mathit{Type}\\to\\mathit{Type} \\tag{15}\n$$\n\nWe can always transform $h:\\mathit{Hashmap}(n,X)$ into a map $\\mathit{hget}(h):\\mathbf{2}^n\\to X^?$. Henceforth, we usually write $h[i]$ instead of $\\mathit{hget}(h)(i)$:\n\n$$\nh[i]:\\equiv\\mathit{hget}(h)(i):X^?\\quad\\text{for any }i:\\mathbf{2}^n,\\ h:\\mathit{Hashmap}(n,X) \\tag{16}\n$$\n\n#### 2.3.7. Definition of hashmap type as a Patricia tree\n\nLogically, one might define $\\mathit{Hashmap}(n,X)$ as an (incomplete) binary tree of depth $n$ with edge labels $0$ and $1$ and with values of type $X$ in the leaves. Another way to describe the same structure would be as a *(bitwise) trie* for binary strings of length equal to $n$.\n\nIn practice, we prefer to use a compact representation of this trie, by compressing each vertex having only one child with its parent. The resulting representation is known as a *Patricia tree* or a *binary radix tree*. Each intermediate vertex now has exactly two children, labeled by two non-empty binary strings, beginning with zero for the left child and with one for the right child.\n\nIn other words, there are two types of (non-root) nodes in a Patricia tree:\n\n- $\\text{Leaf}(x)$, containing value $x$ of type $X$.\n- $\\text{Node}(l,s_l,r,s_r)$, where $l$ is the (reference to the) left child or subtree, $s_l$ is the bitstring labeling the edge connecting this vertex to its left child (always beginning with 0), $r$ is the right subtree, and $s_r$ is the bitstring labeling the edge to the right child (always beginning with 1).\n\nA third type of node, to be used only once at the root of the Patricia tree, is also necessary:\n\n- $\\text{Root}(n,s_0,t)$, where $n$ is the common length of index bitstrings of $\\mathit{Hashmap}(n,X)$, $s_0$ is the common prefix of all index bitstrings, and $t$ is a reference to a $\\text{Leaf}$ or a $\\text{Node}$.\n\nIf we want to allow the Patricia tree to be empty, a fourth type of (root) node would be used:\n\n- $\\text{EmptyRoot}(n)$, where $n$ is the common length of all index bitstrings.\n\nWe define the height of a Patricia tree by\n\n$$\n\\texttt{Height}(\\texttt{Leaf}(x))=0 \\tag{17}\n$$\n\n\n$$\n\\texttt{Height}\\bigl(\\texttt{Node}(l,s_l,r,s_r)\\bigr) = \\texttt{Height}(l)+\\texttt{Len}(s_l) = \\texttt{Height}(r)+\\texttt{Len}(s_r) \\qquad (18)\n$$\n\n$$\n\\texttt{Height}\\bigl(\\texttt{Root}(n,s_0,t)\\bigr)=\\texttt{Len}(s_0)+\\texttt{Height}(t)=n \\tag{19}\n$$\n\nThe last two expressions in each of the last two formulas must be equal. We use Patricia trees of height $n$ to represent values of type $\\mathit{Hashmap}(n,X)$.\n\nIf there are $N$ leaves in the tree (i.e., our hashmap contains $N$ values), then there are exactly $N-1$ intermediate vertices. Inserting a new value always involves splitting an existing edge by inserting a new vertex in the middle and adding a new leaf as the other child of this new vertex. Deleting a value from a hashmap does the opposite: a leaf and its parent are deleted, and the parent's parent and its other child become directly linked.\n\n#### 2.3.8. Merkle-Patricia trees\n\nWhen working with blockchains, we want to be able to compare Patricia trees (i.e., hash maps) and their subtrees, by reducing them to a single hash value. The classical way of achieving this is given by the Merkle tree. Essentially, we want to describe a way of hashing objects $h$ of type $\\mathit{Hashmap}(n,X)$ with the aid of a hash function $\\text{Hash}$ defined for binary strings, provided we know how to compute hashes $\\text{Hash}(x)$ of objects $x:X$ (e.g., by applying the hash function $\\text{Hash}$ to a binary serialization of object $x$).\n\nOne might define $\\text{Hash}(h)$ recursively as follows:\n\n$$\n\\text{Hash}\\bigl(\\text{Leaf}(x)\\bigr):=\\text{Hash}(x) \\tag{20}\n$$\n\n$$\n\\texttt{Hash}\\bigl(\\texttt{Node}(l,s_l,r,s_r)\\bigr):=\\texttt{Hash}\\bigl(\\texttt{Hash}(l).\\texttt{Hash}(r).\\texttt{Code}(s_l).\\texttt{Code}(s_r)\\bigr) \\qquad (21)\n$$\n\n\n$$\n\\texttt{Hash}\\bigl(\\texttt{Root}(n,s_0,t)\\bigr):=\\texttt{Hash}\\bigl(\\texttt{Code}(n).\\texttt{Code}(s_0).\\texttt{Hash}(t)\\bigr) \\tag{22}\n$$\n\nHere $s.t$ denotes the concatenation of (bit) strings $s$ and $t$, and $\\text{Code}(s)$ is a prefix code for all bit strings $s$. For example, one might encode 0 by 10, 1 by 11, and the end of the string by 0.<sup>[5](#fn5)</sup>\n\nWe will see later (cf. [2.3.12](#2-3-12-peculiarities-of-ton-vm) and [2.3.14](#2-3-14-tvm-cells)) that this is a (slightly tweaked) version of recursively defined hashes for values of arbitrary (dependent) algebraic types.\n\n#### 2.3.9. Recomputing Merkle tree hashes\n\nThis way of recursively defining $\\text{Hash}(h)$, called a *Merkle tree hash*, has the advantage that, if one explicitly stores $\\text{Hash}(h')$ along with each node $h'$ (resulting in a structure called a *Merkle tree*, or, in our case, a *Merkle–Patricia tree*), one needs to recompute only at most $n$ hashes when an element is added to, deleted from or changed in the hashmap.\n\nIn this way, if one represents the global blockchain state by a suitable Merkle tree hash, it is easy to recompute this state hash after each transaction.\n\n#### 2.3.10. Merkle proofs\n\nUnder the assumption ([7](#2-2-9-hash-assumption)) of \"injectivity\" of the chosen hash function $\\texttt{Hash}$, one can construct a proof that, for a given value $z$ of $\\texttt{Hash}(h)$, $h:\\mathit{Hashmap}(n,X)$, one has $\\mathit{hget}(h)(i)=x$ for some $i:\\mathbf{2}^n$ and $x:X$. Such a proof will consist of the path in the Merkle–Patricia tree from the leaf corresponding to $i$ to the root, augmented by the hashes of all siblings of all nodes occurring on this path.\n\nIn this way, a light node<sup>[6](#fn6)</sup> knowing only the value of $\\text{Hash}(h)$ for some hashmap $h$ (e.g., smart-contract persistent storage or global blockchain state) might request from a full node<sup>[7](#fn7)</sup> not only the value $x=h[i]=\\mathit{hget}(h)(i)$, but such a value along with a Merkle proof starting from the already known value $\\text{Hash}(h)$. Then, under assumption ([7](#2-2-9-hash-assumption)), the light node can check for itself that $x$ is indeed the correct value of $h[i]$.\n\nIn some cases, the client may want to obtain the value $y=\\text{Hash}(x)=\\text{Hash}(h[i])$ instead—for example, if $x$ itself is very large (e.g., a hashmap itself). Then a Merkle proof for $(i,y)$ can be provided instead. If $x$ is a hashmap as well, then a second Merkle proof starting from $y=\\text{Hash}(x)$ may be obtained from a full node, to provide a value $x[j]=h[i][j]$ or just its hash.\n\n#### 2.3.11. Importance of Merkle proofs for a multi-chain system such as TON\n\nNotice that a node normally cannot be a full node for all shardchains existing in the TON environment. It usually is a full node only for some shardchains—for instance, those containing its own account, a smart contract it is interested in, or those that this node has been assigned to be a validator of. For other shardchains, it must be a light node—otherwise the storage, computing and network bandwidth requirements would be prohibitive. This means that such a node cannot directly check assertions about the state of other shardchains; it must rely on Merkle proofs obtained from full nodes for those shardchains, which is as safe as checking by itself unless ([7](#2-2-9-hash-assumption)) fails (i.e., a hash collision is found)\n\n#### 2.3.12. Peculiarities of TON VM\n\nThe TON VM or TVM (TON Virtual Machine), used to run smart contracts in the masterchain and Workchain Zero, is considerably different from customary designs inspired by the EVM (Ethereum Virtual Machine): it works not just with 256-bit integers, but actually with (almost) arbitrary records, structures, or sum-product types, making it more suitable to execute code written in high-level (especially functional) languages. Essentially, TVM uses tagged data types, not unlike those used in implementations of Prolog or Erlang.\n\nOne might imagine first that the state of a TVM smart contract is not just a hashmap $\\mathbf{2}^{256}\\to \\mathbf{2}^{256}$, or $\\mathit{Hashmap}(256,\\mathbf{2}^{256})$, but (as a first step) $\\mathit{Hashmap}(256,X)$, where $X$ is a type with several constructors, enabling it to store, apart from 256-bit integers, other data structures, including other hashmaps $\\mathit{Hashmap}(256,X)$ in particular. This would mean that a cell of TVM (persistent or temporary) storage—or a variable or an element of an array in a TVM smart-contract code—may contain not only an integer, but a whole new hashmap. Of course, this would mean that a cell contains not just 256 bits, but also, say, an 8-bit tag, describing how these 256 bits should be interpreted.\n\nIn fact, values do not need to be precisely 256-bit. The value format used by TVM consists of a sequence of raw bytes and references to other structures, mixed in arbitrary order, with some descriptor bytes inserted in suitable locations to be able to distinguish pointers from raw data (e.g., strings or integers); cf. [2.3.14](#2-3-14-tvm-cells).\n\nThis raw value format may be used to implement arbitrary sum-product algebraic types. In this case, the value would contain a raw byte first, describing the constructor being used (from the perspective of a high-level language), and then other fields or constructor arguments, consisting of raw bytes and references to other structures depending on the constructor chosen (cf. [2.2.5](#2-2-5-tl%2C-or-the-type-language)). However, TVM does not know anything about the correspondence between constructors and their arguments; the mixture of bytes and references is explicitly described by certain descriptor bytes.<sup>[8](#fn8)</sup>\n\nThe Merkle tree hashing is extended to arbitrary such structures: to compute the hash of such a structure, all references are recursively replaced by hashes of objects referred to, and then the hash of the resulting byte string (descriptor bytes included) is computed.\n\nIn this way, the Merkle tree hashing for hashmaps, described in [2.3.8](#2-3-8-merkle-patricia-trees), is just a special case of hashing for arbitrary (dependent) algebraic data types, applied to type $Hashmap(n, X)$ with two constructors.<sup>[9](#fn9)</sup>\n\n#### 2.3.13. Persistent storage of TON smart contracts\n\nPersistent storage of a TON smart contract essentially consists of its \"global variables\", preserved between calls to the smart contract. As such, it is just a \"product\", \"tuple\", or \"record\" type, consisting of fields of the correct types, corresponding to one global variable each. If there are too many global variables, they cannot fit into one TON cell because of the global restriction on TON cell size. In such a case, they are split into several records and organized into a tree, essentially becoming a \"product of products\" or \"product of products of products\" type instead of just a product type.\n\n#### 2.3.14. TVM Cells\n\nUltimately, the TON VM keeps all data in a collection of *(TVM) cells*. Each cell contains two descriptor bytes first, indicating how many bytes of raw data are present in this cell (up to 128) and how many references to other cells are present (up to four). Then these raw data bytes and references follow. Each cell is referenced exactly once, so we might have included in each cell a reference to its \"parent\" (the only cell referencing this one). However, this reference need not be explicit.\n\nIn this way, the persistent data storage cells of a TON smart contract are organized into a tree,<sup>[10](#fn10)</sup> with a reference to the root of this tree kept in the smart-contract description. If necessary, a Merkle tree hash of this entire persistent storage is recursively computed, starting from the leaves and then simply replacing all references in a cell with the recursively computed hashes of the referenced cells, and subsequently computing the hash of the byte string thus obtained.\n\n#### 2.3.15. Generalized Merkle proofs for values of arbitrary algebraic types\n\nBecause the TON VM represents a value of arbitrary algebraic type by means of a tree consisting of (TVM) cells, and each cell has a well-defined (recursively computed) Merkle hash, depending in fact on the whole subtree rooted in this cell, we can provide \"generalized Merkle proofs\" for (parts of) values of arbitrary algebraic types, intended to prove that a certain subtree of a tree with a known Merkle hash takes a specific value or a value with a specific hash. This generalizes the approach of [2.3.10](#2-3-10-merkle-proofs), where only Merkle proofs for $x[i]=y$ have been considered.\n\n#### 2.3.16. Support for sharding in TON VM data structures\n\nWe have just outlined how the TON VM, without being overly complicated, supports arbitrary (dependent) algebraic data types in high-level smart-contract languages. However, sharding of large (or global) smart contracts requires special support on the level of TON VM. To this end, a special version of the hashmap type has been added to the system, amounting to a \"map\" $\\mathit{Account}\\dashrightarrow X$. This \"map\" might seem equivalent to $\\mathit{Hashmap}(m,X)$, where $\\mathit{Account}=\\mathbf{2}^m$. However, when a shard is split in two, or two shards are merged, such hashmaps are automatically split in two, or merged back, so as to keep only those keys that belong to the corresponding shard.\n\n#### 2.3.17. Payment for persistent storage\n\nA noteworthy feature of the TON Blockchain is the payment exacted from smart contracts for storing their persistent data (i.e., for enlarging the total state of the blockchain). It works as follows:\n\nEach block declares two rates, nominated in the principal currency of the blockchain (usually the Gram): the price for keeping one cell in the persistent storage, and the price for keeping one raw byte in some cell of the persistent storage. Statistics on the total numbers of cells and bytes used by each account are stored as part of its state, so by multiplying these numbers by the two rates declared in the block header, we can compute the payment to be deducted from the account balance for keeping its data between the previous block and the current one.\n\nHowever, payment for persistent storage usage is not exacted for every account and smart contract in each block; instead, the sequence number of the block where this payment was last exacted is stored in the account data, and when any action is done with the account (e.g., a value transfer or a message is received and processed by a smart contract), the storage usage payment for all blocks since the previous such payment is deducted from the account balance before performing any further actions. If the account's balance would become negative after this, the account is destroyed.\n\nA workchain may declare some number of raw data bytes per account to be \"free\" (i.e., not participating in the persistent storage payments) in order to make \"simple\" accounts, which keep only their balance in one or two cryptocurrencies, exempt from these constant payments.\n\nNotice that, if nobody sends any messages to an account, its persistent storage payments are not collected, and it can exist indefinitely. However, anybody can send, for instance, an empty message to destroy such an account. A small incentive, collected from part of the original balance of the account to be destroyed, can be given to the sender of such a message. We expect, however, that the validators would destroy such insolvent accounts for free, simply to decrease the global blockchain state size and to avoid keeping large amounts of data without compensation.\n\nPayments collected for keeping persistent data are distributed among the validators of the shardchain or the masterchain (proportionally to their stakes in the latter case).\n\n#### 2.3.18. Local and global smart contracts; smart-contract instances\n\nA smart contract normally resides just in one shard, selected according to the smart contract's $account\\_id$, similarly to an \"ordinary\" account. This is usually sufficient for most applications. However, some \"high-load\" smart contracts may want to have an \"instance\" in each shardchain of some workchain. To achieve this, they must propagate their creating transaction into all shardchains, for instance, by committing this transaction into the \"root\" shardchain $(w,\\emptyset)$<sup>[11](#fn11)</sup> of the workchain $w$ and paying a large commission.<sup>[12](#fn12)</sup>\n\nThis action effectively creates instances of the smart contract in each shard, with separate balances. Originally, the balance transferred in the creating transaction is distributed simply by giving the instance in shard $(w,s)$ the $2^{-|s|}$ part of the total balance. When a shard splits into two child shards, balances of all instances of global smart contracts are split in half; when two shards merge, balances are added together.\n\nIn some cases, splitting/merging instances of global smart contracts may involve (delayed) execution of special methods of these smart contracts. By default, the balances are split and merged as described above, and some special \"account-indexed\" hashmaps are also automatically split and merged (cf. [2.3.16](#2-3-16-support-for-sharding-in-ton-vm-data-structures)).\n\n#### 2.3.19. Limiting splitting of smart contracts\n\nA global smart contract may limit its splitting depth $d$ upon its creation, in order to make persistent storage expenses more predictable. This means that, if shardchain $(w,s)$ with $|s|\\geq d$ splits in two, only one of two new shardchains inherits an instance of the smart contract. This shardchain is chosen deterministically: each global smart contract has some \"$account\\_id$\", which is essentially the hash of its creating transaction, and its instances have the same $account\\_id$ with the first $\\leq d$ bits replaced by suitable values needed to fall into the correct shard. This $account\\_id$ selects which shard will inherit the smart-contract instance after splitting.\n\n#### 2.3.20. Account/Smart-contract state\n\nWe can summarize all of the above to conclude that an account or smart-contract state consists of the following:\n\n- A balance in the principal currency of the blockchain\n- A balance in other currencies of the blockchain\n- Smart-contract code (or its hash)\n- Smart-contract persistent data (or its Merkle hash)\n- Statistics on the number of persistent storage cells and raw bytes used\n- The last time (actually, the masterchain block number) when payment for smart-contract persistent storage was collected\n- The public key needed to transfer currency and send messages from this account (optional; by default equal to $account\\_id$ itself). In some cases, more sophisticated signature checking code may be located here, similar to what is done for Bitcoin transaction outputs; then the $account\\_id$ will be equal to the hash of this code.\n\nWe also need to keep somewhere, either in the account state or in some other account-indexed hashmap, the following data:\n\n- The output message queue of the account (cf. [2.4.17](#2-4-17-output-queues))\n- The collection of (hashes of) recently delivered messages (cf. [2.4.23](#2-4-23-preventing-double-delivery-of-messages))\n\nNot all of these are really required for every account; for example, smart-contract code is needed only for smart contracts, but not for \"simple\" accounts. Furthermore, while any account must have a non-zero balance in the principal currency (e.g., Grams for the masterchain and shardchains of the basic workchain), it may have balances of zero in other currencies. In order to avoid keeping unused data, a sum-product type (depending on the workchain) is defined (during the workchain's creation), which uses different tag bytes (e.g., TL constructors; cf. [2.2.5](#2-2-5-tl-or-the-type-language)) to distinguish between different \"constructors\" used. Ultimately, the account state is itself kept as a collection of cells of the TVM persistent storage.\n\n---\n\n### 2.4  Messages Between Shardchains\n\nAn important component of the TON Blockchain is the *messaging system* between blockchains. These blockchains may be shardchains of the same workchain, or of different workchains.\n\n#### 2.4.1. Messages, accounts and transactions: a bird's eye view of the system\n\n*Messages* are sent from one account to another. Each *transaction* consists of an account receiving one message, changing its state according to certain rules, and generating several (maybe one or zero) new messages to other accounts. Each message is generated and received (delivered) exactly once.\n\nThis means that messages play a fundamental role in the system, comparable to that of accounts (smart contracts). From the perspective of the Infinite Sharding Paradigm (cf. [2.1.2](#2-1-2-infinite-sharding-paradigm)), each account resides in its separate \"account-chain\", and the only way it can affect the state of some other account is by sending a message.\n\n#### 2.4.2. Accounts as processes or actors; Actor model\n\nOne might think about accounts (and smart contracts) as \"processes\", or \"actors\", that are able to process incoming messages, change their internal state and generate some outbound messages as a result. This is closely related to the so-called *Actor model*, used in languages such as Erlang (however, actors in Erlang are usually called \"processes\"). Since new actors (i.e., smart contracts) are also allowed to be created by existing actors as a result of processing an inbound message, the correspondence with the Actor model is essentially complete.\n\n#### 2.4.3. Message recipient\n\nAny message has its *recipient*, characterized by the *target workchain identifier $w$* (assumed by default to be the same as that of the originating shardchain), and the *recipient account $account\\_id$*. The exact format (i.e., number of bits) of $account\\_id$ depends on $w$; however, the shard is always determined by its first (most significant) 64 bits.\n\n#### 2.4.4. Message sender\n\nIn most cases, a message has a *sender*, characterized again by a $(w',\\mathit{account\\_id}')$ pair. If present, it is located after the message recipient and message value. Sometimes, the sender is unimportant or it is somebody outside the blockchain (i.e., not a smart contract), in which case this field is absent.\n\nNotice that the Actor model does not require the messages to have an implicit sender. Instead, messages may contain a reference to the Actor to which an answer to the request should be sent; usually it coincides with the sender. However, it is useful to have an explicit unforgeable sender field in a message in a cryptocurrency (Byzantine) environment.\n\n#### 2.4.5. Message value\n\nAnother important characteristic of a message is its attached *value*, in one or several cryptocurrencies supported both by the source and by the target workchain. The value of the message is indicated at its very beginning immediately after the message recipient; it is essentially a list of $(currency\\_id, value)$ pairs.\n\nNotice that \"simple\" value transfers between \"simple\" accounts are just empty (no-op) messages with some value attached to them. On the other hand, a slightly more complicated message body might contain a simple text or binary comment (e.g., about the purpose of the payment).\n\n#### 2.4.6. External messages, or \"messages from nowhere\"\n\nSome messages arrive into the system \"from nowhere\"—that is, they are not generated by an account (smart contract or not) residing in the blockchain. The most typical example arises when a user wants to transfer some funds from an account controlled by her to some other account. In this case, the user sends a \"message from nowhere\" to her own account, requesting it to generate a message to the receiving account, carrying the specified value. If this message is correctly signed, her account receives it and generates the required outbound messages.\n\nIn fact, one might consider a \"simple\" account as a special case of a smart contract with predefined code. This smart contract receives only one type of message. Such an inbound message must contain a list of outbound messages to be generated as a result of delivering (processing) the inbound message, along with a signature. The smart contract checks the signature, and, if it is correct, generates the required messages.\n\nOf course, there is a difference between \"messages from nowhere\" and normal messages, because the \"messages from nowhere\" cannot bear value, so they cannot pay for their \"gas\" (i.e., their processing) themselves. Instead, they are tentatively executed with a small gas limit before even being suggested for inclusion in a new shardchain block; if the execution fails (the signature is incorrect), the \"message from nowhere\" is deemed incorrect and is discarded. If the execution does not fail within the small gas limit, the message may be included in a new shardchain block and processed completely, with the payment for the gas (processing capacity) consumed exacted from the receiver's account. \"Messages from nowhere\" can also define some transaction fee which is deducted from the receiver's account on top of the gas payment for redistribution to the validators.\n\nIn this sense, \"messages from nowhere\" or \"external messages\" take the role of transaction candidates used in other blockchain systems (e.g., Bitcoin and Ethereum).\n\n#### 2.4.7. Log messages, or \"messages to nowhere\"\n\nSimilarly, sometimes a special message can be generated and routed to a specific shardchain not to be delivered to its recipient, but to be logged in order to be easily observable by anybody receiving updates about the shard in question. These logged messages may be output in a user's console, or trigger an execution of some script on an off-chain server. In this sense, they represent the external \"output\" of the \"blockchain supercomputer\", just as the \"messages from nowhere\" represent the external \"input\" of the \"blockchain supercomputer\".\n\n#### 2.4.8. Interaction with off-chain services and external blockchains\n\nThese external input and output messages can be used for interacting with off-chain services and other (external) blockchains, such as Bitcoin or Ethereum. One might create tokens or cryptocurrencies inside the TON Blockchain pegged to Bitcoins, Ethers or any ERC-20 tokens defined in the Ethereum blockchain, and use \"messages from nowhere\" and \"messages to nowhere\", generated and processed by scripts residing on some third-party off-chain servers, to implement the necessary interaction between the TON Blockchain and these external blockchains.\n\n#### 2.4.9. Message body\n\nThe *message body* is simply a sequence of bytes, the meaning of which is determined only by the receiving workchain and/or smart contract. For blockchains using TON VM, this could be the serialization of any TVM cell, generated automatically via the `Send()` operation. Such a serialization is obtained simply by recursively replacing all references in a TON VM cell with the cells referred to. Ultimately, a string of raw bytes appears, which is usually prepended by a 4-byte \"message type\" or \"message constructor\", used to select the correct method of the receiving smart contract.\n\nAnother option would be to use TL-serialized objects (cf. [2.2.5](#2-2-5-tl-or-the-type-language)) as message bodies. This might be especially useful for communication between different workchains, one or both of which are not necessarily using the TON VM.\n\n#### 2.4.10. Gas limit and other workchain/VM-specific parameters\n\nSometimes a message needs to carry information about the gas limit, the gas price, transaction fees and similar values that depend on the receiving workchain and are relevant only for the receiving workchain, but not necessarily for the originating workchain. Such parameters are included in or before the message body, sometimes (depending on the workchain) with special 4-byte prefixes indicating their presence (which can be defined by a TL-scheme; cf. [2.2.5](#2-2-5-tl-or-the-type-language)).\n\n#### 2.4.11. Creating messages: smart contracts and transactions\n\nThere are two sources of new messages. Most messages are created during smart-contract execution (via the `Send()` operation in TON VM), when some smart contract is invoked to process an incoming message. Alternatively, messages may come from the outside as \"external messages\" or \"messages from nowhere\" (cf. [2.4.6](#2-4-6-external-messages-or-messages-from-nowhere)).<sup>[13](#fn13)</sup>\n\n#### 2.4.12. Delivering messages\n\nWhen a message reaches the shardchain containing its destination account,<sup>[14](#fn14)</sup> it is \"delivered\" to its destination account. What happens next depends on the workchain; from an outside perspective, it is important that such a message can never be forwarded further from this shardchain.\n\nFor shardchains of the basic workchain, delivery consists in adding the message value (minus any gas payments) to the balance of the receiving account, and possibly in invoking a message-dependent method of the receiving smart contract afterwards, if the receiving account is a smart contract. In fact, a smart contract has only one entry point for processing all incoming messages, and it must distinguish between different types of messages by looking at their first few bytes (e.g., the first four bytes containing a TL constructor; cf. [2.2.5](#2-2-5-tl-or-the-type-language)).\n\n#### 2.4.13. Delivery of a message is a transaction\n\nBecause the delivery of a message changes the state of an account or smart contract, it is a special *transaction* in the receiving shardchain, and is explicitly registered as such. Essentially, *all* TON Blockchain transactions consist in the delivery of one inbound message to its receiving account (smart contract), neglecting some minor technical details.\n\n#### 2.4.14. Messages between instances of the same smart contract\n\nRecall that a smart contract may be *local* (i.e., residing in one shardchain as any ordinary account does) or *global* (i.e., having instances in all shards, or at least in all shards up to some known depth $d$; cf. [2.3.18](#2-3-18-local-and-global-smart-contracts-smart-contract-instances)). Instances of a global smart contract may exchange special messages to transfer information and value between each other if required. In this case, the (unforgeable) sender $account\\_id$ becomes important (cf. [2.4.4](#2-4-4-message-sender)).\n\n#### 2.4.15. Messages to any instance of a smart contract; wildcard addresses\n\nSometimes a message (e.g., a client request) needs be delivered to any instance of a global smart contract, usually the closest one (if there is one residing in the same shardchain as the sender, it is the obvious candidate). One way of doing this is by using a \"wildcard recipient address\", with the first $d$ bits of the destination $account\\_id$ allowed to take arbitrary values. In practice, one will usually set these $d$ bits to the same values as in the sender's $account\\_id$.\n\n#### 2.4.16. Input queue is absent\n\nAll messages received by a blockchain (usually a shardchain; sometimes the masterchain)—or, essentially, by an \"account-chain\" residing inside some shardchain—are immediately delivered (i.e., processed by the receiving account). Therefore, there is no \"input queue\" as such. Instead, if not all messages destined for a specific shardchain can be processed because of limitations on the total size of blocks and gas usage, some messages are simply left to accumulate in the output queues of the originating shardchains.\n\n#### 2.4.17. Output queues\n\nFrom the perspective of the Infinite Sharding Paradigm (cf. [2.1.2](#2-1-2-infinite-sharding-paradigm)), each account-chain (i.e., each account) has its own output queue, consisting of all messages it has generated, but not yet delivered to their recipients. Of course, account-chains have only a virtual existence; they are grouped into shardchains, and a shardchain has an output \"queue\", consisting of the union of the output queues of all accounts belonging to the shardchain.\n\nThis shardchain output \"queue\" imposes only partial order on its member messages. Namely, a message generated in a preceding block must be delivered before any message generated in a subsequent block, and any messages generated by the same account and having the same destination must be delivered in the order of their generation.\n\n#### 2.4.18. Reliable and fast inter-chain messaging\n\nIt is of paramount importance for a scalable multi-blockchain project such as TON to be able to forward and deliver messages between different shardchains (cf. [2.1.3](#2-1-3-messages-instant-hypercube-routing)), even if there are millions of them in the system. The messages should be delivered *reliably* (i.e., messages should not be lost or delivered more than once) and *quickly*. The TON Blockchain achieves this goal by using a combination of two \"message routing\" mechanisms.\n\n#### 2.4.19. Hypercube routing: \"slow path\" for messages with assured delivery\n\nThe TON Blockchain uses \"hypercube routing\" as a slow, but safe and reliable way of delivering messages from one shardchain to another, using several intermediate shardchains for transit if necessary. Otherwise, the validators of any given shardchain would need to keep track of the state of (the output queues of) all other shardchains, which would require prohibitive amounts of computing power and network bandwidth as the total quantity of shardchains grows, thus limiting the scalability of the system. Therefore, it is not possible to deliver messages directly from any shard to every other. Instead, each shard is \"connected\" only to shards differing in exactly one hexadecimal digit of their $(w,s)$ shard identifiers (cf. [2.1.8](#2-1-8-identification-of-shardchains)). In this way, all shardchains constitute a \"hypercube\" graph, and messages travel along the edges of this hypercube.\n\nIf a message is sent to a shard different from the current one, one of the hexadecimal digits (chosen deterministically) of the current shard identifier is replaced by the corresponding digit of the target shard, and the resulting identifier is used as the proximate target to forward the message to.<sup>[15](#fn15)</sup>\n\nThe main advantage of hypercube routing is that the block validity conditions imply that validators creating blocks of a shardchain must collect and process messages from the output queues of \"neighboring\" shardchains, on pain of losing their stakes. In this way, any message can be expected to reach its final destination sooner or later; a message cannot be lost in transit or delivered twice.\n\nNotice that hypercube routing introduces some additional delays and expenses, because of the necessity to forward messages through several intermediate shardchains. However, the number of these intermediate shardchains grows very slowly, as the logarithm $\\log N$ (more precisely, $\\lceil\\log_{16}N\\rceil-1$) of the total number of shardchains $N$. For example, if $N\\approx250$, there will be at most one intermediate hop; and for $N\\approx4000$ shardchains, at most two. With four intermediate hops, we can support up to one million shardchains. We think this is a very small price to pay for the essentially unlimited scalability of the system. In fact, it is not necessary to pay even this price:\n\n#### 2.4.20. Instant Hypercube Routing: \"fast path\" for messages\n\nA novel feature of the TON Blockchain is that it introduces a \"fast path\" for forwarding messages from one shardchain to any other, allowing in most cases to bypass the \"slow\" hypercube routing of [2.4.19](#2-4-19-hypercube-routing-slow-path-for-messages-with-assured-delivery) altogether and deliver the message into the very next block of the final destination shardchain.\n\nThe idea is as follows. During the \"slow\" hypercube routing, the message travels (in the network) along the edges of the hypercube, but it is delayed (for approximately five seconds) at each intermediate vertex to be committed into the corresponding shardchain before continuing its voyage.\n\nTo avoid unnecessary delays, one might instead relay the message along with a suitable Merkle proof along the edges of the hypercube, without waiting to commit it into the intermediate shardchains. In fact, the network message should be forwarded from the validators of the \"task group\" (cf. [2.6.8](#2-6-8-election-of-validator-task-groups)) of the original shard to the designated block producer (cf. [2.6.9](#2-6-9-rotating-priority-order-on-each-task-group)) of the \"task group\" of the destination shard; this might be done directly without going along the edges of the hypercube. When this message with the Merkle proof reaches the validators (more precisely, the collators; cf. [2.6.5](#2-6-5-collators-obtaining-money-by-suggesting-new-blocks-to-validators)) of the destination shardchain, they can commit it into a new block immediately, without waiting for the message to complete its travel along the \"slow path\". Then a confirmation of delivery along with a suitable Merkle proof is sent back along the hypercube edges, and it may be used to stop the travel of the message along the \"slow path\", by committing a special transaction.\n\nNote that this \"instant delivery\" mechanism does not replace the \"slow\" but failproof mechanism described in [2.4.19](#2-4-19-hypercube-routing-slow-path-for-messages-with-assured-delivery). The \"slow path\" is still needed because the validators cannot be punished for losing or simply deciding not to commit the \"fast path\" messages into new blocks of their blockchains.<sup>[16](#fn16)</sup>\n\nTherefore, both message forwarding methods are run in parallel, and the \"slow\" mechanism is aborted only if a proof of success of the \"fast\" mechanism is committed into an intermediate shardchain.<sup>[17](#fn17)</sup>\n\n#### 2.4.21. Collecting input messages from output queues of neighboring shardchains\n\nWhen a new block for a shardchain is proposed, some of the output messages of the neighboring (in the sense of the routing hypercube of [2.4.19](#2-4-19-hypercube-routing-slow-path-for-messages-with-assured-delivery)) shardchains are included in the new block as \"input\" messages and immediately delivered (i.e., processed). There are certain rules as to the order in which these neighbors' output messages must be processed. Essentially, an \"older\" message (coming from a shardchain block referring to an older masterchain block) must be delivered before any \"newer\" message; and for messages coming from the same neighboring shardchain, the partial order of the output queue described in [2.4.17](#2-4-17-output-queues) must be observed.\n\n#### 2.4.22. Deleting messages from output queues\n\nOnce an output queue message is observed as having been delivered by a neighboring shardchain, it is explicitly deleted from the output queue by a special transaction.\n\n#### 2.4.23. Preventing double delivery of messages\n\nTo prevent double delivery of messages taken from the output queues of the neighboring shardchains, each shardchain (more precisely, each account-chain inside it) keeps the collection of recently delivered messages (or just their hashes) as part of its state. When a delivered message is observed to be deleted from the output queue by its originating neighboring shardchain (cf. [2.4.22](#2-4-22-deleting-messages-from-output-queues)), it is deleted from the collection of recently delivered messages as well.\n\n#### 2.4.24. Forwarding messages intended for other shardchains\n\nHypercube routing (cf. [2.4.19](#2-4-19-hypercube-routing-slow-path-for-messages-with-assured-delivery)) means that sometimes outbound messages are delivered not to the shardchain containing the intended recipient, but to a neighboring shardchain lying on the hypercube path to the destination. In this case, \"delivery\" consists in moving the inbound message to the outbound queue. This is reflected explicitly in the block as a special *forwarding transaction*, containing the message itself. Essentially, this looks as if the message had been received by somebody inside the shardchain, and one identical message had been generated as result.\n\n#### 2.4.25. Payment for forwarding and keeping a message\n\nThe forwarding transaction actually spends some gas (depending on the size of the message being forwarded), so a gas payment is deducted from the value of the message being forwarded on behalf of the validators of this shardchain. This forwarding payment is normally considerably smaller than the gas payment exacted when the message is finally delivered to its recipient, even if the message has been forwarded several times because of hypercube routing. Furthermore, as long as a message is kept in the output queue of some shardchain, it is part of the shardchain's global state, so a payment for keeping global data for a long time may be also collected by special transactions.\n\n#### 2.4.26. Messages to and from the masterchain\n\nMessages can be sent directly from any shardchain to the masterchain, and vice versa. However, gas prices for sending messages to and for processing messages in the masterchain are quite high, so this ability will be used only when truly necessary—for example, by the validators to deposit their stakes. In some cases, a minimal deposit (attached value) for messages sent to the masterchain may be defined, which is returned only if the message is deemed \"valid\" by the receiving party.\n\nMessages cannot be automatically routed through the masterchain. A message with $\\mathit{workchain\\_id}\\neq-1$ ($-1$ being the special $\\mathit{workchain\\_id}$ indicating the masterchain) cannot be delivered to the masterchain.\n\nIn principle, one can create a message-forwarding smart contract inside the masterchain, but the price of using it would be prohibitive.\n\n#### 2.4.27. Messages between accounts in the same shardchain\n\nIn some cases, a message is generated by an account belonging to some shardchain, destined to another account in the same shardchain. For example, this happens in a new workchain which has not yet split into several shardchains because the load is manageable.\n\nSuch messages might be accumulated in the output queue of the shardchain and then processed as incoming messages in subsequent blocks (any shard is considered a neighbor of itself for this purpose). However, in most cases it is possible to deliver these messages within the originating block itself.\n\nIn order to achieve this, a partial order is imposed on all transactions included in a shardchain block, and the transactions (each consisting in the delivery of a message to some account) are processed respecting this partial order. In particular, a transaction is allowed to process some output message of a preceding transaction with respect to this partial order.\n\nIn this case, the message body is not copied twice. Instead, the originating and the processing transactions refer to a shared copy of the message.\n\n### 2.5  Global Shardchain State. \"Bag of Cells\" Philosophy\n\nNow we are ready to describe the global state of a TON blockchain, or at least of a shardchain of the basic workchain.\n\nWe start with a \"high-level\" or \"logical\" description, which consists in saying that the global state is a value of algebraic type $\\mathit{ShardchainState}$.\n\n#### 2.5.1. Shardchain state as a collection of account-chain states\n\nAccording to the Infinite Sharding Paradigm (cf. [2.1.2](#2-1-2-infinite-sharding-paradigm)), any shardchain is just a (temporary) collection of virtual \"account-chains\", containing exactly one account each. This means that, essentially, the global shardchain state must be a hashmap\n\n$$\n\\mathit{ShardchainState}:=(\\mathit{Account}\\dashrightarrow\\mathit{AccountState}) \\tag{23}\n$$\n\nwhere all $\\mathit{account\\_id}$ appearing as indices of this hashmap must begin with prefix $s$, if we are discussing the state of shard $(w,s)$ (cf. [2.1.8](#2-1-8-identification-of-shardchains)).\n\nIn practice, we might want to split $\\mathit{AccountState}$ into several parts (e.g., keep the account output message queue separate to simplify its examination by the neighboring shardchains), and have several hashmaps $(\\mathit{Account}\\dashrightarrow\\mathit{AccountStatePart}_i)$ inside the $\\mathit{ShardchainState}$. We might also add a small number of \"global\" or \"integral\" parameters to the $\\mathit{ShardchainState}$, (e.g., the total balance of all accounts belonging to this shard, or the total number of messages in all output queues).\n\nHowever, equation ([23](#2-5-1-shardchain-state-as-a-collection-of-account-chain-states)) is a good first approximation of what the shardchain global state looks like, at least from a \"logical\" (\"high-level\") perspective. The formal description of algebraic types $\\mathit{AccountState}$ and $\\mathit{ShardchainState}$ can be done with the aid of a TL-scheme (cf. [2.2.5](#2-2-5-tl-or-the-type-language)), to be provided elsewhere.\n\n#### 2.5.2. Splitting and merging shardchain states\n\nNotice that the Infinite Sharding Paradigm description of the shardchain state above shows how this state ([23](#2-5-1-shardchain-state-as-a-collection-of-account-chain-states)) should be processed when shards are split or merged. In fact, these state transformations turn out to be very simple operations with hashmaps.\n\n#### 2.5.3. Account-chain state\n\nThe (virtual) account-chain state is just the state of one account, described by type $\\mathit{AccountState}$. Usually it has all or some of the fields listed in [2.3.20](#2-3-20-account-smart-contract-state), depending on the specific constructor used.\n\n#### 2.5.4. Global workchain state\n\nSimilarly to ([23](#2-5-1-shardchain-state-as-a-collection-of-account-chain-states)) the shardchain state equation, we may define the global *workchain* state by the same formula, but with $\\mathit{account\\_id}$'s allowed to take any values, not just those belonging to one shard. Remarks similar to those made in [2.5.1](#2-5-1-shardchain-state-as-a-collection-of-account-chain-states) apply in this case as well: we might want to split this hashmap into several hashmaps, and we might want to add some \"integral\" parameters such as the total balance.\n\nEssentially, the global workchain state *must* be given by the same type $\\mathit{ShardchainState}$ as the shardchain state, because it is the shardchain state we would obtain if all existing shardchains of this workchain suddenly merged into one.\n\n#### 2.5.5. Low-level perspective: \"bag of cells\"\n\nThere is a \"low-level\" description of the account-chain or shardchain state as well, complementary to the \"high-level\" description given above. This description is quite important, because it turns out to be pretty universal, providing a common basis for representing, storing, serializing and transferring by network almost all data used by the TON Blockchain (blocks, shardchain states, smart-contract storage, Merkle proofs, etc.). At the same time, such a universal \"low-level\" description, once understood and implemented, allows us to concentrate our attention on the \"high-level\" considerations only.\n\nRecall that the TVM represents values of arbitrary algebraic types (including, for instance, $\\mathit{ShardchainState}$ of the shardchain state equation) by means of a tree of *TVM cells*, or *cells* for short (cf. [2.3.14](#2-3-14-tvm-cells) and [2.2.5](#2-2-5-tl-or-the-type-language)).\n\nAny such cell consists of two *descriptor bytes*, defining certain flags and values $0\\leq b\\leq 128$, the quantity of raw bytes, and $0\\leq c\\leq 4$, the quantity of references to other cells. Then $b$ raw bytes and $c$ cell references follow.<sup>[18](#fn18)</sup>\n\nThe exact format of cell references depends on the implementation and on whether the cell is located in RAM, on disk, in a network packet, in a block, and so on. A useful abstract model consists in imagining that all cells are kept in content-addressable memory, with the address of a cell equal to its (SHA-256) hash. Recall that the (Merkle) hash of a cell is computed exactly by replacing the references to its child cells by their (recursively computed) hashes and hashing the resulting byte string.\n\nIn this way, if we use cell hashes to reference cells (e.g., inside descriptions of other cells), the system simplifies somewhat, and the hash of a cell starts to coincide with the hash of the byte string representing it.\n\nNow we see that *any object representable by TVM, the global shardchain state included, can be represented as a \"bag of cells\"*—i.e., *a collection of cells along with a \"root\" reference to one of them* (e.g., by hash). Notice that duplicate cells are removed from this description (the \"bag of cells\" is a set of cells, not a multiset of cells), so the abstract tree representation might actually become a directed acyclic graph (dag) representation.\n\nOne might even keep this state on disk in a $B$- or $B+$-tree, containing all cells in question (maybe with some additional data, such as subtree height or reference counter), indexed by cell hash. However, a naive implementation of this idea would result in the state of one smart contract being scattered among distant parts of the disk file, something we would rather avoid.<sup>[19](#fn19)</sup>\n\nNow we are going to explain in some detail how almost all objects used by the TON Blockchain can be represented as \"bags of cells\", thus demonstrating the universality of this approach.\n\n#### 2.5.6. Shardchain block as a \"bag of cells\"\n\nA shardchain block itself can be also described by an algebraic type, and stored as a \"bag of cells\". Then a naive binary representation of the block may be obtained simply by concatenating the byte strings representing each of the cells in the \"bag of cells\", in arbitrary order. This representation might be improved and optimized, for instance, by providing a list of offsets of all cells at the beginning of the block, and replacing hash references to other cells with 32-bit indices in this list whenever possible. However, one should imagine that a block is essentially a \"bag of cells\", and all other technical details are just minor optimization and implementation issues.\n\n#### 2.5.7. Update to an object as a \"bag of cells\"\n\nImagine that we have an old version of some object represented as a \"bag of cells\", and that we want to represent a new version of the same object, supposedly not too different from the previous one. One might simply represent the new state as another \"bag of cells\" with its own root, *and remove from it all cells occurring in the old version*. The remaining \"bag of cells\" is essentially an *update* to the object. Everybody who has the old version of this object and the update can compute the new version, simply by uniting the two bags of cells, and removing the old root (decreasing its reference counter and de-allocating the cell if the reference counter becomes zero).\n\n#### 2.5.8. Updates to the state of an account\n\nIn particular, updates to the state of an account, or to the global state of a shardchain, or to any hashmap can be represented using the idea described in [2.5.7](#2-5-7-update-to-an-object-as-a-bag-of-cells). This means that when we receive a new shardchain block (which is a \"bag of cells\"), we interpret this \"bag of cells\" not just by itself, but by uniting it first with the \"bag of cells\" representing the previous state of the shardchain. In this sense each block may \"contain\" the whole state of the blockchain.\n\n#### 2.5.9. Updates to a block\n\nRecall that a block itself is a \"bag of cells\", so, if it becomes necessary to edit a block, one can similarly define a \"block update\" as a \"bag of cells\", interpreted in the presence of the \"bag of cells\" which is the previous version of this block. This is roughly the idea behind the \"vertical blocks\" discussed in [2.1.17](#2-1-17-correcting-invalid-shardchain-blocks).\n\n#### 2.5.10. Merkle proof as a \"bag of cells\"\n\nNotice that a (generalized) Merkle proof—for example, one asserting that $x[i]=y$ starting from a known value of $\\texttt{Hash}(x)=h$ (cf. [2.3.10](#2-3-10-merkle-proofs) and [2.3.15](#2-3-15-generalized-merkle-proofs-for-values-of-arbitrary-algebraic-types))—may also be represented as a \"bag of cells\". Namely, one simply needs to provide a subset of cells corresponding to a path from the root of $x:\\mathit{Hashmap}(n,X)$ to its desired leaf with index $i:\\mathbf{2}^n$ and value $y:X$. References to children of these cells not lying on this path will be left \"unresolved\" in this proof, represented by cell hashes. One can also provide a simultaneous Merkle proof of, say, $x[i]=y$ and $x[i']=y'$, by including in the \"bag of cells\" the cells lying on the union of the two paths from the root of $x$ to leaves corresponding to indices $i$ and $i'$.\n\n#### 2.5.11. Merkle proofs as query responses from full nodes\n\nIn essence, a full node with a complete copy of a shardchain (or account-chain) state can provide a Merkle proof when requested by a light node (e.g., a network node running a light version of the TON Blockchain client), enabling the receiver to perform some simple queries without external help, using only the cells provided in this Merkle proof. The light node can send its queries in a serialized format to the full node, and receive the correct answers with Merkle proofs—or just the Merkle proofs, because the requester should be able to compute the answers using only the cells included in the Merkle proof. This Merkle proof would consist simply of a \"bag of cells\", containing only those cells belonging to the shardchain's state that have been accessed by the full node while executing the light node's query. This approach can be used in particular for executing \"get queries\" of smart contracts (cf. [4.3.12](#4-3-12-tentative-execution-of-get-methods-of-smart-contracts)).\n\n#### 2.5.12. Augmented update, or state update with Merkle proof of validity\n\nRecall (cf. [2.5.7](#2-5-7-update-to-an-object-as-a-bag-of-cells)) that we can describe the changes in an object state from an old value $x:X$ to a new value $x':X$ by means of an \"update\", which is simply a \"bag of cells\", containing those cells that lie in the subtree representing new value $x'$, but not in the subtree representing old value $x$, because the receiver is assumed to have a copy of the old value $x$ and all its cells.\n\nHowever, if the receiver does not have a full copy of $x$, but knows only its (Merkle) hash $h=\\text{Hash}(x)$, it will not be able to check the validity of the update (i.e., that all \"dangling\" cell references in the update do refer to cells present in the tree of $x$). One would like to have \"verifiable\" updates, augmented by Merkle proofs of existence of all referred cells in the old state. Then anybody knowing only $h=\\text{Hash}(x)$ would be able to check the validity of the update and compute the new $h'=\\text{Hash}(x')$ by itself.\n\nBecause our Merkle proofs are \"bags of cells\" themselves (cf. [2.5.10](#2-5-10-merkle-proof-as-a-bag-of-cells)), one can construct such an *augmented update* as a \"bag of cells\", containing the old root of $x$, some of its descendants along with paths from the root of $x$ to them, and the new root of $x'$ and all its descendants that are not part of $x$.\n\n#### 2.5.13. Account state updates in a shardchain block\n\nIn particular, account state updates in a shardchain block should be augmented as discussed in [2.5.12](#2-5-12-augmented-update-or-state-update-with-merkle-proof-of-validity). Otherwise, somebody might commit a block containing an invalid state update, referring to a cell absent in the old state; proving the invalidity of such a block would be problematic (how is the challenger to prove that a cell is *not* part of the previous state?).\n\nNow, if all state updates included in a block are augmented, their validity is easily checked, and their invalidity is also easily shown as a violation of the recursive defining property of (generalized) Merkle hashes.\n\n#### 2.5.14. \"Everything is a bag of cells\" philosophy\n\nPrevious considerations show that everything we need to store or transfer, either in the TON Blockchain or in the network, is representable as a \"bag of cells\". This is an important part of the TON Blockchain design philosophy. Once the \"bag of cells\" approach is explained and some \"low-level\" serializations of \"bags of cells\" are defined, one can simply define everything (block format, shardchain and account state, etc.) on the high level of abstract (dependent) algebraic data types.\n\nThe unifying effect of the \"everything is a bag of cells\" philosophy considerably simplifies the implementation of seemingly unrelated services; cf. [5.1.9](#5-1-9-ton-vm-support-for-smart-payment-channels) for an example involving payment channels.\n\n#### 2.5.15. Block \"headers\" for TON blockchains\n\nUsually, a block in a blockchain begins with a small header, containing the hash of the previous block, its creation time, the Merkle hash of the tree of all transactions contained in the block, and so on. Then the block hash is defined to be the hash of this small block header. Because the block header ultimately depends on all data included in the block, one cannot alter the block without changing its hash.\n\nIn the \"bag of cells\" approach used by the blocks of TON blockchains, there is no designated block header. Instead, the block hash is defined as the (Merkle) hash of the root cell of the block. Therefore, the top (root) cell of the block might be considered a small \"header\" of this block.\n\nHowever, the root cell might not contain all the data usually expected from such a header. Essentially, one wants the header to contain some of the fields defined in the *Block* datatype. Normally, these fields will be contained in several cells, including the root. These are the cells that together constitute a \"Merkle proof\" for the values of the fields in question. One might insist that a block contain these \"header cells\" in the very beginning, before any other cells. Then one would need to download only the first several bytes of a block serialization in order to obtain all of the \"header cells\", and to learn all of the expected fields.\n\n---\n\n### 2.6   Creating and Validating New Blocks\n\nThe TON Blockchain ultimately consists of shardchain and masterchain blocks. These blocks must be created, validated and propagated through the network to all parties concerned, in order for the system to function smoothly and correctly.\n\n#### 2.6.1. Validators\n\nNew blocks are created and validated by special designated nodes, called *validators*. Essentially, any node wishing to become a validator may become one, provided it can deposit a sufficiently large stake (in TON coins, i.e., Grams; cf. [Appendix A](#appendix-a-the-ton-coin-or-the-gram)) into the masterchain. Validators obtain some \"rewards\" for good work, namely, the transaction, storage and gas fees from all transactions (messages) committed into newly generated blocks, and some newly minted coins, reflecting the \"gratitude\" of the whole community to the validators for keeping the TON Blockchain working. This income is distributed among all participating validators proportionally to their stakes.\n\nHowever, being a validator is a high responsibility. If a validator signs an invalid block, it can be punished by losing part or all of its stake, and by being temporarily or permanently excluded from the set of validators. If a validator does not participate in creating a block, it does not receive its share of the reward associated with that block. If a validator abstains from creating new blocks for a long time, it may lose part of its stake and be suspended or permanently excluded from the set of validators.\n\nAll this means that the validator does not get its money \"for nothing\". Indeed, it must keep track of the states of all or some shardchains (each validator is responsible for validating and creating new blocks in a certain subset of shardchains), perform all computations requested by smart contracts in these shardchains, receive updates about other shardchains and so on. This activity requires considerable disk space, computing power and network bandwidth.\n\n#### 2.6.2. Validators instead of miners\n\nRecall that the TON Blockchain uses the Proof-of-Stake approach, instead of the Proof-of-Work approach adopted by Bitcoin, the current version of Ethereum, and most other cryptocurrencies. This means that one cannot \"mine\" a new block by presenting some proof-of-work (computing a lot of otherwise useless hashes) and obtain some new coins as a result. Instead, one must become a validator and spend one's computing resources to store and process TON Blockchain requests and data. In short, *one must be a validator to mine new coins.* In this respect, *validators are the new miners.*\n\nHowever, there are some other ways to earn coins apart from being a validator.\n\n#### 2.6.3. Nominators and \"mining pools\"\n\nTo become a validator, one would normally need to buy and install several high-performance servers and acquire a good Internet connection for them. This is not so expensive as the ASIC equipment currently required to mine Bitcoins. However, one definitely cannot mine new TON coins on a home computer, let alone a smartphone.\n\nIn the Bitcoin, Ethereum and other Proof-of-Work cryptocurrency mining communities there is a notion of *mining pools*, where a lot of nodes, having insufficient computing power to mine new blocks by themselves, combine their efforts and share the reward afterwards.\n\nA corresponding notion in the Proof-of-Stake world is that of a *nominator*. Essentially, this is a node lending its money to help a validator increase its stake; the validator then distributes the corresponding share of its reward (or some previously agreed fraction of it—say, 50%) to the nominator.\n\nIn this way, a nominator can also take part in the \"mining\" and obtain some reward proportional to the amount of money it is willing to deposit for this purpose. It receives only a fraction of the corresponding share of the validator's reward, because it provides only the \"capital\", but does not need to buy computing power, storage and network bandwidth.\n\nHowever, if the validator loses its stake because of invalid behavior, the nominator loses its share of the stake as well. In this sense the nominator *shares the risk*. It must choose its nominated validator wisely, otherwise it can lose money. In this sense, nominators make a weighted decision and \"vote\" for certain validators with their funds.\n\nOn the other hand, this nominating or lending system enables one to become a validator without investing a large amount of money into Grams (TON coins) first. In other words, it prevents those keeping large amounts of Grams from monopolizing the supply of validators.\n\n#### 2.6.4. Fishermen: obtaining money by pointing out others' mistakes\n\nAnother way to obtain some rewards without being a validator is by becoming a *fisherman*. Essentially, any node can become a fisherman by making a small deposit in the masterchain. Then it can use special masterchain transactions to publish (Merkle) invalidity proofs of some (usually shardchain) blocks previously signed and published by validators. If other validators agree with this invalidity proof, the offending validators are punished (by losing part of their stake), and the fisherman obtains some reward (a fraction of coins confiscated from the offending validators). Afterwards, the invalid (shardchain) block must be corrected as outlined in [2.1.17](#2-1-17-correcting-invalid-shardchain-blocks). Correcting invalid masterchain blocks may involve creating \"vertical\" blocks on top of previously committed masterchain blocks (cf. [2.1.17](#2-1-17-correcting-invalid-shardchain-blocks)); there is no need to create a fork of the masterchain.\n\nNormally, a fisherman would need to become a full node for at least some shardchains, and spend some computing resources by running the code of at least some smart contracts. While a fisherman does not need to have as much computing power as a validator, we think that a natural candidate to become a fisherman is a would-be validator that is ready to process new blocks, but has not yet been elected as a validator (e.g., because of a failure to deposit a sufficiently large stake).\n\n#### 2.6.5. Collators: obtaining money by suggesting new blocks to validators\n\nYet another way to obtain some rewards without being a validator is by becoming a *collator*. This is a node that prepares and suggests to a validator new shardchain block candidates, complemented (collated) with data taken from the state of this shardchain and from other (usually neighboring) shardchains, along with suitable Merkle proofs. (This is necessary, for example, when some messages need to be forwarded from neighboring shardchains.) Then a validator can easily check the proposed block candidate for validity, without having to download the complete state of this or other shardchains.\n\nBecause a validator needs to submit new (collated) block candidates to obtain some (\"mining\") rewards, it makes sense to pay some part of the reward to a collator willing to provide suitable block candidates. In this way, a validator may free itself from the necessity of watching the state of the neighboring shardchains, by outsourcing it to a collator.\n\nHowever, we expect that during the system's initial deployment phase there will be no separate designated collators, because all validators will be able to act as collators for themselves.\n\n#### 2.6.6. Collators or validators: obtaining money for including user transactions\n\nUsers can open micropayment channels to some collators or validators and pay small amounts of coins in exchange for the inclusion of their transactions in the shardchain.\n\n#### 2.6.7. Global validator set election\n\nThe \"global\" set of validators is elected once each month (actually, every $2^{19}$ masterchain blocks). This set is determined and universally known one month in advance.\n\nIn order to become a validator, a node must transfer some TON coins (Grams) into the masterchain, and then send them to a special smart contract as its suggested stake $s$. Another parameter, sent along with the stake, is $l\\geq 1$, the maximum validating load this node is willing to accept relative to the minimal possible. There is also a global upper bound (another configurable parameter) $L$ on $l$, equal to, say, 10.\n\nThen the global set of validators is elected by this smart contract, simply by selecting up to $T$ candidates with maximal suggested stakes and publishing their identities. Originally, the total number of validators is $T=100$; we expect it to grow to 1000 as the load increases. It is a configurable parameter (cf. [2.1.21](#2-1-21-configurable-parameters)).\n\nThe actual stake of each validator is computed as follows: If the top $T$ proposed stakes are $s_1\\geq s_2\\geq\\cdots\\geq s_T$, the actual stake of $i$-th validator is set to $s'_i:=\\min(s_i,l_i\\cdot s_T)$. In this way, $s'_i/s'_T\\leq l_i$, so the $i$-th validator does not obtain more than $l_i\\leq L$ times the load of the weakest validator (because the load is ultimately proportional to the stake).\n\nThen elected validators may withdraw the unused part of their stake, $s_i-s'_i$. Unsuccessful validator candidates may withdraw all of their proposed stake.\n\nEach validator publishes its *public signing key*, not necessarily equal to the public key of the account the stake came from.<sup>[20](#fn20)</sup>\n\nThe stakes of the validators are frozen until the end of the period for which they have been elected, and one month more, in case new disputes arise (i.e., an invalid block signed by one of these validators is found). After that, the stake is returned, along with the validator's share of coins minted and fees from transactions processed during this time.\n\n#### 2.6.8. Election of validator \"task groups\"\n\nThe whole global set of validators (where each validator is considered present with multiplicity equal to its stake—otherwise a validator might be tempted to assume several identities and split its stake among them) is used only to validate new masterchain blocks. The shardchain blocks are validated only by specially selected subsets of validators, taken from the global set of validators chosen as described in [2.6.7](#2-6-7-global-validator-set-election).\n\nThese validator \"subsets\" or \"task groups\", defined for every shard, are rotated each hour (actually, every $2^{10}$ masterchain blocks), and they are known one hour in advance, so that every validator knows which shards it will need to validate, and can prepare for that (e.g., by downloading missing shardchain data).\n\nThe algorithm used to select validator task groups for each shard $(w,s)$ is deterministic pseudorandom. It uses pseudorandom numbers embedded by validators into each masterchain block (generated by a consensus using threshold signatures) to create a random seed, and then computes for example $\\text{Hash}(\\text{CODE}(w).\\text{CODE}(s).\\mathit{validator\\_id}.\\mathit{rand\\_seed})$ for each validator. Then validators are sorted by the value of this hash, and the first several are selected, so as to have at least $20/T$ of the total validator stakes and consist of at least 5 validators.\n\nThis selection could be done by a special smart contract. In that case, the selection algorithm would easily be upgradable without hard forks by the voting mechanism mentioned in [2.1.21](#2-1-21-configurable-parameters). All other \"constants\" mentioned so far (such as $2^{19}$, $2^{10}$, $T$, 20, and 5) are also configurable parameters.\n\n#### 2.6.9. Rotating priority order on each task group\n\nThere is a certain \"priority\" order imposed on the members of a shard task group, depending on the hash of the previous masterchain block and (shardchain) block sequence number. This order is determined by generating and sorting some hashes as described above.\n\nWhen a new shardchain block needs to be generated, the shard task group validator selected to create this block is normally the first one with respect to this rotating \"priority\" order. If it fails to create the block, the second or third validator may do it. Essentially, all of them may suggest their block candidates, but the candidate suggested by the validator having the highest priority should win as the result of Byzantine Fault Tolerant (BFT) consensus protocol.\n\n#### 2.6.10. Propagation of shardchain block candidates\n\nBecause shardchain task group membership is known one hour in advance, their members can use that time to build a dedicated \"shard validators multicast overlay network\", using the general mechanisms of the TON Network (cf. [3.3](#3-3-overlay-networks-and-multicasting-messages)). When a new shardchain block needs to be generated—normally one or two seconds after the most recent masterchain block has been propagated—everybody knows who has the highest priority to generate the next block (cf. [2.6.9](#2-6-9-rotating-priority-order-on-each-task-group)). This validator will create a new collated block candidate, either by itself or with the aid of a collator (cf. [2.6.5](#2-6-5-collators-obtaining-money-by-suggesting-new-blocks-to-validators)). The validator must check (validate) this block candidate (especially if it has been prepared by some collator) and sign it with its (validator) private key. Then the block candidate is propagated to the remainder of the task group using the prearranged multicast overlay network (the task group creates its own private overlay network as explained in [3.3](#3-3-overlay-networks-and-multicasting-messages), and then uses a version of the streaming multicast protocol described in [3.3.15](#3-3-15-streaming-broadcast-protocol) to propagate block candidates).\n\nA truly BFT way of doing this would be to use a Byzantine multicast protocol, such as the one used in Honey Badger BFT [[11]](#ref-11): encode the block candidate by an $(N,2N/3)$-erasure code, send $1/N$ of the resulting data directly to each member of the group, and expect them to multicast directly their part of the data to all other members of the group.\n\nHowever, a faster and more straightforward way of doing this (cf. also [3.3.15](#3-3-15-streaming-broadcast-protocol)) is to split the block candidate into a sequence of signed one-kilobyte blocks (\"chunks\"), augment their sequence by a Reed–Solomon or a fountain code (such as the RaptorQ code [[9]](#ref-9) [[14]](#ref-14)), and start transmitting chunks to the neighbors in the \"multicast mesh\" (i.e., the overlay network), expecting them to propagate these chunks further. Once a validator obtains enough chunks to reconstruct the block candidate from them, it signs a confirmation receipt and propagates it through its neighbors to the whole of the group. Then its neighbors stop sending new chunks to it, but may continue to send the (original) signatures of these chunks, believing that this node can generate the subsequent chunks by applying the Reed–Solomon or fountain code by itself (having all data necessary), combine them with signatures, and propagate to its neighbors that are not yet ready.\n\nIf the \"multicast mesh\" (overlay network) remains connected after removing all \"bad\" nodes (recall that up to one-third of nodes are allowed to be bad in a Byzantine way, i.e., behave in arbitrary malicious fashion), this algorithm will propagate the block candidate as quickly as possible.\n\nNot only the designated high-priority block creator may multicast its block candidate to the whole of the group. The second and third validator by priority may start multicasting their block candidates, either immediately or after failing to receive a block candidate from the top priority validator. However, normally only the block candidate with maximal priority will be signed by all (actually, by at least two-thirds of the task group) validators and committed as a new shardchain block.\n\n#### 2.6.11. Validation of block candidates\n\nOnce a block candidate is received by a validator and the signature of its originating validator is checked, the receiving validator checks the validity of this block candidate, by performing all transactions in it and checking that their result coincides with the one claimed. All messages imported from other blockchains must be supported by suitable Merkle proofs in the collated data, otherwise the block candidate is deemed invalid (and, if a proof of this is committed to the masterchain, the validators having already signed this block candidate may be punished). On the other hand, if the block candidate is found to be valid, the receiving validator signs it and propagates its signature to other validators in the group, either through the \"mesh multicast network\", or by direct network messages.\n\nWe would like to emphasize that *a validator does not need access to the states of this or neighboring shardchains in order to check the validity of a (collated) block candidate*.<sup>[21](#fn21)</sup> This allows the validation to proceed very quickly (without disk accesses), and lightens the computational and storage burden on the validators (especially if they are willing to accept the services of outside collators for creating block candidates).\n\n#### 2.6.12. Election of the next block candidate\n\nOnce a block candidate collects at least two-thirds (by stake) of the validity signatures of validators in the task group, it is eligible to be committed as the next shardchain block. A BFT protocol is run to achieve consensus on the block candidate chosen (there may be more than one proposed), with all \"good\" validators preferring the block candidate with the highest priority for this round. As a result of running this protocol, the block is augmented by signatures of at least two-thirds of the validators (by stake). These signatures testify not only to the validity of the block in question, but also to its being elected by the BFT protocol. After that, the block (without collated data) is combined with these signatures, serialized in a deterministic way, and propagated through the network to all parties concerned.\n\n#### 2.6.13. Validators must keep the blocks they have signed\n\nDuring their membership in the task group and for at least one hour (or rather $2^{10}$ blocks) afterward, the validators are expected to keep the blocks they have signed and committed. The failure to provide a signed block to other validators may be punished.\n\n#### 2.6.14. Propagating the headers and signatures of new shardchain blocks to all validators\n\nValidators propagate the headers and signatures of newly-generated shardchain blocks to the *global* set of validators, using a multicast mesh network similar to the one created for each task group.\n\n#### 2.6.15. Generation of new masterchain blocks\n\nAfter all (or almost all) new shardchain blocks have been generated, a new masterchain block may be generated. The procedure is essentially the same as for shardchain blocks (cf. [2.6.12](#2-6-12-election-of-the-next-block-candidate)), with the difference that *all* validators (or at least two-thirds of them) must participate in this process. Because the headers and signatures of new shardchain blocks are propagated to all validators, hashes of the newest blocks in each shardchain can and must be included in the new masterchain block. Once these hashes are committed into the masterchain block, outside observers and other shardchains may consider the new shardchain blocks committed and immutable (cf. [2.1.13](#2-1-13-using-the-masterchain-to-make-workchains-and-shardchains-tightly-coupled)).\n\n#### 2.6.16. Validators must keep the state of masterchain\n\nA noteworthy difference between the masterchain and the shardchains is that all validators are expected to keep track of the masterchain state, without relying on collated data. This is important because the knowledge of validator task groups is derived from the masterchain state.\n\n#### 2.6.17. Shardchain blocks are generated and propagated in parallel\n\nNormally, each validator is a member of several shardchain task groups; their quantity (hence the load on the validator) is approximately proportional to the validator's stake. This means that the validator runs several instances of new shardchain block generation protocol in parallel.\n\n#### 2.6.18. Mitigation of block retention attacks\n\nBecause the total set of validators inserts a new shardchain block's hash into the masterchain after having seen only its header and signatures, there is a small probability that the validators that have generated this block will conspire and try to avoid publishing the new block in its entirety. This would result in the inability of validators of neighboring shardchains to create new blocks, because they must know at least the output message queue of the new block, once its hash has been committed into the masterchain.\n\nIn order to mitigate this, the new block must collect signatures from some other validators (e.g., two-thirds of the union of task groups of neighboring shardchains) testifying that these validators do have copies of this block and are willing to send them to any other validators if required. Only after these signatures are presented may the new block's hash be included in the masterchain.\n\n#### 2.6.19. Masterchain blocks are generated later than shardchain blocks\n\nMasterchain blocks are generated approximately once every five seconds, as are shardchain blocks. However, while the generation of new blocks in all shardchains runs essentially at the same time (normally triggered by the release of a new masterchain block), the generation of new masterchain blocks is deliberately delayed, to allow the inclusion of hashes of newly-generated shardchain blocks in the masterchain.\n\n#### 2.6.20. Slow validators may receive lower rewards\n\nIf a validator is \"slow\", it may fail to validate new block candidates, and two-thirds of the signatures required to commit the new block may be gathered without its participation. In this case, it will receive a lower share of the reward associated with this block.\n\nThis provides an incentive for the validators to optimize their hardware, software, and network connection in order to process user transactions as fast as possible.\n\nHowever, if a validator fails to sign a block before it is committed, its signature may be included in one of the next blocks, and then a part of the reward (exponentially decreasing depending on how many blocks have been generated since—e.g., $0.9^k$ if the validator is $k$ blocks late) will be still given to this validator.\n\n#### 2.6.21. \"Depth\" of validator signatures\n\nNormally, when a validator signs a block, the signature testifies only to the *relative validity* of a block: this block is valid provided all previous blocks in this and other shardchains are valid. The validator cannot be punished for taking for granted invalid data committed into previous blocks.\n\nHowever, the validator signature of a block has an integer parameter called \"depth\". If it is non-zero, it means that the validator asserts the (relative) validity of the specified number of previous blocks as well. This is a way for \"slow\" or \"temporarily offline\" validators to catch up and sign some of the blocks that have been committed without their signatures. Then some part of the block reward will still be given to them (cf. [2.6.20](#2-6-20-slow-validators-may-receive-lower-rewards)).\n\n#### 2.6.22. Validators are responsible for *relative* validity of signed shardchain blocks; absolute validity follows\n\nWe would like to emphasize once again that a validator's signature on a shardchain block $B$ testifies to only the *relative* validity of that block (or maybe of $d$ previous blocks as well, if the signature has \"depth\" $d$, cf. [2.6.21](#2-6-21-depth-of-validator-signatures); but this does not affect the following discussion much). In other words, the validator asserts that the next state $s'$ of the shardchain is obtained from the previous state $s$ by applying the block evaluation function $\\mathit{ev\\_block}$ described in [2.2.6](#2-2-6-blocks-and-transactions-as-state-transformation-operators):\n\n$$\ns' = \\mathit{ev\\_block}(B)(s) \\tag{24}\n$$\n\nIn this way, the validator that signed block $B$ cannot be punished if the original state $s$ turns out to be \"incorrect\" (e.g., because of the invalidity of one of the previous blocks). A fisherman (cf. [2.6.4](#2-6-4-fishermen-obtaining-money-by-pointing-out-others-mistakes)) should complain only if it finds a block that is *relatively* invalid. The PoS system as a whole endeavors to make every block *relatively* valid, not *recursively (or absolutely)* valid. Notice, however, that *if all blocks in a blockchain are relatively valid, then all of them and the blockchain as a whole are absolutely valid*; this statement is easily shown using mathematical induction on the length of the blockchain. In this way, easily verifiable assertions of *relative* validity of blocks together demonstrate the much stronger *absolute validity* of the whole blockchain.\n\nNote that by signing a block $B$ the validator asserts that the block is valid given the original state $s$ (i.e., that the result of ([24](#2-6-22-validators-are-responsible-for-relative-validity-of-signed-shardchain-blocks%3B-absolute-validity-follows)) is not the value $\\bot$ indicating that the next state cannot be computed). In this way, the validator must perform minimal formal checks of the cells of the original state that are accessed during the evaluation of the ([24](#2-6-22-validators-are-responsible-for-relative-validity-of-signed-shardchain-blocks%3B-absolute-validity-follows)).\n\nFor example, imagine that the cell expected to contain the original balance of an account accessed from a transaction committed into a block turns out to have zero raw bytes instead of the expected 8 or 16. Then the original balance simply cannot be retrieved from the cell, and an \"unhandled exception\" happens while trying to process the block. In this case, the validator should not sign such a block on pain of being punished.\n\n#### 2.6.23. Signing masterchain blocks\n\nThe situation with the masterchain blocks is somewhat different: by signing a masterchain block, the validator asserts not only its relative validity, but also the relative validity of all preceding blocks up to the very first block when this validator assumed its responsibility (but not further back).\n\n#### 2.6.24. The total number of validators\n\nThe upper limit $T$ for the total number of validators to be elected (cf. [2.6.7](#2-6-7-global-validator-set-election)) cannot become, in the system described so far, more than, say, several hundred or a thousand, because all validators are expected to participate in a BFT consensus protocol to create each new masterchain block, and it is not clear whether such protocols can scale to thousands of participants. Even more importantly, masterchain blocks must collect the signatures of at least two-thirds of all the validators (by stake), and these signatures must be included in the new block (otherwise all other nodes in the system would have no reason to trust the new block without validating it by themselves). If more than, say, one thousand validator signatures would have to be included in each masterchain block, this would imply more data in each masterchain block, to be stored by all full nodes and propagated through the network, and more processing power spent to check these signatures (in a PoS system, full nodes do not need to validate blocks by themselves, but they need to check the validators' signatures instead).\n\nWhile limiting $T$ to a thousand validators seems more than sufficient for the first phase of the deployment of the TON Blockchain, a provision must be made for future growth, when the total number of shardchains becomes so large that several hundred validators will not suffice to process all of them. To this end, we introduce an additional configurable parameter $T'\\leq T$ (originally equal to $T$), and only the top $T'$ elected validators (by stake) are expected to create and sign new masterchain blocks.\n\n#### 2.6.25. Decentralization of the system\n\nOne might suspect that a Proof-of-Stake system such as the TON Blockchain, relying on $T\\approx1000$ validators to create all shardchain and masterchain blocks, is bound to become \"too centralized\", as opposed to conventional Proof-of-Work blockchains like Bitcoin or Ethereum, where everybody (in principle) might mine a new block, without an explicit upper limit on the total number of miners.\n\nHowever, popular Proof-of-Work blockchains, such as Bitcoin and Ethereum, currently require vast amounts of computing power (high \"hash rates\") to mine new blocks with non-negligible probability of success. Thus, the mining of new blocks tends to be concentrated in the hands of several large players, who invest huge amounts money into datacenters filled with custom-designed hardware optimized for mining; and in the hands of several large mining pools, which concentrate and coordinate the efforts of larger groups of people who are not able to provide a sufficient \"hash rate\" by themselves.\n\nTherefore, as of 2017, more than 75% of new Ethereum or Bitcoin blocks are produced by less than ten miners. In fact, the two largest Ethereum mining pools produce together more than half of all new blocks! Clearly, such a system is much more centralized than one relying on $T\\approx1000$ nodes to produce new blocks.\n\nOne might also note that the investment required to become a TON Blockchain validator—i.e., to buy the hardware (say, several high-performance servers) and the stake (which can be easily collected through a pool of nominators if necessary; cf. [2.6.3](#2-6-3-nominators-and-mining-pools))—is much lower than that required to become a successful stand-alone Bitcoin or Ethereum miner. In fact, the parameter $L$ of [2.6.7](#2-6-7-global-validator-set-election) will force nominators not to join the largest \"mining pool\" (i.e., the validator that has amassed the largest stake), but rather to look for smaller validators currently accepting funds from nominators, or even to create new validators, because this would allow a higher proportion $s'_i/s_i$ of the validator's—and by extension also the nominator's—stake to be used, hence yielding larger rewards from mining. In this way, the TON Proof-of-Stake system actually *encourages* decentralization (creating and using more validators) and *punishes* centralization.\n\n#### 2.6.26. Relative reliability of a block\n\nThe *(relative) reliability* of a block is simply the total stake of all validators that have signed this block. In other words, this is the amount of money certain actors would lose if this block turns out to be invalid. If one is concerned with transactions transferring value lower than the reliability of the block, one can consider them to be safe enough. In this sense, the relative reliability is a measure of trust an outside observer can have in a particular block.\n\nNote that we speak of the *relative* reliability of a block, because it is a guarantee that the block is valid *provided the previous block and all other shardchains' blocks referred to are valid* (cf. [2.6.22](#2-6-22-validators-are-responsible-for-relative-validity-of-signed-shardchain-blocks-absolute-validity-follows)).\n\nThe relative reliability of a block can grow after it is committed—for example, when belated validators' signatures are added (cf. [2.6.21](#2-6-21-depth-of-validator-signatures)). On the other hand, if one of these validators loses part or all of its stake because of its misbehavior related to some other blocks, the relative reliability of a block may *decrease*.\n\n#### 2.6.27. \"Strengthening\" the blockchain\n\nIt is important to provide incentives for validators to increase the relative reliability of blocks as much as possible. One way of doing this is by allocating a small reward to validators for adding signatures to blocks of other shardchains. Even \"would-be\" validators, who have deposited a stake insufficient to get into the top $T$ validators by stake and to be included in the global set of validators (cf. [2.6.7](#2-6-7-global-validator-set-election)), might participate in this activity (if they agree to keep their stake frozen instead of withdrawing it after having lost the election). Such would-be validators might double as fishermen (cf. [2.6.4](#2-6-4-fishermen-obtaining-money-by-pointing-out-others-mistakes)): if they have to check the validity of certain blocks anyway, they might as well opt to report invalid blocks and collect the associated rewards.\n\n#### 2.6.28. Recursive reliability of a block\n\nOne can also define the *recursive reliability* of a block to be the minimum of its relative reliability and the recursive reliabilities of all blocks it refers to (i.e., the masterchain block, the previous shardchain block, and some blocks of neighboring shardchains). In other words, if the block turns out to be invalid, either because it is invalid by itself or because one of the blocks it depends on is invalid, then at least this amount of money would be lost by someone. If one is truly unsure whether to trust a specific transaction in a block, one should compute the *recursive* reliability of this block, not just the *relative* one.\n\nIt does not make sense to go too far back when computing recursive reliability, because, if we look too far back, we will see blocks signed by validators whose stakes have already been unfrozen and withdrawn. In any case, we do not allow the validators to automatically reconsider blocks that are that old (i.e., created more than two months ago, if current values of configurable parameters are used), and create forks starting from them or correct them with the aid of \"vertical blockchains\" (cf. [2.1.17](#2-1-17-correcting-invalid-shardchain-blocks)), even if they turn out to be invalid. We assume that a period of two months provides ample opportunities for detecting and reporting any invalid blocks, so that if a block is not challenged during this period, it is unlikely to be challenged at all.\n\n#### 2.6.29. Consequence of Proof-of-Stake for light nodes\n\nAn important consequence of the Proof-of-Stake approach used by the TON Blockchain is that a light node (running light client software) for the TON Blockchain does not need to download the \"headers\" of all shardchain or even masterchain blocks in order to be able to check by itself the validity of Merkle proofs provided to it by full nodes as answers to its queries.\n\nIndeed, because the most recent shardchain block hashes are included in the masterchain blocks, a full node can easily provide a Merkle proof that a given shardchain block is valid starting from a known hash of a masterchain block. Next, the light node needs to know only the very first block of the masterchain (where the very first set of validators is announced), which (or at least the hash of which) might be built-in into the client software, and only one masterchain block approximately every month afterwards, where newly-elected validator sets are announced, because this block will have been signed by the previous set of validators. Starting from that, it can obtain the several most recent masterchain blocks, or at least their headers and validator signatures, and use them as a base for checking Merkle proofs provided by full nodes.\n\n---\n\n### 2.7   Splitting and Merging Shardchains\n\nOne of the most characteristic and unique features of the TON Blockchain is its ability to automatically split a shardchain in two when the load becomes too high, and merge them back if the load subsides (cf. [2.1.10](#2-1-10-dynamic-splitting-and-merging-of-shardchains)). We must discuss it in some detail because of its uniqueness and its importance to the scalability of the whole project.\n\n#### 2.7.1. Shard configuration\n\nRecall that, at any given moment of time, each workchain $w$ is split into one or several shardchains $(w,s)$ (cf. [2.1.8](#2-1-8-identification-of-shardchains)). These shardchains may be represented by leaves of a binary tree, with root $(w,\\emptyset)$, and each non-leaf node $(w,s)$ having children $(w,s.0)$ and $(w,s.1)$. In this way, every account belonging to workchain $w$ is assigned to exactly one shard, and everybody who knows the current shardchain configuration can determine the shard $(w,s)$ containing account $\\mathit{account\\_id}$: it is the only shard with binary string $s$ being a prefix of $\\mathit{account\\_id}$.\n\nThe shard configuration—i.e., this *shard binary tree*, or the collection of all active $(w,s)$ for a given $w$ (corresponding to the leaves of the shard binary tree)—is part of the masterchain state and is available to everybody who keeps track of the masterchain.<sup>[22](#fn22)</sup>\n\n#### 2.7.2. Most recent shard configuration and state\n\nRecall that hashes of the most recent shardchain blocks are included in each masterchain block. These hashes are organized in a shard binary tree (actually, a collection of trees, one for each workchain). In this way, each masterchain block contains the most recent shard configuration.\n\n#### 2.7.3. Announcing and performing changes in the shard configuration\n\nThe shard configuration may be changed in two ways: either a shard $(w,s)$ can be *split* into two shards $(w,s.0)$ and $(w,s.1)$, or two \"sibling\" shards $(w,s.0)$ and $(w,s.1)$ can be *merged* into one shard $(w,s)$.\n\nThese split/merge operations are announced several (e.g., $2^6$; this is a configurable parameter) blocks in advance, first in the \"headers\" of the corresponding shardchain blocks, and then in the masterchain block that refers to these shardchain blocks. This advance announcement is needed for all parties concerned to prepare for the planned change (e.g., build an overlay multicast network to distribute new blocks of the newly-created shardchains, as discussed in [3.3](#3-3-overlay-networks-and-multicasting-messages)). Then the change is committed, first into the (header of the) shardchain block (in case of a split; for a merge, blocks of both shardchains should commit the change), and then propagated to the masterchain block. In this way, the masterchain block defines not only the most recent shard configuration *before* its creation, but also the next immediate shard configuration.\n\n#### 2.7.4. Validator task groups for new shardchains\n\nRecall that each shard, i.e., each shardchain, normally is assigned a subset of validators (a validator task group) dedicated to creating and validating new blocks in the corresponding shardchain (cf. [2.6.8](#2-6-8-election-of-validator-task-groups)). These task groups are elected for some period of time (approximately one hour) and are known some time in advance (also approximately one hour), and are immutable during this period.<sup>[23](#fn23)</sup>\n\nHowever, the actual shard configuration may change during this period because of split/merge operations. One must assign task groups to newly created shards. This is done as follows:\n\nNotice that any active shard $(w,s)$ will either be a descendant of some uniquely determined original shard $(w,s')$, meaning that $s'$ is a prefix of $s$, or it will be the root of a subtree of original shards $(w,s')$, where $s$ will be a prefix of every $s'$. In the first case, we simply take the task group of the original shard $(w,s')$ to double as the task group of the new shard $(w,s)$. In the latter case, the task group of the new shard $(w,s)$ will be the union of task groups of all original shards $(w,s')$ that are descendants of $(w,s)$ in the shard tree.\n\nIn this way, every active shard $(w,s)$ gets assigned a well-defined subset of validators (task group). When a shard is split, both children inherit the whole of the task group from the original shard. When two shards are merged, their task groups are also merged.\n\nAnyone who keeps track of the masterchain state can compute validator task groups for each of the active shards.\n\n#### 2.7.5. Limit on split/merge operations during the period of responsibility of original task groups\n\nUltimately, the new shard configuration will be taken into account, and new dedicated validator subsets (task groups) will automatically be assigned to each shard. Before that happens, one must impose a certain limit on split/merge operations; otherwise, an original task group may end up validating $2^k$ shardchains for a large $k$ at the same time, if the original shard quickly splits into $2^k$ new shards.\n\nThis is achieved by imposing limits on how far the active shard configuration may be removed from the original shard configuration (the one used to select validator task groups currently in charge). For example, one might require that the distance in the shard tree from an active shard $(w,s)$ to an original shard $(w,s')$ must not exceed 3, if $s'$ is a predecessor of $s$ (i.e., $s'$ is a prefix of binary string $s$), and must not exceed 2, if $s'$ is a successor of $s$ (i.e., $s$ is a prefix of $s'$). Otherwise, the split or merge operation is not permitted.\n\nRoughly speaking, one is imposing a limit on the number of times a shard can be split (e.g., three) or merged (e.g., two) during the period of responsibility of a given collection of validator task groups. Apart from that, after a shard has been created by merging or splitting, it cannot be reconfigured for some period of time (some number of blocks).\n\n#### 2.7.6. Determining the necessity of split operations\n\nThe split operation for a shardchain is triggered by certain formal conditions (e.g., if for 64 consecutive blocks the shardchain blocks are at least 90% full). These conditions are monitored by the shardchain task group. If they are met, first a \"split preparation\" flag is included in the header of a new shardchain block (and propagated to the masterchain block referring to this shardchain block). Then, several blocks afterwards, the \"split commit\" flag is included in the header of the shardchain block (and propagated to the next masterchain block).\n\n#### 2.7.7. Performing split operations\n\nAfter the \"split commit\" flag is included in a block $B$ of shardchain $(w,s)$, there cannot be a subsequent block $B'$ in that shardchain. Instead, two blocks $B'_0$ and $B'_1$ of shardchains $(w,s.0)$ and $(w,s.1)$, respectively, will be created, both referring to block $B$ as their previous block (and both of them will indicate by a flag in the header that the shard has been just split). The next masterchain block will contain hashes of blocks $B'_0$ and $B'_1$ of the new shardchains; it is not allowed to contain the hash of a new block $B'$ of shardchain $(w,s)$, because a \"split commit\" event has already been committed into the previous masterchain block.\n\nNotice that both new shardchains will be validated by the same validator task group as the old one, so they will automatically have a copy of their state. The state splitting operation itself is quite simple from the perspective of the Infinite Sharding Paradigm (cf. [2.5.2](#2-5-2-splitting-and-merging-shardchain-states)).\n\n#### 2.7.8. Determining the necessity of merge operations\n\nThe necessity of shard merge operations is also detected by certain formal conditions (e.g., if for 64 consecutive blocks the sum of the sizes of the two blocks of sibling shardchains does not exceed 60% of maximal block size). These formal conditions should also take into account the total gas spent by these blocks and compare it to the current block gas limit, otherwise the blocks may happen to be small because there are some computation-intensive transactions that prevent the inclusion of more transactions.\n\nThese conditions are monitored by validator task groups of both sibling shards $(w,s.0)$ and $(w,s.1)$. Notice that siblings are necessarily neighbors with respect to hypercube routing (cf. [2.4.19](#2-4-19-hypercube-routing-slow-path-for-messages-with-assured-delivery)), so validators from the task group of any shard will be monitoring the sibling shard to some extent anyways.\n\nWhen these conditions are met, either one of the validator subgroups can suggest to the other that they merge by sending a special message. Then they combine into a provisional \"merged task group\", with combined membership, capable of running BFT consensus algorithms and of propagating block updates and block candidates if necessary.\n\nIf they reach consensus on the necessity and readiness of merging, \"merge prepare\" flags are committed into the headers of some blocks of each shardchain, along with the signatures of at least two-thirds of the validators of the sibling's task group (and are propagated to the next masterchain blocks, so that everybody can get ready for the imminent reconfiguration). However, they continue to create separate shardchain blocks for some predefined number of blocks.\n\n#### 2.7.9. Performing merge operations\n\nAfter that, when the validators from the union of the two original task groups are ready to become validators for the merged shardchain (this might involve a state transfer from the sibling shardchain and a state merge operation), they commit a \"merge commit\" flag in the headers of blocks of their shardchain (this event is propagated to the next masterchain blocks), and stop creating new blocks in separate shardchains (once the merge commit flag appears, creating blocks in separate shardchains is forbidden). Instead, a merged shardchain block is created (by the union of the two original task groups), referring to both of its \"preceding blocks\" in its \"header\". This is reflected in the next masterchain block, which will contain the hash of the newly created block of the merged shardchain. After that, the merged task group continues creating blocks in the merged shardchain.\n\n---\n\n### 2.8  Classification of Blockchain Projects\n\nWe will conclude our brief discussion of the TON Blockchain by comparing it with existing and proposed blockchain projects. Before doing this, however, we must introduce a sufficiently general classification of blockchain projects. The comparison of particular blockchain projects, based on this classification, is postponed until [2.9](#2-9-comparison-to-other-blockchain-projects).\n\n#### 2.8.1. Classification of blockchain projects\n\nAs a first step, we suggest some classification criteria for blockchains (i.e., for blockchain projects). Any such classification is somewhat incomplete and superficial, because it must ignore some of the most specific and unique features of the projects under consideration. However, we feel that this is a necessary first step in providing at least a very rough and approximate map of the blockchain projects territory.\n\nThe list of criteria we consider is the following:\n\n- Single-blockchain vs. multi-blockchain architecture (cf. [2.8.2](#2-8-2-single-blockchain-vs-multi-blockchain-projects))\n- Consensus algorithm: Proof-of-Stake vs. Proof-of-Work (cf. [2.8.3](#2-8-3-creating-and-validating-blocks-proof-of-work-vs-proof-of-stake))\n- For Proof-of-Stake systems, the exact block generation, validation and consensus algorithm used (the two principal options are DPOS vs. BFT; cf. [2.8.4](#2-8-4-variants-of-proof-of-stake-dpos-vs-bft))\n- Support for \"arbitrary\" (Turing-complete) smart contracts (cf. [2.8.6](#2-8-6-support-for-turing-complete-code-in-transactions))\n\nMulti-blockchain systems have additional classification criteria (cf. [2.8.7](#2-8-7-classification-of-multichain-systems)):\n\n- Type and rules of member blockchains: homogeneous, heterogeneous (cf. [2.8.8](#2-8-8-blockchain-types-homogeneous-and-heterogeneous-systems)), mixed (cf. [2.8.9](#2-8-9-mixed-heterogeneous-homogeneous-systems)). Confederations (cf. [2.8.10](#2-8-10-heterogeneous-systems-with-several-workchains-having-the-same-rules%2C-or-confederations)).\n- Absence or presence of a *masterchain*, internal or external (cf. [2.8.11](#2-8-11-presence-of-a-masterchain-external-or-internal))\n- Native support for sharding (cf. [2.8.12](#2-8-12-sharding-support)). Static or dynamic sharding (cf. [2.8.13](#2-8-13-dynamic-and-static-sharding)).\n- Interaction between member blockchains: loosely-coupled and tightly-coupled systems (cf. [2.8.14](#2-8-14-interaction-between-blockchains-loosely-coupled-and-tightly-coupled-systems))\n\n#### 2.8.2. Single-blockchain vs. multi-blockchain projects\n\nThe first classification criterion is the quantity of blockchains in the system. The oldest and simplest projects consist of a *single blockchain* (\"singlechain projects\" for short); more sophisticated projects use (or, rather, plan to use) *multiple blockchains* (\"multichain projects\").\n\nSinglechain projects are generally simpler and better tested; they have withstood the test of time. Their main drawback is low performance, or at least transaction throughput, which is on the level of ten (Bitcoin) to less than one hundred<sup>[24](#fn24)</sup> (Ethereum) transactions per second for general-purpose systems. Some specialized systems (such as Bitshares) are capable of processing tens of thousands of specialized transactions per second, at the expense of requiring the blockchain state to fit into memory, and limiting the processing to a predefined special set of transactions, which are then executed by highly-optimized code written in languages like C++ (no VMs here).\n\nMultichain projects promise the scalability everybody craves. They may support larger total states and more transactions per second, at the expense of making the project much more complex, and its implementation more challenging. As a result, there are few multichain projects already running, but most proposed projects are multichain. We believe that the future belongs to multichain projects.\n\n#### 2.8.3. Creating and validating blocks: Proof-of-Work vs. Proof-of-Stake\n\nAnother important distinction is the algorithm and protocol used to create and propagate new blocks, check their validity, and select one of several forks if they appear.\n\nThe two most common paradigms are *Proof-of-Work (PoW)* and *Proof-of-Stake (PoS)*. The Proof-of-Work approach usually allows any node to create (\"mine\") a new block (and obtain some reward associated with mining a block) if it is lucky enough to solve an otherwise useless computational problem (usually involving the computation of a large amount of hashes) before other competitors manage to do this. In the case of forks (for example, if two nodes publish two otherwise valid but different blocks to follow the previous one) the longest fork wins. In this way, the guarantee of immutability of the blockchain is based on the amount of *work* (computational resources) spent to generate the blockchain: anybody who would like to create a fork of this blockchain would need to re-do this work to create alternative versions of the already committed blocks. For this, one would need to control more than 50% of the total computing power spent creating new blocks, otherwise the alternative fork will have exponentially low chances of becoming the longest.\n\nThe Proof-of-Stake approach is based on large *stakes* (nominated in cryptocurrency) made by some special nodes (*validators*) to assert that they have checked (*validated*) some blocks and have found them correct. Validators sign blocks, and receive some small rewards for this; however, if a validator is ever caught signing an incorrect block, and a proof of this is presented, part or all of its stake is forfeit. In this way, the guarantee of validity and immutability of the blockchain is given by the total volume of stakes put by validators on the validity of the blockchain.\n\nThe Proof-of-Stake approach is more natural in the respect that it incentivizes the validators (which replace PoW miners) to perform useful computation (needed to check or create new blocks, in particular, by performing all transactions listed in a block) instead of computing otherwise useless hashes. In this way, validators would purchase hardware that is better adapted to processing user transactions, in order to receive rewards associated with these transactions, which seems quite a useful investment from the perspective of the system as a whole.\n\nHowever, Proof-of-Stake systems are somewhat more challenging to implement, because one must provide for many rare but possible conditions. For example, some malicious validators might conspire to disrupt the system to extract some profit (e.g., by altering their own cryptocurrency balances). This leads to some non-trivial game-theoretic problems.\n\nIn short, Proof-of-Stake is more natural and more promising, especially for multichain projects (because Proof-of-Work would require prohibitive amounts of computational resources if there are many blockchains), but must be more carefully thought out and implemented. Most currently running blockchain projects, especially the oldest ones (such as Bitcoin and at least the original Ethereum), use Proof-of-Work.\n\n#### 2.8.4. Variants of Proof-of-Stake. DPOS vs. BFT\n\nWhile Proof-of-Work algorithms are very similar to each other and differ mostly in the hash functions that must be computed for mining new blocks, there are more possibilities for Proof-of-Stake algorithms. They merit a sub-classification of their own.\n\nEssentially, one must answer the following questions about a Proof-of-Stake algorithm:\n\n- Who can produce (\"mine\") a new block—any full node, or only a member of a (relatively) small subset of validators? (Most PoS systems require new blocks to be generated and signed by one of several designated validators.)\n- Do validators guarantee the validity of the blocks by their signatures, or are all full nodes expected to validate all blocks by themselves? (Scalable PoS systems must rely on validator signatures instead of requiring all nodes to validate all blocks of all blockchains.)\n- Is there a designated producer for the next blockchain block, known in advance, such that nobody else can produce that block instead?\n- Is a newly-created block originally signed by only one validator (its producer), or must it collect a majority of validator signatures from the very beginning?\n\nWhile there seem to be $2^4$ possible classes of PoS algorithms depending on the answers to these questions, the distinction in practice boils down to two major approaches to PoS. In fact, most modern PoS algorithms, designed to be used in scalable multi-chain systems, answer the first two questions in the same fashion: only validators can produce new blocks, and they guarantee block validity without requiring all full nodes to check the validity of all blocks by themselves.\n\nAs to the two last questions, their answers turn out to be highly correlated, leaving essentially only two basic options:\n\n- *Delegated Proof-of-Stake (DPOS)*: There is a universally known designated producer for every block; no one else can produce that block; the new block is originally signed only by its producing validator.\n- *Byzantine Fault Tolerant (BFT)* PoS algorithms: There is a known subset of validators, any of which can suggest a new block; the choice of the actual next block among several suggested candidates, which must be validated and signed by a majority of validators before being released to the other nodes, is achieved by a version of Byzantine Fault Tolerant consensus protocol.\n\n#### 2.8.5. Comparison of DPOS and BFT PoS\n\nThe BFT approach has the advantage that a newly-produced block has *from the very beginning* the signatures of a majority of validators testifying to its validity. Another advantage is that, if a majority of validators executes the BFT consensus protocol correctly, no forks can appear at all. On the other hand, BFT algorithms tend to be quite convoluted and require more time for the subset of validators to reach consensus. Therefore, blocks cannot be generated too often. This is why we expect the TON Blockchain (which is a BFT project from the perspective of this classification) to produce a block only once every five seconds. In practice, this interval might be decreased to 2–3 seconds (though we do not promise this), but not further, if validators are spread across the globe.\n\nThe DPOS algorithm has the advantage of being quite simple and straightforward. It can generate new blocks quite often—say, once every two seconds, or maybe even once every second,<sup>[25](#fn25)</sup> because of its reliance on designated block producers known in advance.\n\nHowever, DPOS requires all nodes—or at least all validators—to validate all blocks received, because a validator producing and signing a new block confirms not only the *relative* validity of this block, but also the validity of the previous block it refers to, and all the blocks further back in the chain (maybe up to the beginning of the period of responsibility of the current subset of validators). There is a predetermined order on the current subset of validators, so that for each block there is a designated producer (i.e., validator expected to generate that block); these designated producers are rotated in a round-robin fashion. In this way, a block is at first signed only by its producing validator; then, when the next block is mined, and its producer chooses to refer to this block and not to one of its predecessors (otherwise its block would lie in a shorter chain, which might lose the \"longest fork\" competition in the future), the signature of the next block is essentially an additional signature on the previous block as well. In this way, a new block gradually collects the signatures of more validators—say, twenty signatures in the time needed to generate the next twenty blocks. A full node will either need to wait for these twenty signatures, or validate the block by itself, starting from a sufficiently confirmed block (say, twenty blocks back), which might be not so easy.\n\nThe obvious disadvantage of the DPOS algorithm is that a new block (and transactions committed into it) achieves the same level of trust (\"recursive reliability\" as discussed in [2.6.28](#2-6-28-recursive-reliability-of-a-block)) only after twenty more blocks are mined, compared to the BFT algorithms, which deliver this level of trust (say, twenty signatures) immediately. Another disadvantage is that DPOS uses the \"longest fork wins\" approach for switching to other forks; this makes forks quite probable if at least some producers fail to produce subsequent blocks after the one we are interested in (or we fail to observe these blocks because of a network partition or a sophisticated attack).\n\nWe believe that the BFT approach, while more sophisticated to implement and requiring longer time intervals between blocks than DPOS, is better adapted to \"tightly-coupled\" (cf. [2.8.14](#2-8-14-interaction-between-blockchains-loosely-coupled-and-tightly-coupled-systems)) multichain systems, because other blockchains can start acting almost immediately after seeing a committed transaction (e.g., generating a message intended for them) in a new block, without waiting for twenty confirmations of validity (i.e., the next twenty blocks), or waiting for the next six blocks to be sure that no forks appear and verifying the new block by themselves (verifying blocks of other blockchains may become prohibitive in a scalable multi-chain system). Thus they can achieve scalability while preserving high reliability and availability (cf. [2.8.12](#2-8-12-sharding-support)).\n\nOn the other hand, DPOS might be a good choice for a \"loosely-coupled\" multi-chain system, where fast interaction between blockchains is not required—e.g., if each blockchain (\"workchain\") represents a separate distributed exchange, and inter-blockchain interaction is limited to rare transfers of tokens from one workchain into another (or, rather, trading one altcoin residing in one workchain for another at a rate approaching $1:1$). This is what is actually done in the BitShares project, which uses DPOS quite successfully.\n\nTo summarize, while DPOS can *generate* new blocks and *include transactions* into them *faster* (with smaller intervals between blocks), these transactions reach the level of trust required to use them in other blockchains and off-chain applications as \"committed\" and \"immutable\" *much more slowly* than in the BFT systems—say, in thirty seconds<sup>[26](#fn26)</sup> instead of five. Faster transaction *inclusion* does not mean faster transaction *commitment*. This could become a huge problem if fast inter-blockchain interaction is required. In that case, one must abandon DPOS and opt for BFT PoS instead.\n\n#### 2.8.6. Support for Turing-complete code in transactions, i.e., essentially arbitrary smart contracts\n\nBlockchain projects normally collect some *transactions* in their blocks, which alter the blockchain state in a way deemed useful (e.g., transfer some amount of cryptocurrency from one account to another). Some blockchain projects might allow only some specific predefined types of transactions (such as value transfers from one account to another, provided correct signatures are presented). Others might support some limited form of scripting in the transactions. Finally, some blockchains support the execution of arbitrarily complex code in transactions, enabling the system (at least in principle) to support arbitrary applications, provided the performance of the system permits. This is usually associated with \"Turing-complete virtual machines and scripting languages\" (meaning that any program that can be written in any other computing language may be re-written to be performed inside the blockchain), and \"smart contracts\" (which are programs residing in the blockchain).\n\nOf course, support for arbitrary smart contracts makes the system truly flexible. On the other hand, this flexibility comes at a cost: the code of these smart contracts must be executed on some virtual machine, and this must be done every time for each transaction in the block when somebody wants to create or validate a block. This slows down the performance of the system compared to the case of a predefined and immutable set of types of simple transactions, which can be optimized by implementing their processing in a language such as C++ (instead of some virtual machine).\n\nUltimately, support for Turing-complete smart contracts seems to be desirable in any general-purpose blockchain project; otherwise, the designers of the blockchain project must decide in advance which applications their blockchain will be used for. In fact, the lack of support for smart contracts in the Bitcoin blockchain was the principal reason why a new blockchain project, Ethereum, had to be created.\n\nIn a (heterogeneous; cf. [2.8.8](#2-8-8-blockchain-types%3A-homogeneous-and-heterogeneous-systems)) multi-chain system, one might have \"the best of both worlds\" by supporting Turing-complete smart contracts in some blockchains (i.e., workchains), and a small predefined set of highly-optimized transactions in others.\n\n#### 2.8.7. Classification of multichain systems\n\nSo far, the classification was valid both for single-chain and multi-chain systems. However, multi-chain systems admit several more classification criteria, reflecting the relationship between the different blockchains in the system. We now discuss these criteria.\n\n#### 2.8.8. Blockchain types: homogeneous and heterogeneous systems\n\nIn a multi-chain system, all blockchains may be essentially of the same type and have the same rules (i.e., use the same format of transactions, the same virtual machine for executing smart-contract code, share the same cryptocurrency, and so on), and this similarity is explicitly exploited, but with different data in each blockchain. In this case, we say that the system is *homogeneous*. Otherwise, different blockchains (which will usually be called *workchains* in this case) can have different \"rules\". Then we say that the system is *heterogeneous*.\n\n#### 2.8.9. Mixed heterogeneous-homogeneous systems\n\nSometimes we have a mixed system, where there are several sets of types or rules for blockchains, but many blockchains with the same rules are present, and this fact is explicitly exploited. Then it is a mixed *heterogeneous-homogeneous system*. To our knowledge, the TON Blockchain is the only example of such a system.\n\n#### 2.8.10. Heterogeneous systems with several workchains having the same rules, or *confederations*\n\nIn some cases, several blockchains (workchains) with the same rules can be present in a heterogeneous system, but the interaction between them is the same as between blockchains with different rules (i.e., their similarity is not exploited explicitly). Even if they appear to use \"the same\" cryptocurrency, they in fact use different \"altcoins\" (independent incarnations of the cryptocurrency). Sometimes one can even have certain mechanisms to convert these altcoins at a rate near to $1:1$. However, this does not make the system homogeneous in our view; it remains heterogeneous. We say that such a heterogeneous collection of workchains with the same rules is a *confederation*.\n\nWhile making a heterogeneous system that allows one to create several workchains with the same rules (i.e., a confederation) may seem a cheap way of building a scalable system, this approach has a lot of drawbacks, too. Essentially, if someone hosts a large project in many workchains with the same rules, she does not obtain a large project, but rather a lot of small instances of this project. This is like having a chat application (or a game) that allows having at most 50 members in any chat (or game) room, but \"scales\" by creating new rooms to accommodate more users when necessary. As a result, a lot of users can participate in the chats or in the game, but can we say that such a system is truly scalable?\n\n#### 2.8.11. Presence of a masterchain, external or internal\n\nSometimes, a multi-chain project has a distinguished \"masterchain\" (sometimes called \"control blockchain\"), which is used, for example, to store the overall configuration of the system (the set of all active blockchains, or rather workchains), the current set of validators (for a Proof-of-Stake system), and so on. Sometimes other blockchains are \"bound\" to the masterchain, for example by committing the hashes of their latest blocks into it (this is something the TON Blockchain does, too).\n\nIn some cases, the masterchain is *external*, meaning that it is not a part of the project, but some other pre-existing blockchain, originally completely unrelated to its use by the new project and agnostic of it. For example, one can try to use the Ethereum blockchain as a masterchain for an external project, and publish special smart contracts into the Ethereum blockchain for this purpose (e.g., for electing and punishing validators).\n\n#### 2.8.12. Sharding support\n\nSome blockchain projects (or systems) have native support for *sharding*, meaning that several (necessarily homogeneous; cf. [2.8.8](#2-8-8-blockchain-types%3A-homogeneous-and-heterogeneous-systems)) blockchains are thought of as *shards* of a single (from a high-level perspective) virtual blockchain. For example, one can create 256 shard blockchains (\"shardchains\") with the same rules, and keep the state of an account in exactly one shard selected depending on the first byte of its $\\mathit{account\\_id}$.\n\nSharding is a natural approach to scaling blockchain systems, because, if it is properly implemented, users and smart contracts in the system need not be aware of the existence of sharding at all. In fact, one often wants to add sharding to an existing single-chain project (such as Ethereum) when the load becomes too high.\n\nAn alternative approach to scaling would be to use a \"confederation\" of heterogeneous workchains as described in [2.8.10](#2-8-10-heterogeneous-systems-with-several-workchains-having-the-same-rules%2C-or-confederations), allowing each user to keep her account in one or several workchains of her choice, and transfer funds from her account in one workchain to another workchain when necessary, essentially performing a $1:1$ altcoin exchange operation. The drawbacks of this approach have already been discussed in [2.8.10](#2-8-10-heterogeneous-systems-with-several-workchains-having-the-same-rules%2C-or-confederations).\n\nHowever, sharding is not so easy to implement in a fast and reliable fashion, because it implies a lot of messages between different shardchains. For example, if accounts are evenly distributed between $N$ shards, and the only transactions are simple fund transfers from one account to another, then only a small fraction ($1/N$) of all transactions will be performed within a single blockchain; almost all ($1-1/N$) transactions will involve two blockchains, requiring inter-blockchain communication. If we want these transactions to be fast, we need a fast system for transferring messages between shardchains. In other words, the blockchain project needs to be \"tightly-coupled\" in the sense described in [2.8.14](#2-8-14-interaction-between-blockchains-loosely-coupled-and-tightly-coupled-systems).\n\n#### 2.8.13. Dynamic and static sharding\n\nSharding might be *dynamic* (if additional shards are automatically created when necessary) or *static* (when there is a predefined number of shards, which is changeable only through a hard fork at best). Most sharding proposals are static; the TON Blockchain uses dynamic sharding (cf. [2.7](#2-7-splitting-and-merging-shardchains)).\n\n#### 2.8.14. Interaction between blockchains: loosely-coupled and tightly-coupled systems\n\nMulti-blockchain projects can be classified according to the supported level of interaction between the constituent blockchains.\n\nThe least level of support is the absence of any interaction between different blockchains whatsoever. We do not consider this case here, because we would rather say that these blockchains are not parts of one blockchain system, but just separate instances of the same blockchain protocol.\n\nThe next level of support is the absence of any specific support for messaging between blockchains, making interaction possible in principle, but awkward. We call such systems \"loosely-coupled\"; in them one must send messages and transfer value between blockchains as if they had been blockchains belonging to completely separate blockchain projects (e.g., Bitcoin and Ethereum; imagine two parties want to exchange some Bitcoins, kept in the Bitcoin blockchain, into Ethers, kept in the Ethereum blockchain). In other words, one must include the outbound message (or its generating transaction) in a block of the source blockchain. Then she (or some other party) must wait for enough confirmations (e.g., a given number of subsequent blocks) to consider the originating transaction to be \"committed\" and \"immutable\", so as to be able to perform external actions based on its existence. Only then may a transaction relaying the message into the target blockchain (perhaps along with a reference and a Merkle proof of existence for the originating transaction) be committed.\n\nIf one does not wait long enough before transferring the message, or if a fork happens anyway for some other reason, the joined state of the two blockchains turns out to be inconsistent: a message is delivered into the second blockchain that has never been generated in (the ultimately chosen fork of) the first blockchain.\n\nSometimes partial support for messaging is added, by standardizing the format of messages and the location of input and output message queues in the blocks of all workchains (this is especially useful in heterogeneous systems). While this facilitates messaging to a certain extent, it is conceptually not too different from the previous case, so such systems are still \"loosely-coupled\".\n\nBy contrast, \"tightly-coupled\" systems include special mechanisms to provide fast messaging between all blockchains. The desired behavior is to be able to deliver a message into another workchain immediately after it has been generated in a block of the originating blockchain. On the other hand, \"tightly-coupled\" systems are also expected to maintain overall consistency in the case of forks. While these two requirements appear to be contradictory at first glance, we believe that the mechanisms used by the TON Blockchain (the inclusion of shardchain block hashes into masterchain blocks; the use of \"vertical\" blockchains for fixing invalid blocks, cf. [2.1.17](#2-1-17-correcting-invalid-shardchain-blocks); hypercube routing, cf. [2.4.19](#2-4-19-hypercube-routing-slow-path-for-messages-with-assured-delivery); Instant Hypercube Routing, cf. [2.4.20](#2-4-20-instant-hypercube-routing%3A-“fast-path”-for-messages)) enable it to be a \"tightly-coupled\" system, perhaps the only one so far.\n\nOf course, building a \"loosely-coupled\" system is much simpler; however, fast and efficient sharding (cf. [2.8.12](#2-8-12-sharding-support)) requires the system to be \"tightly-coupled\".\n\n#### 2.8.15. Simplified classification. Generations of blockchain projects\n\nThe classification we have suggested so far splits all blockchain projects into a large number of classes. However, the classification criteria we use happen to be quite correlated in practice. This enables us to suggest a simplified \"generational\" approach to the classification of blockchain projects, as a very rough approximation of reality, with some examples. Projects that have not been implemented and deployed yet are shown in *italics*; the most important characteristics of a generation are shown in **bold**.\n\n- First generation: Single-chain, **PoW**, no support for smart contracts. Examples: Bitcoin (2009) and a lot of otherwise uninteresting imitators (Litecoin, Monero, ...).\n- Second generation: Single-chain, PoW, **smart-contract support**. Example: Ethereum (2013; deployed in 2015), at least in its original form.\n- Third generation: Single-chain, **PoS**, smart-contract support. Example: *future Ethereum* (2018 or later).\n- Alternative third (3') generation: **Multi-chain**, PoS, no support for smart contracts, loosely-coupled. Example: Bitshares (2013–2014; uses DPOS).\n- Fourth generation: **Multi-chain, PoS, smart-contract support**, loosely-coupled. Examples: *EOS* (2017; uses DPOS), *PolkaDot* (2016; uses BFT).\n- Fifth generation: Multi-chain, PoS with BFT, smart-contract support, **tightly-coupled, with sharding**. Examples: *TON* (2017).\n\nWhile not all blockchain projects fall precisely into one of these categories, most of them do.\n\n#### 2.8.16. Complications of changing the \"genome\" of a blockchain project\n\nThe above classification defines the \"genome\" of a blockchain project. This genome is quite \"rigid\": it is almost impossible to change it once the project is deployed and is used by a lot of people. One would need a series of hard forks (which would require the approval of the majority of the community), and even then the changes would need to be very conservative in order to preserve backward compatibility (e.g., changing the semantics of the virtual machine might break existing smart contracts). An alternative would be to create new \"sidechains\" with their different rules, and bind them somehow to the blockchain (or the blockchains) of the original project. One might use the blockchain of the existing single-blockchain project as an external masterchain for an essentially new and separate project.<sup>[27](#fn27)</sup>\n\nOur conclusion is that the genome of a project is very hard to change once it has been deployed. Even starting with PoW and planning to replace it with PoS in the future is quite complicated.<sup>[28](#fn28)</sup> Adding shards to a project originally designed without support for them seems almost impossible.<sup>[29](#fn29)</sup> In fact, adding support for smart contracts into a project (namely, Bitcoin) originally designed without support for such features has been deemed impossible (or at least undesirable by the majority of the Bitcoin community) and eventually led to the creation of a new blockchain project, Ethereum.\n\n#### 2.8.17. Genome of the TON Blockchain\n\nTherefore, if one wants to build a scalable blockchain system, one must choose its genome carefully from the very beginning. If the system is meant to support some additional specific functionality in the future not known at the time of its deployment, it should support \"heterogeneous\" workchains (having potentially different rules) from the start. For the system to be truly scalable, it must support sharding from the very beginning; sharding makes sense only if the system is \"tightly-coupled\" (cf. [2.8.14](#2-8-14-interaction-between-blockchains-loosely-coupled-and-tightly-coupled-systems)), so this in turn implies the existence of a masterchain, a fast system of inter-blockchain messaging, usage of BFT PoS, and so on.\n\nWhen one takes into account all these implications, most of the design choices made for the TON Blockchain project appear natural, and almost the only ones possible.\n\n---\n\n### 2.9  Comparison to Other Blockchain Projects\n\nWe conclude our brief discussion of the TON Blockchain and its most important and unique features by trying to find a place for it on a map containing existing and proposed blockchain projects. We use the classification criteria described in [2.8](#2-8-classification-of-blockchain-projects) to discuss different blockchain projects in a uniform way and construct such a \"map of blockchain projects\". We represent this map as [Table 1](#table-1), and then briefly discuss a few projects separately to point out their peculiarities that may not fit into the general scheme.\n\n<div id=\"table-1\"></div>\n\n| Project | Year | G. | Cons. | Sm. | Ch. | R. | Sh. | Int. |\n|---------|------|-----|-------|-----|-----|-----|-----|------|\n| Bitcoin | 2009 | 1 | PoW | no | 1 | | | |\n| Ethereum | 2013, 2015 | 2 | PoW | yes | 1 | | | |\n| NXT | 2014 | 2+ | PoS | no | 1 | | | |\n| Tezos | 2017, ? | 2+ | PoS | yes | 1 | | | |\n| Casper | 2015, (2017) | 3 | PoW/PoS | yes | 1 | | | |\n| BitShares | 2013, 2014 | 3' | DPoS | no | m | ht. | no | L |\n| EOS | 2016, (2018) | 4 | DPoS | yes | m | ht. | no | L |\n| PolkaDot | 2016, (2019) | 4 | PoS BFT | yes | m | ht. | no | L |\n| Cosmos | 2017, ? | 4 | PoS BFT | yes | m | ht. | no | L |\n| TON | 2017, (2018) | 5 | PoS BFT | yes | m | mix | dyn. | T |\n\n**Table 1:** A summary of some notable blockchain projects. The columns are: *Project* — project name; *Year* — year announced and year deployed; *G.* — generation (cf. [2.8.15](#2-8-15-simplified-classification-generations-of-blockchain-projects)); *Cons.* — consensus algorithm (cf. [2.8.3](#2-8-3-creating-and-validating-blocks-proof-of-work-vs-proof-of-stake) and [2.8.4](#2-8-4-variants-of-proof-of-stake-dpos-vs-bft)); *Sm.* — support for arbitrary code (smart contracts; cf. [2.8.6](#2-8-6-support-for-turing-complete-code-in-transactions%2C-i-e-%2C-essentially-arbitrary-smart-contracts)); *Ch.* — single/multiple blockchain system (cf. [2.8.2](#2-8-2-single-blockchain-vs-multi-blockchain-projects)); *R.* — heterogeneous/homogeneous multichain systems (cf. [2.8.8](#2-8-8-blockchain-types-homogeneous-and-heterogeneous-systems)); *Sh.* — sharding support (cf. [2.8.12](#2-8-12-sharding-support)); *Int.* — interaction between blockchains, (L)oose or (T)ight (cf. [2.8.14](#2-8-14-interaction-between-blockchains-loosely-coupled-and-tightly-coupled-systems)).\n\n#### 2.9.1. Bitcoin [[12]](#ref-12); https://bitcoin.org/ \n\n*Bitcoin* (2009) is the first and the most famous blockchain project. It is a typical *first-generation* blockchain project: it is single-chain, it uses Proof-of-Work with a \"longest-fork-wins\" fork selection algorithm, and it does not have a Turing-complete scripting language (however, simple scripts without loops are supported). The Bitcoin blockchain has no notion of an account; it uses the UTXO (Unspent Transaction Output) model instead.\n\n#### 2.9.2. Ethereum [[2]](#ref-2); https://ethereum.org/\n\n*Ethereum* (2015) is the first blockchain with support for Turing-complete smart contracts. As such, it is a typical *second-generation* project, and the most popular among them. It uses Proof-of-Work on a single blockchain, but has smart contracts and accounts.\n\n#### 2.9.3. NXT; https://nxtplatform.org/\n\n*NXT* (2014) is the first PoS-based blockchain and currency. It is still single-chain, and has no smart contract support.\n\n#### 2.9.4. Tezos; https://www.tezos.com/\n\n*Tezos* (2018 or later) is a proposed PoS-based single-blockchain project. We mention it here because of its unique feature: its block interpretation function $\\mathit{ev\\_block}$ (cf. [2.2.6](#2-2-6-blocks-and-transactions-as-state-transformation-operators)) is not fixed, but is determined by an OCaml module, which can be upgraded by committing a new version into the blockchain (and collecting some votes for the proposed change). In this way, one will be able to create custom single-chain projects by first deploying a \"vanilla\" Tezos blockchain, and then gradually changing the block interpretation function in the desired direction, without any need for hard forks.\n\nThis idea, while intriguing, has the obvious drawback that it forbids any optimized implementations in other languages like C++, so a Tezos-based blockchain is destined to have lower performance. We think that a similar result might have been obtained by publishing a formal *specification* of the proposed block interpretation function $\\mathit{ev\\_trans}$, without fixing a particular *implementation*.\n\n#### 2.9.5. Casper<sup>[30](#fn30)</sup>\n\n*Casper* is an upcoming PoS algorithm for Ethereum; its gradual deployment in 2017 (or 2018), if successful, will change Ethereum into a single-chain PoS or mixed PoW+PoS system with smart contract support, transforming Ethereum into a *third-generation* project.\n\n#### 2.9.6. BitShares [[8]](#ref-8); https://bitshares.org\n\n*BitShares* (2014) is a platform for distributed blockchain-based exchanges. It is a heterogeneous multi-blockchain DPoS system without smart contracts; it achieves its high performance by allowing only a small set of predefined specialized transaction types, which can be efficiently implemented in C++, assuming the blockchain state fits into memory. It is also the first blockchain project to use Delegated Proof-of-Stake (DPoS), demonstrating its viability at least for some specialized purposes.\n\n#### 2.9.7. EOS [[5]](#ref-5); https://eos.io\n\n*EOS* (2018 or later) is a proposed heterogeneous multi-blockchain DPoS system *with* smart contract support and with some minimal support for messaging (still loosely-coupled in the sense described in [2.8.14](#2-8-14-interaction-between-blockchains-loosely-coupled-and-tightly-coupled-systems)). It is an attempt by the same team that has previously successfully created the BitShares and SteemIt projects, demonstrating the strong points of the DPoS consensus algorithm. Scalability will be achieved by creating specialized workchains for projects that need it (e.g., a distributed exchange might use a workchain supporting a special set of optimized transactions, similarly to what BitShares did) and by creating multiple workchains with the same rules (*confederations* in the sense described in [2.8.10](#2-8-11-heterogeneous-systems-with-several-workchains-having-the-same-rules-or-confederations)). The drawbacks and limitations of this approach to scalability have been discussed in *loc. cit.* Cf. also [2.8.5](#2-8-5-comparison-of-dpos-and-bft-pos), [2.8.12](#2-8-13-sharding-support), and [2.8.14](#2-8-15-interaction-between-blockchains-loosely-coupled-and-tightly-coupled-systems) for a more detailed discussion of DPoS, sharding, interaction between workchains and their implications for the scalability of a blockchain system.\n\nAt the same time, even if one will not be able to \"create a Facebook inside a blockchain\" (cf. [2.9.13](#2-9-13-is-it-possible-to-upload-facebook-into-a-blockchain)), EOS or otherwise, we think that EOS might become a convenient platform for some highly-specialized weakly interacting distributed applications, similar to BitShares (decentralized exchange) and SteemIt (decentralized blog platform).\n\n#### 2.9.8. PolkaDot [[17]](#ref-17); https://polkadot.io/\n\n*PolkaDot* (2019 or later) is one of the best thought-out and most detailed proposed multichain Proof-of-Stake projects; its development is led by one of the Ethereum co-founders. This project is one of the closest projects to the TON Blockchain on our map. (In fact, we are indebted for our terminology for \"fishermen\" and \"nominators\" to the PolkaDot project.)\n\nPolkaDot is a heterogeneous loosely-coupled multichain Proof-of-Stake project, with Byzantine Fault Tolerant (BFT) consensus for generation of new blocks and a masterchain (which might be external—e.g., the Ethereum blockchain). It also uses hypercube routing, somewhat like (the slow version of) TON's as described in [2.4.19](#2-4-19-hypercube-routing-slow-path-for-messages-with-assured-delivery).\n\nIts unique feature is its ability to create not only *public*, but also *private* blockchains. These private blockchains would also be able to interact with other public blockchains, PolkaDot or otherwise.\n\nAs such, PolkaDot might become a platform for large-scale *private* blockchains, which might be used, for example, by bank consortiums to quickly transfer funds to each other, or for any other uses a large corporation might have for private blockchain technology.\n\nHowever, PolkaDot has no sharding support and is not tightly-coupled. This somewhat hampers its scalability, which is similar to that of EOS. (Perhaps a bit better, because PolkaDot uses BFT PoS instead of DPoS.)\n\n#### 2.9.9. Universa; https://universa.io\n\nThe only reason we mention this unusual blockchain project here is because it is the only project so far to make in passing an explicit reference to something similar to our Infinite Sharding Paradigm (cf. [2.1.2](#2-1-2-infinite-sharding-paradigm)). Its other peculiarity is that it bypasses all complications related to Byzantine Fault Tolerance by promising that only trusted and licensed partners of the project will be admitted as validators, hence they will never commit invalid blocks. This is an interesting decision; however, it essentially makes a blockchain project deliberately *centralized*, something blockchain projects usually want to avoid (why does one need a blockchain at all to work in a trusted centralized environment?).\n\n#### 2.9.10. Plasma; https://plasma.io\n\n*Plasma* (2019?) is an unconventional blockchain project from another co-founder of Ethereum. It is supposed to mitigate some limitations of Ethereum without introducing sharding. In essence, it is a separate project from Ethereum, introducing a hierarchy of (heterogeneous) workchains, bound to the Ethereum blockchain (to be used as an external masterchain) at the top level. Funds can be transferred from any blockchain up in the hierarchy (starting from the Ethereum blockchain as the root), along with a description of a job to be done. Then the necessary computations are done in the child workchain (possibly requiring forwarding of parts of the original job further down the tree), their results are passed up, and a reward is collected. The problem of achieving consistency and validating these workchains is circumvented by a (payment channel-inspired) mechanism allowing users to unilaterally withdraw their funds from a misbehaving workchain to its parent workchain (albeit slowly), and re-allocate their funds and their jobs to another workchain.\n\nIn this way, Plasma might become a platform for distributed computations bound to the Ethereum blockchain, something like a \"mathematical co-processor\". However, this does not seem like a way to achieve true general-purpose scalability.\n\n#### 2.9.11. Specialized blockchain projects\n\nThere are also some specialized blockchain projects, such as FileCoin (a system that incentivizes users to offer their disk space for storing the files of other users who are willing to pay for it), Golem (a blockchain-based platform for renting and lending computing power for specialized applications such as 3D-rendering) or SONM (another similar computing power-lending project). Such projects do not introduce anything conceptually new on the level of blockchain organization; rather, they are particular blockchain applications, which could be implemented by smart contracts running in a general-purpose blockchain, provided it can deliver the required performance. As such, projects of this kind are likely to use one of the existing or planned blockchain projects as their base, such as EOS, PolkaDot or TON. If a project needs \"true\" scalability (based on sharding), it would better use TON; if it is content to work in a \"confederated\" context by defining a family of workchains of its own, explicitly optimized for its purpose, it might opt for EOS or PolkaDot.\n \n#### 2.9.12. The TON Blockchain\n\nThe TON (Telegram Open Network) Blockchain (planned 2018) is the project we are describing in this document. It is designed to be the first fifth-generation blockchain project—that is, a BFT PoS-multichain project, mixed homogeneous/heterogeneous, with support for (shardable) custom workchains, with native sharding support, and tightly-coupled (in particular, capable of forwarding messages between shards almost instantly while preserving a consistent state of all shardchains). As such, it will be a truly scalable general-purpose blockchain project, capable of accommodating essentially any applications that can be implemented in a blockchain at all. When augmented by the other components of the TON Project (cf. [1](#1-brief-description-of-ton-components)), its possibilities expand even further.\n\n#### 2.9.13. Is it possible to \"upload Facebook into a blockchain\"?\n\nSometimes people claim that it will be possible to implement a social network on the scale of Facebook as a distributed application residing in a blockchain. Usually a favorite blockchain project is cited as a possible \"host\" for such an application.\n\nWe cannot say that this is a technical impossibility. Of course, one needs a tightly-coupled blockchain project with true sharding (i.e., TON) in order for such a large application not to work too slowly (e.g., deliver messages and updates from users residing in one shardchain to their friends residing in another shardchain with reasonable delays). However, we think that this is not needed and will never be done, because the price would be prohibitive.\n\nLet us consider \"uploading Facebook into a blockchain\" as a thought experiment; any other project of similar scale might serve as an example as well. Once Facebook is uploaded into a blockchain, all operations currently done by Facebook's servers will be serialized as transactions in certain blockchains (e.g., TON's shardchains), and will be performed by all validators of these blockchains. Each operation will have to be performed, say, at least twenty times, if we expect every block to collect at least twenty validator signatures (immediately or eventually, as in DPOS systems). Similarly, all data kept by Facebook's servers on their disks will be kept on the disks of all validators for the corresponding shardchain (i.e., in at least twenty copies).\n\nBecause the validators are essentially the same servers (or perhaps clusters of servers, but this does not affect the validity of this argument) as those currently used by Facebook, we see that the total hardware expenses associated with running Facebook in a blockchain are at least twenty times higher than if it were implemented in the conventional way.\n\nIn fact, the expenses would be much higher still, because the blockchain's virtual machine is slower than the \"bare CPU\" running optimized compiled code, and its storage is not optimized for Facebook-specific problems. One might partially mitigate this problem by crafting a specific workchain with some special transactions adapted for Facebook; this is the approach of BitShares and EOS to achieving high performance, available in the TON Blockchain as well. However, the general blockchain design would still impose some additional restrictions by itself, such as the necessity to register all operations as transactions in a block, to organize these transactions in a Merkle tree, to compute and check their Merkle hashes, to propagate this block further, and so on.\n\nTherefore, a conservative estimate is that one would need 100 times more servers of the same performance as those used by Facebook now in order to validate a blockchain project hosting a social network of that scale. Somebody will have to pay for these servers, either the company owning the distributed application (imagine seeing 700 ads on each Facebook page instead of 7) or its users. Either way, this does not seem economically viable.\n\nWe believe that *it is not true that everything should be uploaded into the blockchain*. For example, it is not necessary to keep user photographs in the blockchain; registering the hashes of these photographs in the blockchain and keeping the photographs in a distributed off-chain storage (such as FileCoin or TON Storage) would be a better idea. This is the reason why TON is not just a blockchain project, but a collection of several components (TON P2P Network, TON Storage, TON Services) centered around the TON Blockchain as outlined in Chapters [1](#1-brief-description-of-ton-components) and [4](#4-ton-services-and-applications).\n\n---\n\n## 3. TON Networking\n\nAny blockchain project requires not only a specification of block format and blockchain validation rules, but also a network protocol used to propagate new blocks, send and collect transaction candidates and so on. In other words, a specialized peer-to-peer network must be set up by every blockchain project. This network must be peer-to-peer, because blockchain projects are normally expected to be decentralized, so one cannot rely on a centralized group of servers and use conventional client-server architecture, as, for instance, classical online banking applications do. Even light clients (e.g., light cryptocurrency wallet smartphone applications), which must connect to full nodes in a client-server–like fashion, are actually free to connect to another full node if their previous peer goes down, provided the protocol used to connect to full nodes is standardized enough.\n\nWhile the networking demands of single-blockchain projects, such as Bitcoin or Ethereum, can be met quite easily (one essentially needs to construct a \"random\" peer-to-peer overlay network, and propagate all new blocks and transaction candidates by a gossip protocol), multi-blockchain projects, such as the TON Blockchain, are much more demanding (e.g., one must be able to subscribe to updates of only some shardchains, not necessarily all of them). Therefore, the networking part of the TON Blockchain and the TON Project as a whole merits at least a brief discussion.\n\nOn the other hand, once the more sophisticated network protocols needed to support the TON Blockchain are in place, it turns out that they can easily be used for purposes not necessarily related to the immediate demands of the TON Blockchain, thus providing more possibilities and flexibility for creating new services in the TON ecosystem.\n\n### 3.1  Abstract Datagram Network Layer\n\nThe cornerstone in building the TON networking protocols is the *(TON) Abstract (Datagram) Network Layer*. It enables all nodes to assume certain \"network identities\", represented by 256-bit \"abstract network addresses\", and communicate (send datagrams to each other, as a first step) using only these 256-bit network addresses to identify the sender and the receiver. In particular, one does not need to worry about IPv4 or IPv6 addresses, UDP port numbers, and the like; they are hidden by the Abstract Network Layer.\n\n#### 3.1.1. Abstract network addresses\n\nAn *abstract network address*, or an *abstract address*, or just *address* for short, is a 256-bit integer, essentially equal to a 256-bit ECC public key. This public key can be generated arbitrarily, thus creating as many different network identities as the node likes. However, one must know the corresponding *private* key in order to receive (and decrypt) messages intended for such an address.\n\nIn fact, the address is *not* the public key itself; instead, it is a 256-bit hash ($\\text{Hash}=\\text{Sha256}$) of a serialized TL-object (cf. [2.2.5](#2-2-5-tl-or-the-type-language)) that can describe several types of public keys and addresses depending on its constructor (first four bytes). In the simplest case, this serialized TL-object consists just of a 4-byte magic number and a 256-bit elliptic curve cryptography (ECC) public key; in this case, the address will equal the hash of this 36-byte structure. One might use, however, 2048-bit RSA keys, or any other scheme of public-key cryptography instead.\n\nWhen a node learns another node's abstract address, it must also receive its \"preimage\" (i.e., the serialized TL-object, the hash of which equals that abstract address) or else it will not be able to encrypt and send datagrams to that address.\n\n#### 3.1.2. Lower-level networks. UDP implementation\n\nFrom the perspective of almost all TON Networking components, the only thing that exists is a network (the Abstract Datagram Networking Layer) able to (unreliably) send datagrams from one abstract address to another. In principle, the Abstract Datagram Networking Layer (ADNL) can be implemented over different existing network technologies. However, we are going to implement it over UDP in IPv4/IPv6 networks (such as the Internet or intranets), with an optional TCP fallback if UDP is not available.\n\n#### 3.1.3. Simplest case of ADNL over UDP\n\nThe simplest case of sending a datagram from a sender's abstract address to any other abstract address (with known preimage) can be implemented as follows.\n\nSuppose that the sender somehow knows the IP-address and the UDP port of the receiver who owns the destination abstract address, and that both the receiver and the sender use abstract addresses derived from 256-bit ECC public keys.\n\nIn this case, the sender simply augments the datagram to be sent by its ECC signature (done with its private key) and its source address (or the preimage of the source address, if the receiver is not known to know that preimage yet). The result is encrypted with the recipient's public key, embedded into a UDP datagram and sent to the known IP and port of the recipient. Because the first 256 bits of the UDP datagram contain the recipient's abstract address, the recipient can identify which private key should be used to decrypt the remainder of the datagram. Only after that is the sender's identity revealed.\n\n#### 3.1.4. Less secure way, with the sender's address in plaintext\n\nSometimes a less secure scheme is sufficient, when the recipient's and the sender's addresses are kept in plaintext in the UDP datagram; the sender's private key and the recipient's public key are combined together using ECDH (Elliptic Curve Diffie–Hellman) to generate a 256-bit shared secret, which is used afterwards, along with a random 256-bit nonce also included in the unencrypted part, to derive AES keys used for encryption. The integrity may be provided, for instance, by concatenating the hash of the original plaintext data to the plaintext before encryption.\n\nThis approach has the advantage that, if more than one datagram is expected to be exchanged between the two addresses, the shared secret can be computed only once and then cached; then slower elliptic curve operations will no longer be required for encrypting or decrypting the next datagrams.\n\n#### 3.1.5. Channels and channel identifiers\n\nIn the simplest case, the first 256 bits of a UDP datagram carrying an embedded TON ADNL datagram will be equal to the recipient's address. However, in general they constitute a *channel identifier*. There are different types of channels. Some of them are point-to-point; they are created by two parties who wish to exchange a lot of data in the future and generate a shared secret by exchanging several packets encrypted as described in [3.1.3](#3-1-3-simplest-case-of-adnl-over-udp) or [3.1.4](#3-1-4-less-secure-way-with-the-senders-address-in-plaintext), by running classical or elliptic curve Diffie–Hellman (if extra security is required), or simply by one party generating a random shared secret and sending it to the other party.\n\nAfter that, a channel identifier is derived from the shared secret combined with some additional data (such as the sender's and recipient's addresses), for instance by hashing, and that identifier is used as the first 256 bits of UDP datagrams carrying data encrypted with the aid of that shared secret.\n\n#### 3.1.6. Channel as a tunnel identifier\n\nIn general, a \"channel\", or \"channel identifier\" simply selects a way of processing an inbound UDP datagram, known to the receiver. If the channel is the receiver's abstract address, the processing is done as outlined in [3.1.3](#3-1-3-simplest-case-of-adnl-over-udp) or [3.1.4](#3-1-4-less-secure-way-with-the-senders-address-in-plaintext); if the channel is an established point-to-point channel discussed in [3.1.5](#3-1-5-channels-and-channel-identifiers), the processing consists in decrypting the datagram with the aid of the shared secret as explained in *loc. cit.*, and so on.\n\nIn particular, a channel identifier can actually select a \"tunnel\", when the immediate recipient simply forwards the received message to somebody else—the actual recipient or another proxy. Some encryption or decryption steps (reminiscent of \"onion routing\" [[6]](#ref-6) or even \"garlic routing\"<sup>[31](#fn31)</sup>) might be done along the way, and another channel identifier might be used for re-encrypted forwarded packets (for example, a peer-to-peer channel could be employed to forward the packet to the next recipient on the path).\n\nIn this way, some support for \"tunneling\" and \"proxying\"—somewhat similar to that provided by the TOR or $I^2P$ projects—can be added on the level of the TON Abstract Datagram Network Layer, without affecting the functionality of all higher-level TON network protocols, which would be agnostic of such an addition. This opportunity is exploited by the *TON Proxy* service (cf. [4.1.11](#4-1-11-example%3A-ton-proxy-is-a-fog-service)).\n\n#### 3.1.7. Zero channel and the bootstrap problem\n\nNormally, a TON ADNL node will have some \"neighbor table\", containing information about other known nodes, such as their abstract addresses and their preimages (i.e., public keys) and their IP addresses and UDP ports. Then it will gradually extend this table by using information learned from these known nodes as answers to special queries, and sometimes prune obsolete records.\n\nHowever, when a TON ADNL node just starts up, it may happen that it does not know any other node, and can learn only the IP address and UDP port of a node, but not its abstract address. This happens, for example, if a light client is not able to access any of the previously cached nodes and any nodes hardcoded into the software, and must ask the user to enter an IP address or a DNS domain of a node, to be resolved through DNS.\n\nIn this case, the node will send packets to a special \"zero channel\" of the node in question. This does not require knowledge of the recipient's public key (but the message should still contain the sender's identity and signature), so the message is transferred without encryption. It should be normally used only to obtain an identity (maybe a one-time identity created especially for this purpose) of the receiver, and then to start communicating in a safer way.\n\nOnce at least one node is known, it is easy to populate the \"neighbor table\" and \"routing table\" by more entries, learning them from answers to special queries sent to the already known nodes.\n\nNot all nodes are required to process datagrams sent to the zero channel, but those used to bootstrap light clients should support this feature.\n\n#### 3.1.8. TCP-like stream protocol over ADNL\n\nThe ADNL, being an unreliable (small-size) datagram protocol based on 256-bit abstract addresses, can be used as a base for more sophisticated network protocols. One can build, for example, a TCP-like stream protocol, using ADNL as an abstract replacement for IP. However, most components of the TON Project do not need such a stream protocol.\n\n#### 3.1.9. RLDP, or Reliable Large Datagram Protocol over ADNL\n\nA reliable arbitrary-size datagram protocol built upon the ADNL, called RLDP, is used instead of a TCP-like protocol. This reliable datagram protocol can be employed, for instance, to send RPC queries to remote hosts and receive answers from them (cf. [4.1.5](#4-1-5-pure-network-services-ton-sites-and-ton-services)).\n\n### 3.2   TON DHT: Kademlia-like Distributed Hash Table\n\nThe *TON Distributed Hash Table (DHT)* plays a crucial role in the networking part of the TON Project, being used to locate other nodes in the network. For example, a client wanting to commit a transaction into a shardchain might want to find a validator or a collator of that shardchain, or at least some node that might relay the client's transaction to a collator. This can be done by looking up a special key in the TON DHT. Another important application of the TON DHT is that it can be used to quickly populate a new node's neighbor table (cf. [3.1.7](#3-1-7-zero-channel-and-the-bootstrap-problem)), simply by looking up a random key, or the new node's address. If a node uses proxying and tunneling for its inbound datagrams, it publishes the tunnel identifier and its entry point (e.g., IP address and UDP port) in the TON DHT; then all nodes wishing to send datagrams to that node will obtain this contact information from the DHT first.\n\nThe TON DHT is a member of the family of *Kademlia-like distributed hash tables* [[10]](#ref-10).\n\n#### 3.2.1. Keys of the TON DHT\n\nThe *keys* of the TON DHT are simply 256-bit integers. In most cases, they are computed as SHA-256 of a TL-serialized object (cf. [2.2.5](#2-2-5-tl-or-the-type-language)), called *preimage* of the key, or *key description*. In some cases, the abstract addresses of the TON Network nodes (cf. [3.1.1](#3-1-1-abstract-network-addresses)) can also be used as keys of the TON DHT, because they are also 256-bit, and they are also hashes of TL-serialized objects. For example, if a node is not afraid of publishing its IP address, it can be found by anybody who knows its abstract address by simply looking up that address as a key in the DHT.\n\n#### 3.2.2. Values of the DHT\n\nThe *values* assigned to these 256-bit keys are essentially arbitrary byte strings of limited length. The interpretation of such byte strings is determined by the preimage of the corresponding key; it is usually known both by the node that looks up the key, and by the node that stores the key.\n\n#### 3.2.3. Nodes of the DHT. Semi-permanent network identities\n\nThe key-value mapping of the TON DHT is kept on the *nodes* of the DHT—essentially, all members of the TON Network. To this end, any node of the TON Network (perhaps with the exception of some very light nodes), apart from any number of ephemeral and permanent abstract addresses described in [3.1.1](#3-1-1-abstract-network-addresses), has at least one \"semi-permanent address\", which identifies it as a member of the TON DHT. This *semi-permanent* or *DHT address* should not to be changed too often, otherwise other nodes would be unable to locate the keys they are looking for. If a node does not want to reveal its \"true\" identity, it generates a separate abstract address to be used only for the purpose of participating in the DHT. However, this abstract address must be public, because it will be associated with the node's IP address and port.\n\n#### 3.2.4. Kademlia distance\n\nNow we have both 256-bit keys and 256-bit (semi-permanent) node addresses. We introduce the so-called *XOR distance* or *Kademlia distance $d_K$* on the set of 256-bit sequences, given by\n\n$$\n\\mathit{d_K}(x,y) := (x \\oplus y) \\quad \\text{interpreted as an unsigned 256-bit integer} \\quad (25)\n$$\n\nHere $x \\oplus y$ denotes the bitwise eXclusive OR (XOR) of two bit sequences of the same length.\n\nThe Kademlia distance introduces a metric on the set $\\mathbf{2}^{256}$ of all 256-bit sequences. In particular, we have $d_K(x,y) = 0$ if and only if $x = y$, $d_K(x,y) = d_K(y,x)$, and $d_K(x,z) \\leq d_K(x,y) + d_K(y,z)$. Another important property is that *there is only one point at any given distance from $x$*: $d_K(x,y) = d_K(x,y')$ implies $y = y'$.\n\n#### 3.2.5. Kademlia-like DHTs and the TON DHT\n\nWe say that a distributed hash table (DHT) with 256-bit keys and 256-bit node addresses is a *Kademlia-like DHT* if it is expected to keep the value of key $K$ on $s$ Kademlia-nearest nodes to $K$ (i.e., the $s$ nodes with smallest Kademlia distance from their addresses to $K$.)\n\nHere $s$ is a small parameter, say, $s=7$, needed to improve reliability of the DHT (if we would keep the key only on one node, the nearest one to $K$, the value of that key would be lost if that only node goes offline).\n\nThe TON DHT is a Kademlia-like DHT, according to this definition. It is implemented over the ADNL protocol described in [3.1](#3-1-abstract-datagram-network-layer).\n\n#### 3.2.6. Kademlia routing table\n\nAny node participating in a Kademlia-like DHT usually maintains a *Kademlia routing table*. In the case of TON DHT, it consists of $n=256$ buckets, numbered from $0$ to $n-1$. The $i$-th bucket will contain information about some known nodes (a fixed number $t$ of \"best\" nodes, and maybe some extra candidates) that lie at a Kademlia distance from $2^i$ to $2^{i+1}-1$ from the node's address $a$.<sup>[32](#fn32)</sup> This information includes their (semi-permanent) addresses, IP addresses and UDP ports, and some availability information such as the time and the delay of the last ping.\n\nWhen a Kademlia node learns about any other Kademlia node as a result of some query, it includes it into a suitable bucket of its routing table, first as a candidate. Then, if some of the \"best\" nodes in that bucket fail (e.g., do not respond to ping queries for a long time), they can be replaced by some of the candidates. In this way the Kademlia routing table stays populated.\n\nNew nodes from the Kademlia routing table are also included in the ADNL neighbor table described in [3.1.7](#3-1-7-zero-channel-and-the-bootstrap-problem). If a \"best\" node from a bucket of the Kademlia routing table is used often, a channel in the sense described in [3.1.5](#3-1-5-channels-and-channel-identifiers) can be established to facilitate the encryption of datagrams.\n\nA special feature of the TON DHT is that it tries to select nodes with the smallest round-trip delays as the \"best\" nodes for the buckets of the Kademlia routing table.\n\n#### 3.2.7. Kademlia network queries\n\nA Kademlia node usually supports the following network queries:\n\n- $\\text{Ping}$ — Checks node availability.\n- $\\text{Store}(\\text{key},\\text{value})$ — Asks the node to keep *value* as a value for key *key*. For TON DHT, the $\\text{Store}$ queries are slightly more complicated (cf. [3.2.9](#3-2-9-storing-values-in-ton-dht)).\n- $\\text{Find\\_Node}(\\text{key},l)$ — Asks the node to return $l$ Kademlia-nearest known nodes (from its Kademlia routing table) to *key*.\n- $\\text{Find\\_Value}(\\text{key},l)$ — The same as above, but if the node knows the value corresponding to key *key*, it just returns that value.\n\nWhen any node wants to look up the value of a key $K$, it first creates a set $S$ of $s'$ nodes (for some small value of $s'$, say, $s'=5$), nearest to $K$ with respect to the Kademlia distance among all known nodes (i.e., they are taken from the Kademlia routing table). Then a $\\text{Find\\_Value}$ query is sent to each of them, and nodes mentioned in their answers are included in $S$. Then the $s'$ nodes from $S$, nearest to $K$, are also sent a $\\text{Find\\_Value}$ query if this hasn't been done before, and the process continues until the value is found or the set $S$ stops growing. This is a sort of \"beam search\" of the node nearest to $K$ with respect to Kademlia distance.\n\nIf the value of some key $K$ is to be set, the same procedure is run for $s'\\geq s$, with $\\text{Find\\_Node}$ queries instead of $\\text{Find\\_Value}$, to find $s$ nearest nodes to $K$. Afterwards, $\\text{Store}$ queries are sent to all of them.\n\nThere are some less important details in the implementation of a Kademlia-like DHT (for example, any node should look up $s$ nearest nodes to itself, say, once every hour, and re-publish all stored keys to them by means of $\\text{Store}$ queries). We will ignore them for the time being.\n\n#### 3.2.8. Booting a Kademlia node\n\nWhen a Kademlia node goes online, it first populates its Kademlia routing table by looking up its own address. During this process, it identifies the $s$ nearest nodes to itself. It can download from them all $(key,value)$ pairs known to them to populate its part of the DHT.\n\n#### 3.2.9. Storing values in TON DHT\n\nStoring values in TON DHT is slightly different from a general Kademlia-like DHT. When someone wishes to store a value, she must provide not only the key $K$ itself to the $\\text{Store}$ query, but also its *preimage*—i.e., a TL-serialized string (with one of several predefined TL-constructors at the beginning) containing a \"description\" of the key. This key description is later kept by the node, along with the key and the value.\n\nThe key description describes the \"type\" of the object being stored, its \"owner\", and its \"update rules\" in case of future updates. The owner is usually identified by a public key included in the key description. If it is included, normally only updates signed by the corresponding private key will be accepted. The \"type\" of the stored object is normally just a byte string. However, in some cases it can be more sophisticated—for example, an input tunnel description (cf. [3.1.6](#3-1-6-channel-as-a-tunnel-identifier)), or a collection of node addresses.\n\nThe \"update rules\" can also be different. In some cases, they simply permit replacing the old value with the new value, provided the new value is signed by the owner (the signature must be kept as part of the value, to be checked later by any other nodes after they obtain the value of this key). In other cases, the old value somehow affects the new value. For example, it can contain a sequence number, and the old value is overwritten only if the new sequence number is larger (to prevent replay attacks).\n\n#### 3.2.10. Distributed \"torrent trackers\" and \"network interest groups\" in TON DHT\n\nYet another interesting case is when the value contains a list of nodes—perhaps with their IP addresses and ports, or just with their abstract addresses—and the \"update rule\" consists in including the requester in this list, provided she can confirm her identity.\n\nThis mechanism might be used to create a distributed \"torrent tracker\", where all nodes interested in a certain \"torrent\" (i.e., a certain file) can find other nodes that are interested in the same torrent, or already have a copy.\n\n*TON Storage* (cf. [4.1.8](#4-1-8-example%3A-keeping-files-off-chain%3B-ton-storage)) uses this technology to find the nodes that have a copy of a required file (e.g., a snapshot of the state of a shardchain, or an old block). However, its more important use is to create \"overlay multicast subnetworks\" and \"network interest groups\" (cf. [3.3](#3-3-overlay-networks-and-multicasting-messages)). The idea is that only some nodes are interested in the updates of a specific shardchain. If the number of shardchains becomes very large, finding even one node interested in the same shard may become complicated. This \"distributed torrent tracker\" provides a convenient way to find some of these nodes. Another option would be to request them from a validator, but this would not be a scalable approach, and validators might choose not to respond to such queries coming from arbitrary unknown nodes.\n\n#### 3.2.11. Fall-back keys\n\nMost of the \"key types\" described so far have an extra 32-bit integer field in their TL description, normally equal to zero. However, if the key obtained by hashing that description cannot be retrieved from or updated in the TON DHT, the value in this field is increased, and a new attempt is made. In this way, one cannot \"capture\" and \"censor\" a key (i.e., perform a key retention attack) by creating a lot of abstract addresses lying near the key under attack and controlling the corresponding DHT nodes.\n\n#### 3.2.12. Locating services\n\nSome services, located in the TON Network and available through the (higher-level protocols built upon the) TON ADNL described in [3.1](#3-1-abstract-datagram-network-layer), may want to publish their abstract addresses somewhere, so that their clients would know where to find them.\n\nHowever, publishing the service's abstract address in the TON Blockchain may not be the best approach, because the abstract address might need to be changed quite often, and because it could make sense to provide several addresses, for reliability or load balancing purposes.\n\nAn alternative is to publish a public key into the TON Blockchain, and use a special DHT key indicating that public key as its \"owner\" in the TL description string (cf. [2.2.5](#2-2-5-tl-or-the-type-language)) to publish an up-to-date list of the service's abstract addresses. This is one of the approaches exploited by TON Services.\n\n#### 3.2.13. Locating owners of TON blockchain accounts\n\nIn most cases, owners of TON blockchain accounts would not like to be associated with abstract network addresses, and especially IP addresses, because this can violate their privacy. In some cases, however, the owner of a TON blockchain account may want to publish one or several abstract addresses where she could be contacted.\n\nA typical case is that of a node in the TON Payments \"lightning network\" (cf. [5.2](#5-2-payment-channel-network-or-lightning-network)), the platform for instant cryptocurrency transfers. A public TON Payments node may want not only to establish payment channels with other peers, but also to publish an abstract network address that could be used to contact it at a later time for transferring payments along the already-established channels.\n\nOne option would be to include an abstract network address in the smart contract creating the payment channel. A more flexible option is to include a public key in the smart contract, and then use DHT as explained in [3.2.12](#3-2-12-locating-services).\n\nThe most natural way would be to use the same private key that controls the account in the TON Blockchain to sign and publish updates in the TON DHT about the abstract addresses associated with that account. This is done almost in the same way as described in [3.2.12](#3-2-12-locating-services); however, the DHT key employed would require a special key description, containing only the $\\mathit{account\\_id}$ itself, equal to SHA-256 of the \"account description\", which contains the public key of the account. The signature, included in the value of this DHT key, would contain the account description as well.\n\nIn this way, a mechanism for locating abstract network addresses of some owners of the TON Blockchain accounts becomes available.\n\n#### 3.2.14. Locating abstract addresses\n\nNotice that the TON DHT, while being implemented over TON ADNL, is itself used by the TON ADNL for several purposes.\n\nThe most important of them is to locate a node or its contact data starting from its 256-bit abstract address. This is necessary because the TON ADNL should be able to send datagrams to arbitrary 256-bit abstract addresses, even if no additional information is provided.\n\nTo this end, the 256-bit abstract address is simply looked up as a key in the DHT. Either a node with this address (i.e., using this address as a public semi-persistent DHT address) is found, in which case its IP address and port can be learned; or, an input tunnel description may be retrieved as the value of the key in question, signed by the correct private key, in which case this tunnel description would be used to send ADNL datagrams to the intended recipient.\n\nNotice that in order to make an abstract address \"public\" (reachable from any nodes in the network), its owner must either use it as a semi-permanent DHT address, or publish (in the DHT key equal to the abstract address under consideration) an input tunnel description with another of its public abstract addresses (e.g., the semi-permanent address) as the tunnel's entry point. Another option would be to simply publish its IP address and UDP port.\n\n---\n\n### 3.3  Overlay Networks and Multicasting Messages\n\nIn a multi-blockchain system like the TON Blockchain, even full nodes would normally be interested in obtaining updates (i.e., new blocks) only about some shardchains. To this end, a special overlay (sub)network must be built inside the TON Network, on top of the ADNL protocol discussed in [3.1](#3-1-abstract-datagram-network-layer), one for each shardchain.\n\nTherefore, the need to build arbitrary overlay subnetworks, open to any nodes willing to participate, arises. Special gossip protocols, built upon ADNL, will be run in these overlay networks. In particular, these gossip protocols may be used to propagate (broadcast) arbitrary data inside such a subnetwork.\n\n#### 3.3.1. Overlay networks\n\nAn *overlay (sub)network* is simply a (virtual) network implemented inside some larger network. Usually only some nodes of the larger network participate in the overlay subnetwork, and only some \"links\" between these nodes, physical or virtual, are part of the overlay subnetwork.\n\nIn this way, if the encompassing network is represented as a graph (perhaps a full graph in the case of a datagram network such as ADNL, where any node can easily communicate to any other), the overlay subnetwork is a *subgraph* of this graph.\n\nIn most cases, the overlay network is implemented using some protocol built upon the network protocol of the larger network. It may use the same addresses as the larger network, or use custom addresses.\n\n#### 3.3.2. Overlay networks in TON\n\nOverlay networks in TON are built upon the ADNL protocol discussed in [3.1](#3-1-abstract-datagram-network-layer); they use 256-bit ADNL abstract addresses as addresses in the overlay networks as well. Each node usually selects one of its abstract addresses to double as its address in the overlay network.\n\nIn contrast to ADNL, the TON overlay networks usually do not support sending datagrams to arbitrary other nodes. Instead, some \"semipermanent links\" are established between some nodes (called \"neighbors\" with respect to the overlay network under consideration), and messages are usually forwarded along these links (i.e., from a node to one of its neighbors). In this way, a TON overlay network is a (usually not full) subgraph inside the (full) graph of the ADNL network.\n\nLinks to neighbors in TON overlay networks can be implemented using dedicated peer-to-peer ADNL channels (cf. [3.1.5](#3-1-5-channels-and-channel-identifiers)).\n\nEach node of an overlay network maintains a list of neighbors (with respect to the overlay network), containing their abstract addresses (which they use to identify them in the overlay network) and some link data (e.g., the ADNL channel used to communicate with them).\n\n#### 3.3.3. Private and public overlay networks\n\nSome overlay networks are *public*, meaning that any node can join them at will. Other are *private*, meaning that only certain nodes can be admitted (e.g., those that can prove their identities as validators.) Some private overlay networks can even be unknown to the \"general public\". The information about such overlay networks is made available only to certain trusted nodes; for example, it can be encrypted with a public key, and only nodes having a copy of the corresponding private key will be able to decrypt this information.\n\n#### 3.3.4. Centrally controlled overlay networks\n\nSome overlay networks are *centrally controlled*, by one or several nodes, or by the owner of some widely-known public key. Others are *decentralized*, meaning that there are no specific nodes responsible for them.\n\n#### 3.3.5. Joining an overlay network\n\nWhen a node wants to join an overlay network, it first must learn its 256-bit *network identifier*, usually equal to SHA-256 of the *description* of the overlay network—a TL-serialized object (cf. [2.2.5](#2-2-5-tl-or-the-type-language)) which may contain, for instance, the central authority of the overlay network (i.e., its public key and perhaps its abstract address,<sup>[33](#fn33)</sup>) a string with the name of the overlay network, a TON Blockchain shard identifier if this is an overlay network related to that shard, and so on.\n\nSometimes it is possible to recover the overlay network description starting from the network identifier, simply by looking it up in the TON DHT. In other cases (e.g., for private overlay networks), one must obtain the network description along with the network identifier.\n\n#### 3.3.6. Locating one member of the overlay network\n\nAfter a node learns the network identifier and the network description of the overlay network it wants to join, it must locate at least one node belonging to that network.\n\nThis is also needed for nodes that do not want to join the overlay network, but want just to communicate with it; for example, there might be an overlay network dedicated to collecting and propagating transaction candidates for a specific shardchain, and a client might want to connect to any node of this network to suggest a transaction.\n\nThe method used for locating members of an overlay network is defined in the description of that network. Sometimes (especially for private networks) one must already know a member node to be able to join. In other cases, the abstract addresses of some nodes are contained in the network description. A more flexible approach is to indicate in the network description only the central authority responsible for the network, and then the abstract addresses will be available through values of certain DHT keys, signed by that central authority.\n\nFinally, truly decentralized public overlay networks can use the \"distributed torrent-tracker\" mechanism described in [3.2.10](#3-2-10-distributed-torrent-trackers-and-network-interest-groups-in-ton-dht), also implemented with the aid of the TON DHT.\n\n#### 3.3.7. Locating more members of the overlay network. Creating links\n\nOnce one node of the overlay network is found, a special query may be sent to that node requesting a list of other members, for instance, neighbors of the node being queried, or a random selection thereof.\n\nThis enables the joining member to populate her \"adjacency\" or \"neighbor list\" with respect to the overlay network, by selecting some newly-learned network nodes and establishing links to them (i.e., dedicated ADNL point-to-point channels, as outlined in [3.3.2](#3-3-2-overlay-networks-in-ton)). After that, special messages are sent to all neighbors indicating that the new member is ready to work in the overlay network. The neighbors include their links to the new member in their neighbor lists.\n\n#### 3.3.8. Maintaining the neighbor list\n\nAn overlay network node must update its neighbor list from time to time. Some neighbors, or at least links (channels) to them, may stop responding; in this case, these links must be marked as \"suspended\", some attempts to reconnect to such neighbors must be made, and, if these attempts fail, the links must be destroyed.\n\nOn the other hand, every node sometimes requests from a randomly chosen neighbor its list of neighbors (or some random selection thereof), and uses it to partially update its own neighbor list, by adding some newly-discovered nodes to it, and removing some of the old ones, either randomly or depending on their response times and datagram loss statistics.\n\n#### 3.3.9. The overlay network is a random subgraph\n\nIn this way, the overlay network becomes a random subgraph inside the ADNL network. If the degree of each vertex is at least three (i.e., if each node is connected to at least three neighbors), this random graph is known to be *connected* with a probability almost equal to one. More precisely, the probability of a random graph with $n$ vertices being *disconnected* is exponentially small, and this probability can be completely neglected if, say, $n\\geq20$. (Of course, this does not apply in the case of a global network partition, when nodes on different sides of the partition have no chance to learn about each other.) On the other hand, if $n$ is smaller than 20, it would suffice to require each vertex to have, say, at least ten neighbors.\n\n#### 3.3.10. TON overlay networks are optimized for lower latency\n\nTON overlay networks optimize the \"random\" network graph generated by the previous method as follows. Every node tries to retain at least three neighbors with the minimal round-trip time, changing this list of \"fast neighbors\" very rarely. At the same time, it also has at least three other \"slow neighbors\" that are chosen completely randomly, so that the overlay network graph would always contain a random subgraph. This is required to maintain connectivity and prevent splitting of the overlay network into several unconnected regional subnetworks. At least three \"intermediate neighbors\", which have intermediate round-trip times, bounded by a certain constant (actually, a function of the round-trip times of the fast and the slow neighbors), are also chosen and retained.\n\nIn this way, the graph of an overlay network still maintains enough randomness to be connected, but is optimized for lower latency and higher throughput.\n\n#### 3.3.11. Gossip protocols in an overlay network\n\nAn overlay network is often used to run one of the so-called *gossip protocols*, which achieve some global goal while letting every node interact only with its neighbors. For example, there are gossip protocols to construct an approximate list of all members of a (not too large) overlay network, or to compute an estimate of the number of members of an (arbitrarily large) overlay network, using only a bounded amount of memory at each node (cf. [[15](#ref-15), 4.4.3] or [[1]](#ref-1) for details).\n\n#### 3.3.12. Overlay network as a broadcast domain\n\nThe most important gossip protocol running in an overlay network is the *broadcast protocol*, intended to propagate broadcast messages generated by any node of the network, or perhaps by one of the designated sender nodes, to all other nodes.\n\nThere are in fact several broadcast protocols, optimized for different use cases. The simplest of them receives new broadcast messages and relays them to all neighbors that have not yet sent a copy of that message themselves.\n\n#### 3.3.13. More sophisticated broadcast protocols\n\nSome applications may warrant more sophisticated broadcast protocols. For instance, for broadcasting messages of substantial size, it makes sense to send to the neighbors not the newly-received message itself, but its hash (or a collection of hashes of new messages). The neighbor may request the message itself after learning a previously unseen message hash, to be transferred, say, using the reliable large datagram protocol (RLDP) discussed in [3.1.9](#3-1-9-rldp-or-reliable-large-datagram-protocol-over-adnl). In this way, the new message will be downloaded from one neighbor only.\n\n#### 3.3.14. Checking the connectivity of an overlay network\n\nThe connectivity of an overlay network can be checked if there is a known node (e.g., the \"owner\" or the \"creator\" of the overlay network) that must be in this overlay network. Then the node in question simply broadcasts from time to time short messages containing the current time, a sequence number and its signature. Any other node can be sure that it is still connected to the overlay network if it has received such a broadcast not too long ago. This protocol can be extended to the case of several well-known nodes; for example, they all will send such broadcasts, and all other nodes will expect to receive broadcasts from more than half of the well-known nodes.\n\nIn the case of an overlay network used for propagating new blocks (or just new block headers) of a specific shardchain, a good way for a node to check connectivity is to keep track of the most recent block received so far. Because a block is normally generated every five seconds, if no new block is received for more than, say, thirty seconds, the node probably has been disconnected from the overlay network.\n\n#### 3.3.15. Streaming broadcast protocol\n\nFinally, there is a *streaming broadcast protocol* for TON overlay networks, used, for example, to propagate block candidates among validators of some shardchain (\"shardchain task group\"), who, of course, create a private overlay network for that purpose. The same protocol can be used to propagate new shardchain blocks to all full nodes for that shardchain.\n\nThis protocol has already been outlined in [2.6.10](#2-6-10-propagation-of-shardchain-block-candidates): the new (large) broadcast message is split into, say, $N$ one-kilobyte chunks; the sequence of these chunks is augmented to $M\\geq N$ chunks by means of an erasure code such as the Reed–Solomon or a fountain code (e.g., the RaptorQ code [[9]](#ref-9) [[14]](#ref-14)), and these $M$ chunks are streamed to all neighbors in ascending chunk number order. The participating nodes collect these chunks until they can recover the original large message (one would have to successfully receive at least $N$ of the chunks for this), and then instruct their neighbors to stop sending new chunks of the stream, because now these nodes can generate the subsequent chunks on their own, having a copy of the original message. Such nodes continue to generate the subsequent chunks of the stream and send them to their neighbors, unless the neighbors in turn indicate that this is no longer necessary.\n\nIn this way, a node does not need to download a large message in its entirety before propagating it further. This minimizes broadcast latency, especially when combined with the optimizations described in [3.3.10](#3-3-10-ton-overlay-networks-are-optimized-for-lower-latency).\n\n#### 3.3.16. Constructing new overlay networks based on existing ones\n\nSometimes one does not want to construct an overlay network from scratch. Instead, one or several previously existing overlay networks are known, and the membership of the new overlay network is expected to overlap significantly with the combined membership of these overlay networks.\n\nAn important example arises when a TON shardchain is split in two, or two sibling shardchains are merged into one (cf. [2.7](#2-7-splitting-and-merging-shardchains)). In the first case, the overlay networks used for propagating new blocks to full nodes must be constructed for each of the new shardchains; however, each of these new overlay networks can be expected to be contained in the block propagation network of the original shardchain (and comprise approximately half its members). In the second case, the overlay network for propagating new blocks of the merged shardchain will consist approximately of the union of members of the two overlay networks related to the two sibling shardchains being merged.\n\nIn such cases, the description of the new overlay network may contain an explicit or implicit reference to a list of related existing overlay networks. A node wishing to join the new overlay network may check whether it is already a member of one of these existing networks, and query its neighbors in these networks whether they are interested in the new network as well. In case of a positive answer, new point-to-point channels can be established to such neighbors, and they can be included in the neighbor list for the new overlay network.\n\nThis mechanism does not totally supplant the general mechanism described in [3.3.6](#3-3-6-locating-one-member-of-the-overlay-network) and [3.3.7](#3-3-7-locating-more-members-of-the-overlay-network-creating-links); rather, both are run in parallel and are used to populate the neighbor list. This is needed to prevent inadvertent splitting of the new overlay network into several unconnected subnetworks.\n\n#### 3.3.17. Overlay networks within overlay networks\n\nAnother interesting case arises in the implementation of *TON Payments* (a \"lightning network\" for instant off-chain value transfers; cf. [5.2](#5-2-payment-channel-network-or-lightning-network)). In this case, first an overlay network containing all transit nodes of the \"lightning network\" is constructed. However, some of these nodes have established payment channels in the blockchain; they must always be neighbors in this overlay network, in addition to any \"random\" neighbors selected by the general overlay network algorithms described in [3.3.6](#3-3-6-locating-one-member-of-the-overlay-network), [3.3.7](#3-3-7-locating-more-members-of-the-overlay-network-creating-links) and [3.3.8](#3-3-8-maintaining-the-neighbor-list). These \"permanent links\" to the neighbors with established payment channels are used to run specific lightning network protocols, thus effectively creating an overlay subnetwork (not necessarily connected, if things go awry) inside the encompassing (almost always connected) overlay network.\n\n---\n\n## 4  TON Services and Applications\n\nWe have discussed the TON Blockchain and TON Networking technologies at some length. Now we explain some ways in which they can be combined to create a wide range of services and applications, and discuss some of the services that will be provided by the TON Project itself, either from the very beginning or at a later time.\n\n### 4.1  TON Service Implementation Strategies\n\nWe start with a discussion of how different blockchain and network-related applications and services may be implemented inside the TON ecosystem. First of all, a simple classification is in order:\n\n#### 4.1.1. Applications and services\n\nWe will use the words \"application\" and \"service\" interchangeably. However, there is a subtle and somewhat vague distinction: an *application* usually provides some services directly to human users, while a *service* is usually exploited by other applications and services. For example, TON Storage is a service, because it is designed to keep files on behalf of other applications and services, even though a human user might use it directly as well. A hypothetical \"Facebook in a blockchain\" (cf. [2.9.13](#2-9-13-is-it-possible-to-upload-facebook-into-a-blockchain)) or Telegram messenger, if made available through the TON Network (i.e., implemented as a \"ton-service\" c.f [4.1.6](#4-1-6-telegram-messenger-as-a-ton-service%3B-mtproto-over-rldp)), would rather be an *application*, even though some \"bots\" might access it automatically without human intervention.\n\n#### 4.1.2. Location of the application: on-chain, off-chain or mixed\n\nA service or an application designed for the TON ecosystem needs to keep its data and process that data somewhere. This leads to the following classification of applications (and services):\n\n- *On-chain* applications (cf. [4.1.4](#4-1-4-pure-on-chain-applications%3A-distributed-applications%2C-or-dapps%2C-residing-in-the-blockchain)): All data and processing are in the TON Blockchain.\n- *Off-chain* applications (cf. [4.1.5](#4-1-5-pure-network-services%3A-ton-sites-and-ton-services)): All data and processing are outside the TON Blockchain, on servers available through the TON Network.\n- *Mixed* applications (cf. [4.1.7](#4-1-7-mixed-services%3A-partly-off-chain%2C-partly-on-chain)): Some, but not all, data and processing are in the TON Blockchain; the rest are on off-chain servers available through the TON Network.\n\n#### 4.1.3. Centralization: centralized and decentralized, or distributed, applications\n\nAnother classification criterion is whether the application (or service) relies on a centralized server cluster, or is really \"distributed\" (cf. [4.1.9](#4-1-9-decentralized-mixed-services%2C-or-“fog-services”)). All on-chain applications are automatically decentralized and distributed. Off-chain and mixed applications may exhibit different degrees of centralization.\n\nNow let us consider the above possibilities in more detail.\n\n#### 4.1.4. Pure \"on-chain\" applications: distributed applications, or \"dapps\", residing in the blockchain\n\nOne of the possible approaches, mentioned in [4.1.2](#4-1-2-location-of-the-application-on-chain-off-chain-or-mixed), is to deploy a \"distributed application\" (commonly abbreviated as \"dapp\") completely in the TON Blockchain, as one smart contract or a collection of smart contracts. All data will be kept as part of the permanent state of these smart contracts, and all interaction with the project will be done by means of (TON Blockchain) messages sent to or received from these smart contracts.\n\nWe have already discussed in [2.9.13](#2-9-13-is-it-possible-to-upload-facebook-into-a-blockchain) that this approach has its drawbacks and limitations. It has its advantages, too: such a distributed application needs no servers to run on or to store its data (it runs \"in the blockchain\"—i.e., on the validators' hardware), and enjoys the blockchain's extremely high (Byzantine) reliability and accessibility. The developer of such a distributed application does not need to buy or rent any hardware; all she needs to do is develop some software (i.e., the code for the smart contracts). After that, she will effectively rent the computing power from the validators, and will pay for it in Grams, either herself or by putting this burden on the shoulders of her users.\n\n#### 4.1.5. Pure network services: \"ton-sites\" and \"ton-services\"\n\nAnother extreme option is to deploy the service on some servers and make it available to the users through the ADNL protocol described in [3.1](#3-1-abstract-datagram-network-layer), and maybe some higher level protocol such as the RLDP discussed in [3.1.9](#3-1-9-rldp-or-reliable-large-datagram-protocol-over-adnl), which can be used to send RPC queries to the service in any custom format and obtain answers to these queries. In this way, the service will be totally off-chain, and will reside in the TON Network, almost without using the TON Blockchain.\n\nThe TON Blockchain might be used only to locate the abstract address or addresses of the service, as outlined in [3.2.12](#3-2-12-locating-services), perhaps with the aid of a service such as the TON DNS (cf. [4.3.1](#4-3-1-ton-dns-a-mostly-on-chain-hierarchical-domain-name-service)) to facilitate translation of domain-like human-readable strings into abstract addresses.\n\nTo the extent the ADNL network (i.e., the TON Network) is similar to the Invisible Internet Project ($I^2P$), such (almost) purely network services are analogous to the so-called \"eep-services\" (i.e., services that have an $I^2P$-address as their entry point, and are available to clients through the $I^2P$ network). We will say that such purely network services residing in the TON Network are \"ton-services\".\n\nAn \"eep-service\" may implement HTTP as its client-server protocol; in the TON Network context, a \"ton-service\" might simply use RLDP (cf. [3.1.9](#3-1-9-rldp-or-reliable-large-datagram-protocol-over-adnl)) datagrams to transfer HTTP queries and responses to them. If it uses the TON DNS to allow its abstract address to be looked up by a human-readable domain name, the analogy to a web site becomes almost perfect. One might even write a specialized browser, or a special proxy (\"ton-proxy\") that is run locally on a user's machine, accepts arbitrary HTTP queries from an ordinary web browser the user employs (once the local IP address and the TCP port of the proxy are entered into the browser's configuration), and forwards these queries through the TON Network to the abstract address of the service. Then the user would have a browsing experience similar to that of the World Wide Web (WWW).\n\nIn the $I^2P$ ecosystem, such \"eep-services\" are called \"eep-sites\". One can easily create \"ton-sites\" in the TON ecosystem as well. This is facilitated somewhat by the existence of services such as the TON DNS, which exploit the TON Blockchain and the TON DHT to translate (TON) domain names into abstract addresses.\n\n#### 4.1.6. Telegram Messenger as a ton-service; MTProto over RLDP\n\nWe would like to mention in passing that the MTProto protocol,<sup>[34](#fn34)</sup> used by Telegram Messenger<sup>[35](#fn35)</sup> for client-server interaction, can be easily embedded into the RLDP protocol discussed in [3.1.9](#3-1-9-rldp-or-reliable-large-datagram-protocol-over-adnl), thus effectively transforming Telegram into a ton-service. Because the TON Proxy technology can be switched on transparently for the end user of a ton-site or a ton-service, being implemented on a lower level than the RLDP and ADNL protocols (cf. [3.1.6](#3-1-6-channel-as-a-tunnel-identifier)), this would make Telegram effectively unblockable. Of course, other messaging and social networking services might benefit from this technology as well.\n\n#### 4.1.7. Mixed services: partly off-chain, partly on-chain\n\nSome services might use a mixed approach: do most of the processing off-chain, but also have some on-chain part (for example, to register their obligations towards their users, and vice versa). In this way, part of the state would still be kept in the TON Blockchain (i.e., an immutable public ledger), and any misbehavior of the service or of its users could be punished by smart contracts.\n\n#### 4.1.8. Example: keeping files off-chain; TON Storage\n\nAn example of such a service is given by *TON Storage*. In its simplest form, it allows users to store files off-chain, by keeping on-chain only a hash of the file to be stored, and possibly a smart contract where some other parties agree to keep the file in question for a given period of time for a pre-negotiated fee. In fact, the file may be subdivided into chunks of some small size (e.g., 1 kilobyte), augmented by an erasure code such as a Reed–Solomon or a fountain code, a Merkle tree hash may be constructed for the augmented sequence of chunks, and this Merkle tree hash might be published in the smart contract instead of or along with the usual hash of the file. This is somewhat reminiscent of the way files are stored in a torrent.\n\nAn even simpler form of storing files is completely off-chain: one might essentially create a \"torrent\" for a new file, and use TON DHT as a \"distributed torrent tracker\" for this torrent (cf. [3.2.10](#3-2-10-distributed-torrent-trackers-and-network-interest-groups-in-ton-dht)). This might actually work pretty well for popular files. However, one does not get any availability guarantees. For example, a hypothetical \"blockchain Facebook\" (cf. [2.9.13](#2-9-13-is-it-possible-to-upload-facebook-into-a-blockchain)), which would opt to keep the profile photographs of its users completely off-chain in such \"torrents\", might risk losing photographs of ordinary (not especially popular) users, or at least risk being unable to present these photographs for prolonged periods. The TON Storage technology, which is mostly off-chain, but uses an on-chain smart contract to enforce availability of the stored files, might be a better match for this task.\n\n#### 4.1.9. Decentralized mixed services, or \"fog services\"\n\nSo far, we have discussed *centralized* mixed services and applications. While their on-chain component is processed in a decentralized and distributed fashion, being located in the blockchain, their off-chain component relies on some servers controlled by the service provider in the usual centralized fashion. Instead of using some dedicated servers, computing power might be rented from a cloud computing service offered by one of the large companies. However, this would not lead to decentralization of the off-chain component of the service.\n\nA decentralized approach to implementing the off-chain component of a service consists in creating a *market*, where anybody possessing the required hardware and willing to rent their computing power or disk space would offer their services to those needing them.\n\nFor example, there might exist a registry (which might also be called a \"market\" or an \"exchange\") where all nodes interested in keeping files of other users publish their contact information, along with their available storage capacity, availability policy, and prices. Those needing these services might look them up there, and, if the other party agrees, create smart contracts in the blockchain and upload files for off-chain storage. In this way a service like *TON Storage* becomes truly decentralized, because it does not need to rely on any centralized cluster of servers for storing files.\n\n#### 4.1.10. Example: \"fog computing\" platforms as decentralized mixed services\n\nAnother example of such a decentralized mixed application arises when one wants to perform some specific computations (e.g., 3D rendering or training neural networks), often requiring specific and expensive hardware. Then those having such equipment might offer their services through a similar \"exchange\", and those needing such services would rent them, with the obligations of the sides registered by means of smart contracts. This is similar to what \"fog computing\" platforms, such as Golem (https://golem.network/) or SONM (https://sonm.io/), promise to deliver.\n\n#### 4.1.11. Example: TON Proxy is a fog service\n\n*TON Proxy* provides yet another example of a fog service, where nodes wishing to offer their services (with or without compensation) as tunnels for ADNL network traffic might register, and those needing them might choose one of these nodes depending on the price, latency and bandwidth offered. Afterwards, one might use payment channels provided by *TON Payments* for processing micropayments for the services of those proxies, with payments collected, for instance, for every 128 KiB transferred.\n\n#### 4.1.12. Example: TON Payments is a fog service\n\nThe TON Payments platform (cf. [5](#5-ton-payments)) is also an example of such a decentralized mixed application.\n\n### 4.2  Connecting Users and Service Providers\n\nWe have seen in [4.1.9](#4-1-9-decentralized-mixed-services%2C-or-“fog-services”) that \"fog services\" (i.e., mixed decentralized services) will usually need some *markets*, *exchanges* or *registries*, where those needing specific services might meet those providing them.\n\nSuch markets are likely to be implemented as on-chain, off-chain or mixed services themselves, centralized or distributed.\n\n#### 4.2.1. Example: connecting to TON Payments\n\nFor example, if one wants to use TON Payments (cf. [5](#5-ton-payments)), the first step would be to find at least some existing transit nodes of the \"lightning network\" (cf. [5.2](#5-2-payment-channel-network-or-lightning-network)), and establish payment channels with them, if they are willing. Some nodes can be found with the aid of the \"encompassing\" overlay network, which is supposed to contain all transit lightning network nodes (cf. [3.3.17](#3-3-17-overlay-networks-within-overlay-networks)). However, it is not clear whether these nodes will be willing to create new payment channels. Therefore, a registry is needed where nodes ready to create new links can publish their contact information (e.g., their abstract addresses).\n\n#### 4.2.2. Example: uploading a file into TON Storage\n\nSimilarly, if one wants to upload a file into the TON Storage, she must locate some nodes willing to sign a smart contract binding them to keep a copy of that file (or of any file below a certain size limit, for that matter). Therefore, a registry of nodes offering their services for storing files is needed.\n\n#### 4.2.3. On-chain, mixed and off-chain registries\n\nSuch a registry of service providers might be implemented completely on-chain, with the aid of a smart contract which would keep the registry in its permanent storage. However, this would be quite slow and expensive. A mixed approach is more efficient, where the relatively small and rarely changed on-chain registry is used only to point out some nodes (by their abstract addresses, or by their public keys, which can be used to locate actual abstract addresses as described in [3.2.12](#3-2-12-locating-services)), which provide off-chain (centralized) registry services.\n\nFinally, a decentralized, purely off-chain approach might consist of a public overlay network (cf. [3.3](#3-3-overlay-networks-and-multicasting-messages)), where those willing to offer their services, or those looking to buy somebody's services, simply broadcast their offers, signed by their private keys. If the service to be provided is very simple, even broadcasting the offers might be not necessary: the approximate membership of the overlay network itself might be used as a \"registry\" of those willing to provide a particular service. Then a client requiring this service might locate (cf. [3.3.7](#3-3-7-locating-more-members-of-the-overlay-network-creating-links)) and query some nodes of this overlay network, and then query their neighbors, if the nodes already known are not ready to satisfy its needs.\n\n#### 4.2.4. Registry or exchange in a side-chain\n\nAnother approach to implementing decentralized mixed registries consists in creating an independent specialized blockchain (\"side-chain\"), maintained by its own set of self-proclaimed validators, who publish their identities in an on-chain smart contract and provide network access to all interested parties to this specialized blockchain, collecting transaction candidates and broadcasting block updates through dedicated overlay networks (cf. [3.3](#3-3-overlay-networks-and-multicasting-messages)). Then any full node for this sidechain can maintain its own copy of the shared registry (essentially equal to the global state of this side-chain), and process arbitrary queries related to this registry.\n\n#### 4.2.5. Registry or exchange in a workchain\n\nAnother option is to create a dedicated workchain inside the TON Blockchain, specialized for creating registries, markets and exchanges. This might be more efficient and less expensive than using smart contracts residing in the basic workchain (cf. [2.1.11](#2-1-11-basic-workchain-or-workchain-zero)). However, this would still be more expensive than maintaining registries in side-chains (cf. [4.2.4](#4-2-4-registry-or-exchange-in-a-side-chain)).\n\n### 4.3   Accessing TON Services\n\nWe have discussed in [4.1](#4-1-ton-service-implementation-strategies) the different approaches one might employ for creating new services and applications residing in the TON ecosystem. Now we discuss how these services might be accessed, and some of the \"helper services\" that will be provided by TON, including *TON DNS* and *TON Storage*.\n\n#### 4.3.1. TON DNS: a mostly on-chain hierarchical domain name service\n\nThe *TON DNS* is a predefined service, which uses a collection of smart contracts to keep a map from human-readable domain names to (256-bit) addresses of ADNL network nodes and TON Blockchain accounts and smart contracts.\n\nWhile anybody might in principle implement such a service using the TON Blockchain, it is useful to have such a predefined service with a well-known interface, to be used by default whenever an application or a service wants to translate human-readable identifiers into addresses.\n\n#### 4.3.2. TON DNS use cases\n\nFor example, a user looking to transfer some cryptocurrency to another user or to a merchant may prefer to remember a TON DNS domain name of the account of that user or merchant, instead of keeping their 256-bit account identifiers at hand and copy-pasting them into the recipient field in their light wallet client.\n\nSimilarly, TON DNS may be used to locate account identifiers of smart contracts or entry points of ton-services and ton-sites (cf. [4.1.5](#4-1-5-pure-network-services-ton-sites-and-ton-services)), enabling a specialized client (\"ton-browser\"), or a usual internet browser combined with a specialized ton-proxy extension or stand-alone application, to deliver a WWW-like browsing experience to the user.\n\n#### 4.3.3. TON DNS smart contracts\n\nThe TON DNS is implemented by means of a tree of special (DNS) smart contracts. Each DNS smart contract is responsible for registering subdomains of some fixed domain. The \"root\" DNS smart contract, where level one domains of the TON DNS system will be kept, is located in the masterchain. Its account identifier must be hardcoded into all software that wishes to access the TON DNS database directly.\n\nAny DNS smart contract contains a hashmap, mapping variable-length null-terminated UTF-8 strings into their \"values\". This hashmap is implemented as a binary Patricia tree, similar to that described in [2.3.7](#2-3-7-definition-of-hashmap-type-as-a-patricia-tree) but supporting variable-length bitstrings as keys.\n\n#### 4.3.4. Values of the DNS hashmap, or TON DNS records\n\nAs to the values, they are \"TON DNS records\" described by a TL-scheme (cf. [2.2.5](#2-2-5-tl-or-the-type-language)). They consist of a \"magic number\", selecting one of the options supported, and then either an account identifier, or a smart-contract identifier, or an abstract network address (cf. [3.1](#3-1-abstract-datagram-network-layer)), or a public key used to locate abstract addresses of a service (cf. [3.2.12](#3-2-12-locating-services)), or a description of an overlay network, and so on. An important case is that of another DNS smart contract: in such a case, that smart contract is used to resolve subdomains of its domain. In this way, one can create separate registries for different domains, controlled by the owners of those domains.\n\nThese records may also contain an expiration time, a caching time (usually very large, because updating values in a blockchain too often is expensive), and in most cases a reference to the owner of the subdomain in question. The owner has the right to change this record (in particular, the owner field, thus transferring the domain to somebody else's control), and to prolong it.\n\n#### 4.3.5. Registering new subdomains of existing domains\n\nIn order to register a new subdomain of an existing domain, one simply sends a message to the smart contract, which is the registrar of that domain, containing the subdomain (i.e., the key) to be registered, the value in one of several predefined formats, an identity of the owner, an expiration date, and some amount of cryptocurrency as determined by the domain's owner.\n\nSubdomains are registered on a \"first-come, first-served\" basis.\n\n#### 4.3.6. Retrieving data from a DNS smart contract\n\nIn principle, any full node for the masterchain or shardchain containing a DNS smart contract might be able to look up any subdomain in the database of that smart contract, if the structure and the location of the hashmap inside the persistent storage of the smart contract are known.\n\nHowever, this approach would work only for certain DNS smart contracts. It would fail miserably if a non-standard DNS smart contract were used. \n\nInstead, an approach based on *general smart contract interfaces and get methods* ([cf. 4.3.11](#4-3-11-get-methods-of-smart-contracts)) is used. Any DNS smart contract must define a get method with a known signature, which is invoked to look up a key. Since this approach makes sense for other smart contracts as well, especially those providing on-chain and mixed services, we explain it in some detail in [4.3.11](#4-3-11-get-methods-of-smart-contracts).\n\n#### 4.3.7. Translating a TON DNS domain\n\nOnce any full node, acting by itself or on behalf of some light client, can look up entries in the database of any DNS smart contract, arbitrary TON DNS domain names can be recursively translated, starting from the well-known and fixed root DNS smart contract (account) identifier.\n\nFor example, if one wants to translate `A.B.C`, one looks up keys `.C`, `.B.C`, and `A.B.C` in the root domain database. If the first of them is not found, but the second is, and its value is a reference to another DNS smart contract, then `A` is looked up in the database of that smart contract and the final value is retrieved.\n\n#### 4.3.8. Translating TON DNS domains for light nodes\n\nIn this way, a full node for the masterchain—and also for all shardchains involved in the domain look-up process—might translate any domain name into its current value without external help. A light node might request a full node to do this on its behalf and return the value, along with a Merkle proof (cf. [2.5.11](#2-5-11-merkle-proofs-as-query-responses-from-full-nodes)). This Merkle proof would enable the light node to verify that the answer is correct, so such TON DNS responses cannot be \"spoofed\" by a malicious interceptor, in contrast to the usual DNS protocol.\n\nBecause no node can be expected to be a full node with respect to all shardchains, actual TON DNS domain translation would involve a combination of these two strategies.\n\n#### 4.3.9. Dedicated \"TON DNS servers\"\n\nOne might provide a simple \"TON DNS server\", which would receive RPC \"DNS\" queries (e.g., via the ADNL or RLDP protocols described in [3.1](#3-1-abstract-datagram-network-layer)), requesting that the server translate a given domain, process these queries by forwarding some subqueries to other (full) nodes if necessary, and return answers to the original queries, augmented by Merkle proofs if required.\n\nSuch \"DNS servers\" might offer their services (for free or not) to any other nodes and especially light clients, using one of the methods described in [4.2](#4-2-connecting-users-and-service-providers). Notice that these servers, if considered part of the TON DNS service, would effectively transform it from a distributed on-chain service into a distributed mixed service (i.e., a \"fog service\").\n\nThis concludes our brief overview of the TON DNS service, a scalable on-chain registry for human-readable domain names of TON Blockchain and TON Network entities.\n\n#### 4.3.10. Accessing data kept in smart contracts\n\nWe have already seen that it is sometimes necessary to access data stored in a smart contract without changing its state.\n\nIf one knows the details of the smart-contract implementation, one can extract all the needed information from the smart contract's persistent storage, available to all full nodes of the shardchain the smart contract resides in. However, this is quite an inelegant way of doing things, depending very much on the smart-contract implementation.\n\n#### 4.3.11. \"Get methods\" of smart contracts\n\nA better way would be to define some *get methods* in the smart contract, that is, some types of inbound messages that do not affect the state of the smart contract when delivered, but generate one or more output messages containing the \"result\" of the get method. In this way, one can obtain data from a smart contract, knowing only that it implements a get method with a known signature (i.e., a known format of the inbound message to be sent and outbound messages to be received as a result).\n\nThis way is much more elegant and in line with object oriented programming (OOP). However, it has an obvious defect so far: one must actually commit a transaction into the blockchain (sending the get message to the smart contract), wait until it is committed and processed by the validators, extract the answer from a new block, and pay for gas (i.e., for executing the get method on the validators' hardware). This is a waste of resources: get methods do not change the state of the smart contract anyways, so they need not be executed in the blockchain.\n\n#### 4.3.12. Tentative execution of get methods of smart contracts\n\nWe have already remarked (cf. [2.4.6](#2-4-6-external-messages-or-messages-from-nowhere)) that any full node can tentatively execute any method of any smart contract (i.e., deliver any message to a smart contract), starting from a given state of the smart contract, without actually committing the corresponding transaction. The full node can simply load the code of the smart contract under consideration into the TON VM, initialize its persistent storage from the global state of the shardchain (known to all full nodes of the shardchain), and execute the smart-contract code with the inbound message as its input parameter. The output messages created will yield the result of this computation.\n\nIn this way, any full node can evaluate arbitrary get methods of arbitrary smart contracts, provided their signature (i.e., the format of inbound and outbound messages) is known. The node may keep track of the cells of the shardchain state accessed during this evaluation, and create a Merkle proof of the validity of the computation performed, for the benefit of a light node that might have asked the full node to do so (cf. [2.5.11](#2-5-11-merkle-proofs-as-query-responses-from-full-nodes)).\n\n#### 4.3.13. Smart-contract interfaces in TL-schemes\n\nRecall that the methods implemented by a smart contract (i.e., the input messages accepted by it) are essentially some TL-serialized objects, which can be described by a TL-scheme (cf. [2.2.5](#2-2-5-tl-or-the-type-language)). The resulting output messages can be described by the same TL-scheme as well. In this way, the interface provided by a smart contract to other accounts and smart contracts may be formalized by means of a TL-scheme.\n\nIn particular, (a subset of) get methods supported by a smart contract can be described by such a formalized smart-contract interface.\n\n#### 4.3.14. Public interfaces of a smart contract\n\nNotice that a formalized smart-contract interface, either in form of a TL-scheme (represented as a TL source file; cf. [2.2.5](#2-2-5-tl-or-the-type-language)) or in serialized form,<sup>[36](#fn36)</sup> can be published—for example, in a special field in the smart-contract account description, stored in the blockchain, or separately, if this interface will be referred to many times. In the latter case a hash of the supported public interface may be incorporated into the smart-contract description instead of the interface description itself.\n\nAn example of such a public interface is that of a DNS smart contract, which is supposed to implement at least one standard get method for looking up subdomains (cf. [4.3.6](#4-3-6-retrieving-data-from-a-dns-smart-contract)). A standard method for registering new subdomains can be also included in the standard public interface of DNS smart contracts.\n\n#### 4.3.15. User interface of a smart contract\n\nThe existence of a public interface for a smart contract has other benefits, too. For example, a wallet client application may download such an interface while examining a smart contract on the request of a user, and display a list of public methods (i.e., of available actions) supported by the smart contract, perhaps with some human-readable comments if any are provided in the formal interface. After the user selects one of these methods, a form may be automatically generated according to the TL-scheme, where the user will be prompted for all fields required by the chosen method and for the desired amount of cryptocurrency (e.g., Grams) to be attached to this request. Submitting this form will create a new blockchain transaction containing the message just composed, sent from the user's blockchain account.\n\nIn this way, the user will be able to interact with arbitrary smart contracts from the wallet client application in a user-friendly way by filling and submitting certain forms, provided these smart contracts have published their interfaces.\n\n#### 4.3.16. User interface of a \"ton-service\"\n\nIt turns out that ton-services (i.e., services residing in the TON Network and accepting queries through the ADNL and RLDP protocols of [3](#3-ton-networking); [cf. 4.1.5](#4-1-5-pure-network-services%3A-ton-sites-and-ton-services)) may also profit from having public interfaces, described by TL-schemes ([cf. 2.2.5](#2-2-5-tl%2C-or-the-type-language)). A client application, such as a light wallet or a ton-browser, might prompt the user to select one of the methods and to fill in a form with parameters defined by the interface, similarly to what has just been discussed in [4.3.15](#4-3-15-user-interface-of-a-smart-contract). The only difference is that the resulting TL-serialized message is not submitted as a transaction in the blockchain; instead, it is sent as an RPC query to the abstract address of the ton-service in question, and the response to this query is parsed and displayed according to the formal interface (i.e., a TL-scheme).\n\n#### 4.3.17. Locating user interfaces via TON DNS\n\nThe TON DNS record containing an abstract address of a ton-service or a smart-contract account identifier might also contain an optional field describing the public (user) interface of that entity, or several supported interfaces. Then the client application (be it a wallet, a ton-browser or a ton-proxy) will be able to download the interface and interact with the entity in question (be it a smart contract or a ton-service) in a uniform way.\n\n#### 4.3.18. Blurring the distinction between on-chain and off-chain services\n\nIn this way, the distinction between on-chain, off-chain and mixed services (cf. [4.1.2](#4-1-2-location-of-the-application-on-chain-off-chain-or-mixed)) is blurred for the end user: she simply enters the domain name of the desired service into the address line of her ton-browser or wallet, and the rest is handled seamlessly by the client application.\n\n#### 4.3.19. A light wallet and TON entity explorer can be built into Telegram Messenger clients\n\nAn interesting opportunity arises at this point. A light wallet and TON entity explorer, implementing the above functionality, can be embedded into the Telegram Messenger smartphone client application, thus bringing the technology to more than 200 million people. Users would be able to send hyperlinks to TON entities and resources by including TON URIs (cf. [4.3.22](#4-3-22-hyperlink-urls-may-specify-some-parameters)) in messages; such hyperlinks, if selected, will be opened internally by the Telegram client application of the receiving party, and interaction with the chosen entity will begin.\n\n#### 4.3.20. \"ton-sites\" as ton-services supporting an HTTP interface\n\nA *ton-site* is simply a ton-service that supports an HTTP interface, perhaps along with some other interfaces. This support may be announced in the corresponding TON DNS record.\n\n#### 4.3.21. Hyperlinks\n\nNotice that the HTML pages returned by ton-sites may contain *ton-hyperlinks*—that is, references to other ton-sites, smart contracts and accounts by means of specially crafted URI schemes (cf. [4.3.22](#4-3-22-hyperlink-urls-may-specify-some-parameters))—containing either abstract network addresses, account identifiers, or human-readable TON DNS domains. Then a \"ton-browser\" might follow such a hyperlink when the user selects it, detect the interface to be used, and display a user interface form as outlined in [4.3.15](#4-3-15-user-interface-of-a-smart-contract) and [4.3.16](#4-3-16-user-interface-of-a-ton-service).\n\n#### 4.3.22. Hyperlink URLs may specify some parameters\n\nThe hyperlink URLs may contain not only a (TON) DNS domain or an abstract address of the service in question, but also the name of the method to be invoked and some or all of its parameters. A possible URI scheme for this might look as follows:\n```\nton://<domain>/<method>?<field1>=<value1>&<field2>=...\n```\n\nWhen the user selects such a link in a ton-browser, either the action is performed immediately (especially if it is a get method of a smart contract, invoked anonymously), or a partially filled form is displayed, to be explicitly confirmed and submitted by the user (this may be required for payment forms).\n\n#### 4.3.23. POST actions\n\nA ton-site may embed into the HTML pages it returns some usual-looking POST forms, with POST actions referring either to ton-sites, ton-services or smart contracts by means of suitable (TON) URLs. In that case, once the user fills and submits that custom form, the corresponding action is taken, either immediately or after an explicit confirmation.\n\n#### 4.3.24. TON WWW\n\nAll of the above will lead to the creation of a whole web of cross-referencing entities, residing in the TON Network, which would be accessible to the end user through a ton-browser, providing the user with a WWW-like browsing experience. For end users, this will finally make blockchain applications fundamentally similar to the web sites they are already accustomed to.\n\n#### 4.3.25. Advantages of TON WWW\n\nThis \"TON WWW\" of on-chain and off-chain services has some advantages over its conventional counterpart. For example, payments are inherently integrated in the system. User identity can be always presented to the services (by means of automatically generated signatures on the transactions and RPC requests generated), or hidden at will. Services would not need to check and re-check user credentials; these credentials can be published in the blockchain once and for all. User network anonymity can be easily preserved by means of TON Proxy, and all services will be effectively unblockable. Micropayments are also possible and easy, because ton-browsers can be integrated with the TON Payments system.\n\n---\n## 5  TON Payments\n\nThe last component of the TON Project we will briefly discuss in this text is *TON Payments*, the platform for (micro)payment channels and \"lightning network\" value transfers. It would enable \"instant\" payments, without the need to commit all transactions into the blockchain, pay the associated transaction fees (e.g., for the gas consumed), and wait five seconds until the block containing the transactions in question is confirmed.\n\nThe overall overhead of such instant payments is so small that one can use them for micropayments. For example, a TON file-storing service might charge the user for every 128 KiB of downloaded data, or a paid TON Proxy might require some tiny micropayment for every 128 KiB of traffic relayed.\n\nWhile *TON Payments* is likely to be released later than the core components of the TON Project, some considerations need to be made at the very beginning. For example, the TON Virtual Machine (TON VM; cf. [2.1.20](#2-1-20-ton-virtual-machine)), used to execute the code of TON Blockchain smart contracts, must support some special operations with Merkle proofs. If such support is not present in the original design, adding it at a later stage might become problematic (cf. [2.8.16](#2-8-16-complications-of-changing-the-genome-of-a-blockchain-project)). We will see, however, that the TON VM comes with natural support for \"smart\" payment channels (cf. [5.1.9](#5-1-9-ton-vm-support-for-smart-payment-channels)) out of the box.\n\n### 5.1  Payment Channels\n\nWe start with a discussion of point-to-point payment channels, and how they can be implemented in the TON Blockchain.\n\n#### 5.1.1. The idea of a payment channel\n\nSuppose two parties, $A$ and $B$, know that they will need to make a lot of payments to each other in the future. Instead of committing each payment as a transaction in the blockchain, they create a shared \"money pool\" (or perhaps a small private bank with exactly two accounts), and contribute some funds to it: $A$ contributes $a$ coins, and $B$ contributes $b$ coins. This is achieved by creating a special smart contract in the blockchain, and sending the money to it.\n\nBefore creating the \"money pool\", the two sides agree to a certain protocol. They will keep track of the *state* of the pool—that is, of their balances in the shared pool. Originally, the state is $(a,b)$, meaning that $a$ coins actually belong to $A$, and $b$ coins belong to $B$. Then, if $A$ wants to pay $d$ coins to $B$, they can simply agree that the new state is $(a',b')=(a-d,b+d)$. Afterwards, if, say, $B$ wants to pay $d'$ coins to $A$, the state will become $(a'',b'')=(a'+d',b'-d')$, and so on.\n\nAll this updating of balances inside the pool is done completely off-chain. When the two parties decide to withdraw their due funds from the pool, they do so according to the final state of the pool. This is achieved by sending a special message to the smart contract, containing the agreed-upon final state $(a^*,b^*)$ along with the signatures of both $A$ and $B$. Then the smart contract sends $a^*$ coins to $A$, $b^*$ coins to $B$ and self-destructs.\n\nThis smart contract, along with the network protocol used by $A$ and $B$ to update the state of the pool, is a simple *payment channel between $A$ and $B$.* According to the classification described in [4.1.2](#4-1-2-location-of-the-application-on-chain-off-chain-or-mixed), it is a *mixed* service: part of its state resides in the blockchain (the smart contract), but most of its state updates are performed off-chain (by the network protocol). If everything goes well, the two parties will be able to perform as many payments to each other as they want (with the only restriction being that the \"capacity\" of the channel is not overrun—i.e., their balances in the payment channel both remain non-negative), committing only two transactions into the blockchain: one to open (create) the payment channel (smart contract), and another to close (destroy) it.\n\n#### 5.1.2. Trustless payment channels\n\nThe previous example was somewhat unrealistic, because it assumes that both parties are willing to cooperate and will never cheat to gain some advantage. Imagine, for example, that $A$ will choose not to sign the final balance $(a',b')$ with $a'<a$. This would put $B$ in a difficult situation.\n\nTo protect against such scenarios, one usually tries to develop *trustless* payment channel protocols, which do not require the parties to trust each other, and make provisions for punishing any party who would attempt to cheat.\n\nThis is usually achieved with the aid of signatures. The payment channel smart contract knows the public keys of $A$ and $B$, and it can check their signatures if needed. The payment channel protocol requires the parties to sign the intermediate states and send the signatures to each other. Then, if one of the parties cheats—for instance, pretends that some state of the payment channel never existed—its misbehavior can be proved by showing its signature on that state. The payment channel smart contract acts as an \"on-chain arbiter\", able to process complaints of the two parties about each other, and punish the guilty party by confiscating all of its money and awarding it to the other party.\n\n#### 5.1.3. Simple bidirectional synchronous trustless payment channel\n\nConsider the following, more realistic example: Let the state of the payment channel be described by triple $(\\delta_i,i,o_i)$, where $i$ is the sequence number of the state (it is originally zero, and then it is increased by one when a subsequent state appears), $\\delta_i$ is the *channel imbalance* (meaning that $A$ and $B$ own $a+\\delta_i$ and $b-\\delta_i$ coins, respectively), and $o_i$ is the party allowed to generate the next state (either $A$ or $B$). Each state must be signed both by $A$ and $B$ before any further progress can be made.\n\nNow, if $A$ wants to transfer $d$ coins to $B$ inside the payment channel, and the current state is $S_i=(\\delta_i,i,o_i)$ with $o_i=A$, then it simply creates a new state $S_{i+1}=(\\delta_i-d,i+1,o_{i+1})$, signs it, and sends it to $B$ along with its signature. Then $B$ confirms it by signing and sending a copy of its signature to $A$. After that, both parties have a copy of the new state with both of their signatures, and a new transfer may occur.\n\nIf $A$ wants to transfer coins to $B$ in a state $S_i$ with $o_i=B$, then it first asks $B$ to commit a subsequent state $S_{i+1}$ with the same imbalance $\\delta_{i+1}=\\delta_i$, but with $o_{i+1}=A$. After that, $A$ will be able to make its transfer.\n\nWhen the two parties agree to close the payment channel, they both put their special *final* signatures on the state $S_k$ they believe to be final, and invoke the *clean* or *two-sided finalization method* of the payment channel smart contract by sending it the final state along with both final signatures.\n\nIf the other party does not agree to provide its final signature, or simply if it stops responding, it is possible to close the channel unilaterally. For this, the party wishing to do so will invoke the *unilateral finalization* method, sending to the smart contract its version of the final state, its final signature, and the most recent state having a signature of the other party. After that, the smart contract does not immediately act on the final state received. Instead, it waits for a certain period of time (e.g., one day) for the other party to present its version of the final state. When the other party submits its version and it turns out to be compatible with the already submitted version, the \"true\" final state is computed by the smart contract and used to distribute the money accordingly. If the other party fails to present its version of the final state to the smart contract, then the money is redistributed according to the only copy of the final state presented.\n\nIf one of the two parties cheats—for example, by signing two different states as final, or by signing two different next states $S_{i+1}$ and $S'_{i+1}$, or by signing an invalid new state $S_{i+1}$ (e.g., with imbalance $\\delta_{i+1}<-a$ or $>b$)—then the other party may submit proof of this misbehavior to a third method of the smart contract. The guilty party is punished immediately by losing its share in the payment channel completely.\n\nThis simple payment channel protocol is *fair* in the sense that any party can always get its due, with or without the cooperation of the other party, and is likely to lose all of its funds committed to the payment channel if it tries to cheat.\n\n#### 5.1.4. Synchronous payment channel as a simple virtual blockchain with two validators\n\nThe above example of a simple synchronous payment channel can be recast as follows. Imagine that the sequence of states $S_0$, $S_1$, ..., $S_n$ is actually the sequence of blocks of a very simple blockchain. Each block of this blockchain contains essentially only the current state of the blockchain, and maybe a reference to the previous block (i.e., its hash). Both parties $A$ and $B$ act as validators for this blockchain, so every block must collect both of their signatures. The state $S_i$ of the blockchain defines the designated producer $o_i$ for the next block, so there is no race between $A$ and $B$ for producing the next block. Producer $A$ is allowed to create blocks that transfer funds from $A$ to $B$ (i.e., decrease the imbalance: $\\delta_{i+1}\\leq\\delta_i$), and $B$ can only transfer funds from $B$ to $A$ (i.e., increase $\\delta$).\n\nIf the two validators agree on the final block (and the final state) of the blockchain, it is finalized by collecting special \"final\" signatures of the two parties, and submitting them along with the final block to the channel smart contract for processing and re-distributing the money accordingly.\n\nIf a validator signs an invalid block, or creates a fork, or signs two different final blocks, it can be punished by presenting a proof of its misbehavior to the smart contract, which acts as an \"on-chain arbiter\" for the two validators; then the offending party will lose all its money kept in the payment channel, which is analogous to a validator losing its stake.\n\n#### 5.1.5. Asynchronous payment channel as a virtual blockchain with two workchains\n\nThe synchronous payment channel discussed in [5.1.3](#5-1-3-simple-bidirectional-synchronous-trustless-payment-channel) has a certain disadvantage: one cannot begin the next transaction (money transfer inside the payment channel) before the previous one is confirmed by the other party. This can be fixed by replacing the single virtual blockchain discussed in [5.1.4](#5-1-4-synchronous-payment-channel-as-a-simple-virtual-blockchain-with-two-validators) by a system of two interacting virtual workchains (or rather shardchains).\n\nThe first of these workchains contains only transactions by $A$, and its blocks can be generated only by $A$; its states are $S_i=(i,\\phi_i,j,\\psi_j)$, where $i$ is the block sequence number (i.e., the count of transactions, or money transfers, performed by $A$ so far), $\\phi_i$ is the total amount transferred from $A$ to $B$ so far, $j$ is the sequence number of the most recent valid block in $B$'s blockchain that $A$ is aware of, and $\\psi_j$ is the amount of money transferred from $B$ to $A$ in its $j$ transactions. A signature of $B$ put onto its $j$-th block should also be a part of this state. Hashes of the previous block of this workchain and of the $j$-th block of the other workchain may be also included. Validity conditions for $S_i$ include $\\phi_i\\geq 0$, $\\phi_i\\geq\\phi_{i-1}$ if $i>0$, $\\psi_j\\geq0$, and $-a\\leq\\psi_j-\\phi_i\\leq b$.\n\nSimilarly, the second workchain contains only transactions by $B$, and its blocks are generated only by $B$; its states are $T_j=(j,\\psi_j,i,\\phi_i)$, with similar validity conditions.\n\nNow, if $A$ wants to transfer some money to $B$, it simply creates a new block in its workchain, signs it, and sends to $B$, without waiting for confirmation.\n\nThe payment channel is finalized by $A$ signing (its version of) the final state of its blockchain (with its special \"final signature\"), $B$ signing the final state of its blockchain, and presenting these two final states to the clean finalization method of the payment channel smart contract. Unilateral finalization is also possible, but in that case the smart contract will have to wait for the other party to present its version of the final state, at least for some grace period.\n\n#### 5.1.6. Unidirectional payment channels\n\nIf only $A$ needs to make payments to $B$ (e.g., $B$ is a service provider, and $A$ its client), then a unilateral payment channel can be created. Essentially, it is just the first workchain described in [5.1.5](#5-1-5-asynchronous-payment-channel-as-a-virtual-blockchain-with-two-workchains) without the second one. Conversely, one can say that the asynchronous payment channel described in [5.1.5](#5-1-5-asynchronous-payment-channel-as-a-virtual-blockchain-with-two-workchains) consists of two unidirectional payment channels, or \"half-channels\", managed by the same smart contract.\n\n#### 5.1.7. More sophisticated payment channels. Promises\n\nWe will see later in [5.2.4](#5-2-4-chain-money-transfers) that the \"lightning network\" (cf. [5.2](#5-2-payment-channel-network-or-lightning-network)), which enables instant money transfers through chains of several payment channels, requires higher degrees of sophistication from the payment channels involved.\n\nIn particular, we want to be able to commit \"promises\", or \"conditional money transfers\": $A$ agrees to send $c$ coins to $B$, but $B$ will get the money only if a certain condition is fulfilled, for instance, if $B$ can present some string $u$ with $\\text{Hash}(u)=v$ for a known value of $v$. Otherwise, $A$ can get the money back after a certain period of time.\n\nSuch a promise could easily be implemented on-chain by a simple smart contract. However, we want promises and other kinds of conditional money transfers to be possible off-chain, in the payment channel, because they considerably simplify money transfers along a chain of payment channels existing in the \"lightning network\" (cf. [5.2.4](#5-2-4-chain-money-transfers)).\n\nThe \"payment channel as a simple blockchain\" picture outlined in [5.1.4](#5-1-4-synchronous-payment-channel-as-a-simple-virtual-blockchain-with-two-validators) and [5.1.5](#5-1-5-asynchronous-payment-channel-as-a-virtual-blockchain-with-two-workchains) becomes convenient here. Now we consider a more complicated virtual blockchain, the state of which contains a set of such unfulfilled \"promises\", and the amount of funds locked in such promises. This blockchain—or the two workchains in the asynchronous case—will have to refer explicitly to the previous blocks by their hashes. Nevertheless, the general mechanism remains the same.\n\n#### 5.1.8. Challenges for the sophisticated payment channel smart contracts\n\nNotice that, while the final state of a sophisticated payment channel is still small, and the \"clean\" finalization is simple (if the two sides have agreed on their amounts due, and both have signed their agreement, nothing else remains to be done), the unilateral finalization method and the method for punishing fraudulent behavior need to be more complex. Indeed, they must be able to accept Merkle proofs of misbehavior, and to check whether the more sophisticated transactions of the payment channel blockchain have been processed correctly.\n\nIn other words, the payment channel smart contract must be able to work with Merkle proofs, to check their \"hash validity\", and must contain an implementation of $\\mathit{ev\\_trans}$ and $\\mathit{ev\\_block}$ functions (cf. [2.2.6](#2-2-6-blocks-and-transactions-as-state-transformation-operators)) for the payment channel (virtual) blockchain.\n\n#### 5.1.9. TON VM support for \"smart\" payment channels\n\nThe TON VM, used to run the code of TON Blockchain smart contracts, is up to the challenge of executing the smart contracts required for \"smart\", or sophisticated, payment channels (cf. [5.1.8](#5-1-8-challenges-for-the-sophisticated-payment-channel-smart-contracts)).\n\nAt this point the \"everything is a bag of cells\" paradigm ([cf. 2.5.14](#2-5-14-everything-is-a-bag-of-cells-philosophy)) becomes extremely convenient. Since all blocks (including the blocks of the ephemeral payment channel blockchain) are represented as bags of cells (and described by some algebraic data types), and the same holds for messages and Merkle proofs as well, a Merkle proof can easily be embedded into an inbound message sent to the payment channel smart contract. The \"hash condition\" of the Merkle proof will be checked automatically, and when the smart contract accesses the \"Merkle proof\" presented, it will work with it as if it were a value of the corresponding algebraic data type—albeit incomplete, with some subtrees of the tree replaced by special nodes containing the Merkle hash of the omitted subtree. Then the smart contract will work with that value, which might represent, for instance, a block of the payment channel (virtual) blockchain along with its state, and will evaluate the $\\mathit{ev\\_block}$ function (cf. [2.2.6](#2-2-6-blocks-and-transactions-as-state-transformation-operators)) of that blockchain on this block and the previous state. Then either the computation finishes, and the final state can be compared with that asserted in the block, or an \"absent node\" exception is thrown while attempting to access an absent subtree, indicating that the Merkle proof is invalid.\n\nIn this way, the implementation of the verification code for smart payment channel blockchains turns out to be quite straightforward using TON Blockchain smart contracts. One might say that *the TON Virtual Machine comes with built-in support for checking the validity of other simple blockchains.* The only limiting factor is the size of the Merkle proof to be incorporated into the inbound message to the smart contract (i.e., into the transaction).\n\n#### 5.1.10. Simple payment channel within a smart payment channel\n\nWe would like to discuss the possibility of creating a simple (synchronous or asynchronous) payment channel inside an existing payment channel.\n\nWhile this may seem somewhat convoluted, it is not much harder to understand and implement than the \"promises\" discussed in [5.1.7](#5-1-7-more-sophisticated-payment-channels-promises). Essentially, instead of promising to pay $c$ coins to the other party if a solution to some hash problem is presented, $A$ promises to pay up to $c$ coins to $B$ according to the final settlement of some other (virtual) payment channel blockchain. Generally speaking, this other payment channel blockchain need not even be between $A$ and $B$; it might involve some other parties, say, $C$ and $D$, willing to commit $c$ and $d$ coins into their simple payment channel, respectively. (This possibility is exploited later in [5.2.5](#5-2-5-virtual-payment-channels-inside-a-chain-of-payment-channels).)\n\nIf the encompassing payment channel is asymmetric, two promises need to be committed into the two workchains: $A$ will promise to pay $-\\delta$ coins to $B$ if the final settlement of the \"internal\" simple payment channel yields a negative final imbalance $\\delta$ with $0\\leq-\\delta\\leq c$; and $B$ will have to promise to pay $\\delta$ to $A$ if $\\delta$ is positive. On the other hand, if the encompassing payment channel is symmetric, this can be done by committing a single \"simple payment channel creation\" transaction with parameters $(c,d)$ into the single payment channel blockchain by $A$ (which would freeze $c$ coins belonging to $A$), and then committing a special \"confirmation transaction\" by $B$ (which would freeze $d$ coins of $B$).\n\nWe expect the internal payment channel to be extremely simple (e.g., the simple synchronous payment channel discussed in [5.1.3](#5-1-3-simple-bidirectional-synchronous-trustless-payment-channel)), to minimize the size of Merkle proofs to be submitted. The external payment channel will have to be \"smart\" in the sense described in [5.1.7](#5-1-7-more-sophisticated-payment-channels-promises).\n\n### 5.2  Payment Channel Network, or \"Lightning Network\"\n\nNow we are ready to discuss the \"lightning network\" of TON Payments that enables instant money transfers between any two participating nodes.\n\n#### 5.2.1. Limitations of payment channels\n\nA payment channel is useful for parties who expect a lot of money transfers between them. However, if one needs to transfer money only once or twice to a particular recipient, creating a payment channel with her would be impractical. Among other things, this would imply freezing a significant amount of money in the payment channel, and would require at least two blockchain transactions anyway.\n\n#### 5.2.2. Payment channel networks, or \"lightning networks\"\n\nPayment channel networks overcome the limitations of payment channels by enabling money transfers along *chains* of payment channels. If $A$ wants to transfer money to $E$, she does not need to establish a payment channel with $E$. It would be sufficient to have a chain of payment channels linking $A$ with $E$ through several intermediate nodes—say, four payment channels: from $A$ to $B$, from $B$ to $C$, from $C$ to $D$ and from $D$ to $E$.\n\n#### 5.2.3. Overview of payment channel networks\n\nRecall that a *payment channel network*, known also as a \"lightning network\", consists of a collection of participating nodes, some of which have established long-lived payment channels between them. We will see in a moment that these payment channels will have to be \"smart\" in the sense of [5.1.7](#5-1-7-more-sophisticated-payment-channels-promises). When a participating node $A$ wants to transfer money to any other participating node $E$, she tries to find a path linking $A$ to $E$ inside the payment channel network. When such a path is found, she performs a \"chain money transfer\" along this path.\n\n#### 5.2.4. Chain money transfers\n\nSuppose that there is a chain of payment channels from $A$ to $B$, from $B$ to $C$, from $C$ to $D$, and from $D$ to $E$. Suppose, further, that $A$ wants to transfer $x$ coins to $E$.\n\nA simplistic approach would be to transfer $x$ coins to $B$ along the existing payment channel, and ask him to forward the money further to $C$. However, it is not evident why $B$ would not simply take the money for himself. Therefore, one must employ a more sophisticated approach, not requiring all parties involved to trust each other.\n\nThis can be achieved as follows. $A$ generates a large random number $u$ and computes its hash $v=\\text{Hash}(u)$. Then she creates a promise to pay $x$ coins to $B$ if a number $u$ with hash $v$ is presented (cf. [5.1.7](#5-1-7-more-sophisticated-payment-channels-promises)), inside her payment channel with $B$. This promise contains $v$, but not $u$, which is still kept secret.\n\nAfter that, $B$ creates a similar promise to $C$ in their payment channel. He is not afraid to give such a promise, because he is aware of the existence of a similar promise given to him by $A$. If $C$ ever presents a solution of the hash problem to collect $x$ coins promised by $B$, then $B$ will immediately submit this solution to $A$ to collect $x$ coins from $A$.\n\nThen similar promises of $C$ to $D$ and of $D$ to $E$ are created. When the promises are all in place, $A$ triggers the transfer by communicating the solution $u$ to all parties involved—or just to $E$.\n\nSome minor details are omitted in this description. For example, these promises must have different expiration times, and the amount promised might slightly differ along the chain ($B$ might promise only $x-\\epsilon$ coins to $C$, where $\\epsilon$ is a small pre-agreed transit fee). We ignore such details for the time being, because they are not too relevant for understanding how payment channels work and how they can be implemented in TON.\n\n#### 5.2.5. Virtual payment channels inside a chain of payment channels\n\nNow suppose that $A$ and $E$ expect to make a lot of payments to each other. They might create a new payment channel between them in the blockchain, but this would still be quite expensive, because some funds would be locked in this payment channel. Another option would be to use chain money transfers described in [5.2.4](#5-2-4-chain-money-transfers) for each payment. However, this would involve a lot of network activity and a lot of transactions in the virtual blockchains of all payment channels involved.\n\nAn alternative is to create a virtual payment channel inside the chain linking $A$ to $E$ in the payment channel network. For this, $A$ and $E$ create a (virtual) blockchain for their payments, as if they were going to create a payment channel in the blockchain. However, instead of creating a payment channel smart contract in the blockchain, they ask all intermediate payment channels—those linking $A$ to $B$, $B$ to $C$, etc.—to create simple payment channels inside them, bound to the virtual blockchain created by $A$ and $E$ (cf. [5.1.10](#5-1-10-simple-payment-channel-within-a-smart-payment-channel)). In other words, now a promise to transfer money according to the final settlement between $A$ and $E$ exists inside every intermediate payment channel.\n\nIf the virtual payment channel is unidirectional, such promises can be implemented quite easily, because the final imbalance $\\delta$ is going to be non-positive, so simple payment channels can be created inside intermediate payment channels in the same order as described in [5.2.4](#5-2-4-chain-money-transfers). Their expiration times can also be set in the same way.\n\nIf the virtual payment channel is bidirectional, the situation is slightly more complicated. In that case, one should split the promise to transfer $\\delta$ coins according to the final settlement into two half-promises, as explained in [5.1.10](#5-1-10-simple-payment-channel-within-a-smart-payment-channel): to transfer $\\delta^-=\\max(0,-\\delta)$ coins in the forward direction, and to transfer $\\delta^+=\\max(0,\\delta)$ in the backward direction. These half-promises can be created in the intermediate payment channels independently, one chain of half-promises in the direction from $A$ to $E$, and the other chain in the opposite direction.\n\n#### 5.2.6. Finding paths in the lightning network\n\nOne point remains undiscussed so far: how will $A$ and $E$ find a path connecting them in the payment network? If the payment network is not too large, an OSPF-like protocol can be used: all nodes of the payment network create an overlay network (cf. [3.3.17](#3-3-17-overlay-networks-within-overlay-networks)), and then every node propagates all available link (i.e., participating payment channel) information to its neighbors by a gossip protocol. Ultimately, all nodes will have a complete list of all payment channels participating in the payment network, and will be able to find the shortest paths by themselves—for example, by applying a version of Dijkstra's algorithm modified to take into account the \"capacities\" of the payment channels involved (i.e., the maximal amounts that can be transferred along them). Once a candidate path is found, it can be probed by a special ADNL datagram containing the full path, and asking each intermediate node to confirm the existence of the payment channel in question, and to forward this datagram further according to the path. After that, a chain can be constructed, and a protocol for chain transfers (cf. [5.2.4](#5-2-4-chain-money-transfers)), or for creating a virtual payment channel inside a chain of payment channels (cf. [5.2.5](#5-2-5-virtual-payment-channels-inside-a-chain-of-payment-channels)), can be run.\n\n#### 5.2.7. Optimizations\n\nSome optimizations might be done here. For example, only transit nodes of the lightning network need to participate in the OSPF-like protocol discussed in [5.2.6](#5-2-6-finding-paths-in-the-lightning-network). Two \"leaf\" nodes wishing to connect through the lightning network would communicate to each other the lists of transit nodes they are connected to (i.e., with which they have established payment channels). Then paths connecting transit nodes from one list to transit nodes from the other list can be inspected as outlined above in [5.2.6](#5-2-6-finding-paths-in-the-lightning-network).\n\n#### 5.2.8. Conclusion\n\nWe have outlined how the blockchain and network technologies of the TON project are adequate to the task of creating *TON Payments*, a platform for off-chain instant money transfers and micropayments. This platform can be extremely useful for services residing in the TON ecosystem, allowing them to easily collect micropayments when and where required.\n\n## Conclusion\n\nWe have proposed a scalable multi-blockchain architecture capable of supporting a massively popular cryptocurrency and decentralized applications with user-friendly interfaces.\n\nTo achieve the necessary scalability, we proposed the *TON Blockchain*, a \"tightly-coupled\" multi-blockchain system (cf. [2.8.14](#2-8-14-interaction-between-blockchains-loosely-coupled-and-tightly-coupled-systems)) with bottom-up approach to sharding (cf. [2.8.12](#2-8-12-sharding-support) and [2.1.2](#2-1-2-infinite-sharding-paradigm)). To further increase potential performance, we introduced the 2-blockchain mechanism for replacing invalid blocks (cf. [2.1.17](#2-1-17-correcting-invalid-shardchain-blocks)) and Instant Hypercube Routing for faster communication between shards (cf. [2.4.20](#2-4-20-instant-hypercube-routing-fast-path-for-messages)). A brief comparison of the TON Blockchain to existing and proposed blockchain projects (cf. [2.8](#2-8-classification-of-blockchain-projects) and [2.9](#2-9-comparison-to-other-blockchain-projects)) highlights the benefits of this approach for systems that seek to handle millions of transactions per second.\n\nThe *TON Network*, described in Chapter [3](#3-ton-networking), covers the networking demands of the proposed multi-blockchain infrastructure. This network component may also be used in combination with the blockchain to create a wide spectrum of applications and services, impossible using the blockchain alone (cf. [2.9.13](#2-9-13-is-it-possible-to-upload-facebook-into-a-blockchain)). These services, discussed in Chapter [4](#4-ton-services-and-applications), include *TON DNS*, a service for translating human-readable object identifiers into their addresses; *TON Storage*, a distributed platform for storing arbitrary files; *TON Proxy*, a service for anonymizing network access and accessing TON-powered services; and *TON Payments* (cf. Chapter [5](#5-ton-payments)), a platform for instant off-chain money transfers across the TON ecosystem that applications may use for micropayments.\n\nThe TON infrastructure allows for specialized light client wallet and \"ton-browser\" desktop and smartphone applications that enable a browser-like experience for the end user (cf. [4.3.24](#4-3-24-ton-www)), making cryptocurrency payments and interaction with smart contracts and other services on the TON Platform accessible to the mass user. Such a light client can be integrated into the Telegram Messenger client (cf. [4.3.19](#4-3-19-a-light-wallet-and-ton-entity-explorer-can-be-built-into-telegram-messenger-clients)), thus eventually bringing a wealth of blockchain-based applications to hundreds of millions of users.\n\n---\n\n## A  The TON Coin, or the Gram\n\nThe principal cryptocurrency of the TON Blockchain, and in particular of its masterchain and basic workchain, is the *TON Coin*, also known as the *Gram* (GRM). It is used to make deposits required to become a validator; transaction fees, gas payments (i.e., smart-contract message processing fees) and persistent storage payments are also usually collected in Grams.\n\n### A.1. Subdivision and terminology\n\nA *Gram* is subdivided into one billion ($10^9$) smaller units, called *nanograms*, *ngrams* or simply *nanos*. All transfers and account balances are expressed as non-negative integer multiples of nanos. Other units include:\n\n- A *nano*, *ngram* or *nanogram* is the smallest unit, equal to $10^{-9}$ Grams.\n- A *micro* or *microgram* equals one thousand ($10^3$) nanos.\n- A *milli* is one million ($10^6$) nanos, or one thousandth part ($10^{-3}$) of a Gram.\n- A *Gram* equals one billion ($10^9$) nanos.\n- A *kilogram*, or *kGram*, equals one thousand ($10^3$) Grams.\n- A *megagram*, or *MGram*, equals one million ($10^6$) Grams, or $10^{15}$ nanos.\n- Finally, a *gigagram*, or *GGram*, equals one billion ($10^9$) Grams, or $10^{18}$ nanos.\n\nThere will be no need for larger units, because the initial supply of Grams will be limited to five billion ($5\\cdot10^9$) Grams (i.e., 5 Gigagrams).\n\n### A.2. Smaller units for expressing gas prices\n\nIf the necessity for smaller units arises, \"specks\" equal to $2^{-16}$ nanograms will be used. For example, gas prices may be indicated in specks. However, the actual fee to be paid, computed as the product of the gas price and the amount of gas consumed, will be always rounded down to the nearest multiple of $2^{16}$ specks and expressed as an integer number of nanos.\n\n### A.3. Original supply, mining rewards and inflation\n\nThe total supply of Grams is originally limited to $5$ Gigagrams (i.e., five billion Grams or $5\\cdot10^{18}$ nanos).\n\nThis supply will increase very slowly, as rewards to validators for mining new masterchain and shardchain blocks accumulate. These rewards would amount to approximately $20\\%$ (the exact number may be adjusted in future) of the validator's stake per year, provided the validator diligently performs its duties, signs all blocks, never goes offline and never signs invalid blocks. In this way, the validators will have enough profit to invest into better and faster hardware needed to process the ever growing quantity of users' transactions.\n\nWe expect that at most $10\\%$<sup>[37](#fn37)</sup> of the total supply of Grams, on average, will be bound in validator stakes at any given moment. This will produce an inflation rate of $2\\%$ per year, and as a result, will double the total supply of Grams (to ten Gigagrams) in 35 years. Essentially, this inflation represents a payment made by all members of the community to the validators for keeping the system up and running.\n\nOn the other hand, if a validator is caught misbehaving, a part or all of its stake will be taken away as a punishment, and a larger portion of it will subsequently be \"burned\", decreasing the total supply of Grams. This would lead to deflation. A smaller portion of the fine may be redistributed to the validator or the \"fisherman\" who committed a proof of the guilty validator's misbehavior.\n\n### A.4. Original price of Grams\n\nThe price of the first Gram to be sold will equal approximately \\$0.1 USD. Every subsequent Gram to be sold (by the TON Reserve, controlled by the TON Foundation) will be priced one billionth higher than the previous one. In this way, the $n$-th Gram to be put into circulation will be sold at approximately:\n\n$$\np(n) \\approx 0.1 \\cdot (1 + 10^{-9})^n \\quad \\text{USD} \\tag{26}\n$$\n\nor an approximately equivalent (because of quickly changing market exchange rates) amount of other (crypto)currencies, such as BTC or ETH.\n\n\n#### A.4.1. Exponentially priced cryptocurrencies\n\nWe say that the Gram is an *exponentially priced cryptocurrency*, meaning that the price of the $n$-th Gram to be put into circulation is approximately $p(n)$ given by the formula\n\n$$\np(n)=p_0\\cdot e^{\\alpha n} \\tag{27}\n$$\n\nwith specific values $p_0=0.1$ USD and $\\alpha=10^{-9}$.\n\nMore precisely, a small fraction $dn$ of a new coin is worth $p(n)\\,dn$ dollars, once $n$ coins are put into circulation. (Here $n$ is not necessarily an integer.)\n\nOther important parameters of such a cryptocurrency include $n$, the total number of coins in circulation, and $N\\geq n$, the total number of coins that can exist. For the Gram, $N=5\\cdot 10^9$.\n\n#### A.4.2. Total price of first $n$ coins\n\nThe total price $T(n)=\\int_0^n p(n)\\,dn\\approx p(0)+p(1)+\\cdots+p(n-1)$ of the first $n$ coins of an exponentially priced cryptocurrency (e.g., the Gram) to be put into circulation can be computed by\n\n$$\nT(n)=p_0\\cdot\\alpha^{-1}(e^{\\alpha n}-1) \\tag{28}\n$$\n\n#### A.4.3. Total price of next $\\Delta n$ coins\n\nThe total price $T(n+\\Delta n)-T(n)$ of $\\Delta n$ coins put into circulation after $n$ previously existing coins can be computed by\n\n$$\nT(n+\\Delta n)-T(n)=p_0\\cdot\\alpha^{-1}(e^{\\alpha(n+\\Delta n)}-e^{\\alpha n})=p(n)\\cdot\\alpha^{-1}(e^{\\alpha\\,\\Delta n}-1) \\quad (29)\n$$\n\n#### A.4.4. Buying next coins with total value $T$\n\nSuppose that $n$ coins have already been put into circulation, and that one wants to spend $T$ (dollars) on buying new coins. The quantity of newly-obtained coins $\\Delta n$ can be computed by putting $T(n+\\Delta n)-T(n)=T$ into the ([29](#a-4-3-total-price-of-next-coins)), yielding\n\n$$\n\\Delta n=\\alpha^{-1}\\log\\left(1+\\frac{T\\cdot\\alpha}{p(n)}\\right) \\tag{30}\n$$\n\nOf course, if $T\\lll p(n)\\alpha^{-1}$, then $\\Delta n\\approx T/p(n)$.\n\n#### A.4.5. Market price of Grams\n\nOf course, if the free market price falls below $p(n):=0.1\\cdot (1+10^{-9})^n$, once $n$ Grams are put into circulation, nobody would buy new Grams from the TON Reserve; they would choose to buy their Grams on the free market instead, without increasing the total quantity of Grams in circulation. On the other hand, the market price of a Gram cannot become much higher than $p(n)$, otherwise it would make sense to obtain new Grams from the TON Reserve. This means that the market price of Grams would not be subject to sudden spikes (and drops); this is important because stakes (validator deposits) are frozen for at least one month, and gas prices cannot change too fast either. So, the overall economic stability of the system requires some mechanism that would prevent the exchange rate of the Gram from changing too drastically, such as the one described above.\n\n#### A.4.6. Buying back the Grams\n\nIf the market price of the Gram falls below $0.5\\cdot p(n)$, when there are a total of $n$ Grams in circulation (i.e., not kept on a special account controlled by the TON Reserve), the TON Reserve reserves the right to buy some Grams back and decrease $n$, the total quantity of Grams in circulation. This may be required to prevent sudden falls of the Gram exchange rate.\n\n#### A.4.7. Selling new Grams at a higher price\n\nThe TON Reserve will sell only up to one half (i.e., $2.5\\cdot10^9$ Grams) of the total supply of Grams according to the price formula ([26](#a-4-original-price-of-grams)). It reserves the right not to sell any of the remaining Grams at all, or to sell them at a higher price than $p(n)$, but never at a lower price (taking into account the uncertainty of quickly changing exchange rates). The rationale here is that once at least half of all Grams have been sold, the total value of the Gram market will be sufficiently high, and it will be more difficult for outside forces to manipulate the exchange rate than it may be at the very beginning of the Gram's deployment.\n\n### A.5. Using unallocated Grams\n\nThe TON Reserve will use the bulk of \"unallocated\" Grams (approximately $5\\cdot10^9-n$ Grams)—i.e., those residing in the special account of the TON Reserve and some other accounts explicitly linked to it—only as validator stakes (because the TON Foundation itself will likely have to provide most of the validators during the first deployment phase of the TON Blockchain), and for voting in the masterchain for or against proposals concerning changes in the \"configurable parameters\" and other protocol changes, in the way determined by the TON Foundation (i.e., its creators—the development team). This also means that the TON Foundation will have a majority of votes during the first deployment phase of the TON Blockchain, which may be useful if a lot of parameters end up needing to be adjusted, or if the need arises for hard or soft forks. Later, when less than half of all Grams remain under control of the TON Foundation, the system will become more democratic. Hopefully it will have become more mature by then, without the need to adjust parameters too frequently.\n\n#### A.5.1. Some unallocated Grams will be given to developers\n\nA predefined (relatively small) quantity of \"unallocated\" Grams (e.g., 200 Megagrams, equal to 4% of the total supply) will be transferred during the deployment of the TON Blockchain to a special account controlled by the TON Foundation, and then some \"rewards\" may be paid from this account to the developers of the open source TON software, with a minimum two-year vesting period.\n\n#### A.5.2. The TON Foundation needs Grams for operational purposes\n\nRecall that the TON Foundation will receive the fiat and cryptocurrency obtained by selling Grams from the TON Reserve, and will use them for the development and deployment of the TON Project. For instance, the original set of validators, as well as an initial set of TON Storage and TON Proxy nodes may be installed by the TON Foundation.\n\nWhile this is necessary for the quick start of the project, the ultimate goal is to make the project as decentralized as possible. To this end, the TON Foundation may need to encourage installation of third-party validators and TON Storage and TON Proxy nodes—for example, by paying them for storing old blocks of the TON Blockchain or proxying network traffic of a selected subset of services. Such payments will be made in Grams; therefore, the TON Foundation will need a significant amount of Grams for operational purposes.\n\n#### A.5.3. Taking a pre-arranged amount from the Reserve\n\nThe TON Foundation will transfer to its account a small part of the TON Reserve—say, 10% of all coins (i.e. 500 Megagrams) after the end of the initial sale of Grams—to be used for its own purposes as outlined in [A.5.2](#a-5-2-the-ton-foundation-needs-grams-for-operational-purposes). This is best done simultaneously with the transfer of the funds intended for TON developers, as mentioned in [A.5.1](#a-5-1-some-unallocated-grams-will-be-given-to-developers).\n\nAfter the transfers to the TON Foundation and the TON developers, the TON Reserve price $p(n)$ of the Gram will immediately rise by a certain amount, known in advance. For example, if 10% of all coins are transferred for the purposes of the TON Foundation, and 4% are transferred for the encouragement of the developers, then the total quantity $n$ of coins in circulation will immediately increase by $\\Delta n=7\\cdot10^8$, with the price of the Gram multiplying by $e^{\\alpha\\,\\Delta n}=e^{0.7}\\approx 2$ (i.e, doubling).\n\nThe remaining \"unallocated\" Grams will be used by the TON Reserve as explained above in [A.5](#a-5-using-unallocated-grams). If the TON Foundation needs any more Grams thereafter, it will simply convert into Grams some of the funds it had previously obtained during the sale of the coins, either on the free market or by buying Grams from the TON Reserve. To prevent excessive centralization, the TON Foundation will never endeavour to have more than 10% of the total amount of Grams (i.e., 500 Megagrams) on its account.\n\n### A.6. Bulk sales of Grams\n\nWhen a lot of people simultaneously want to buy large amounts of Grams from the TON Reserve, it makes sense not to process their orders immediately, because this would lead to results very dependent on the timing of specific orders and their processing sequence.\n\nInstead, orders for buying Grams may be collected during some pre-defined period of time (e.g., a day or a month) and then processed all together at once. If $k$ orders with $i$-th order worth $T_i$ dollars arrive, then the total amount $T=T_1+T_2+\\cdots+T_k$ is used to buy $\\Delta n$ new coins according to ([30](#a-4-4-buying-next-coins-with-total-value)), and the sender of the $i$-th order is allotted $\\Delta n\\cdot T_i/T$ of these coins. In this way, all buyers obtain their Grams at the same average price of $T/\\Delta n$ USD per Gram.\n\nAfter that, a new round of collecting orders for buying new Grams begins.\n\nWhen the total value of Gram buying orders becomes low enough, this system of \"bulk sales\" may be replaced with a system of immediate sales of Grams from the TON Reserve according to the formula ([30](#a-4-4-buying-next-coins-with-total-value)).\n\nThe \"bulk sales\" mechanism will probably be used extensively during the initial phase of collecting investments in the TON Project.\n\n---\n\n## References\n\n<span id=\"ref-1\">[1]</span> K. Birman, *Reliable Distributed Systems: Technologies, Web Services and Applications*, Springer, 2005.\n\n<span id=\"ref-2\">[2]</span> V. Buterin, *Ethereum: A next-generation smart contract and decentralized application platform*, https://github.com/ethereum/wiki/wiki/White-Paper, 2013.\n\n<span id=\"ref-3\">[3]</span> M. Ben-Or, B. Kelmer, T. Rabin, *Asynchronous secure computations with optimal resilience*, in *Proceedings of the thirteenth annual ACM symposium on Principles of distributed computing*, p. 183–192. ACM, 1994.\n\n<span id=\"ref-4\">[4]</span> M. Castro, B. Liskov, et al., *Practical byzantine fault tolerance*, Proceedings of the Third Symposium on Operating Systems Design and Implementation (1999), p. 173–186, available at http://pmg.csail.mit.edu/papers/osdi99.pdf.\n\n<span id=\"ref-5\">[5]</span> EOS.IO, *EOS.IO technical white paper*, https://github.com/EOSIO/Documentation/blob/master/TechnicalWhitePaper.md, 2017.\n\n<span id=\"ref-6\">[6]</span> D. Goldschlag, M. Reed, P. Syverson, *Onion Routing for Anonymous and Private Internet Connections*, Communications of the ACM, **42**, num. 2 (1999), http://www.onion-router.net/Publications/CACM-1999.pdf.\n\n<span id=\"ref-7\">[7]</span> L. Lamport, R. Shostak, M. Pease, *The byzantine generals problem*, ACM Transactions on Programming Languages and Systems, **4/3** (1982), p. 382–401.\n\n<span id=\"ref-8\">[8]</span> S. Larimer, *The history of BitShares*, https://docs.bitshares.org/bitshares/history.html, 2013.\n\n<span id=\"ref-9\">[9]</span> M. Luby, A. Shokrollahi, et al., *RaptorQ forward error correction scheme for object delivery*, IETF RFC 6330, https://tools.ietf.org/html/rfc6330, 2011.\n\n<span id=\"ref-10\">[10]</span> P. Maymounkov, D. Mazières, *Kademlia: A peer-to-peer information system based on the XOR metric*, in *IPTPS '01 revised papers from the First International Workshop on Peer-to-Peer Systems*, p. 53–65, available at http://pdos.csail.mit.edu/~petar/papers/maymounkov-kademlia-lncs.pdf, 2002.\n\n<span id=\"ref-11\">[11]</span> A. Miller, Yu Xia, et al., *The honey badger of BFT protocols*, Cryptology e-print archive 2016/99, https://eprint.iacr.org/2016/199.pdf, 2016.\n\n<span id=\"ref-12\">[12]</span> S. Nakamoto, *Bitcoin: A peer-to-peer electronic cash system*, https://bitcoin.org/bitcoin.pdf, 2008.\n\n<span id=\"ref-13\">[13]</span> S. Peyton Jones, *Implementing lazy functional languages on stock hardware: the Spineless Tagless G-machine*, Journal of Functional Programming **2** (2), p. 127–202, 1992.\n\n<span id=\"ref-14\">[14]</span> A. Shokrollahi, M. Luby, *Raptor Codes*, IEEE Transactions on Information Theory **6**, no. 3–4 (2006), p. 212–322.\n\n<span id=\"ref-15\">[15]</span> M. van Steen, A. Tanenbaum, *Distributed Systems, 3rd ed.*, 2017.\n\n<span id=\"ref-16\">[16]</span> The Univalent Foundations Program, *Homotopy Type Theory: Univalent Foundations of Mathematics*, Institute for Advanced Study, 2013, available at https://homotopytypetheory.org/book.\n\n<span id=\"ref-17\">[17]</span> G. Wood, *PolkaDot: vision for a heterogeneous multi-chain framework*, draft 1, https://github.com/w3f/polkadot-white-paper/raw/master/PolkaDotPaper.pdf, 2016.\n\n----\n\n## Footnotes\n\n<span id=\"fn1\">1.</span> https://github.com/ethereum/wiki/wiki/Sharding-FAQ [Back ↑](#2-1-1-list-of-blockchain-types)\n\n<span id=\"fn2\">2.</span> Actually, two-thirds by stake is enough to achieve consensus, but an effort is made to collect as many signatures as possible. [Back ↑](#2-1-15-generation-of-new-blocks-by-validators)\n\n<span id=\"fn3\">3.</span> https://coq.inria.fr [Back ↑](#2-2-4-dependent-type-theory-coq-and-tl)\n\n<span id=\"fn4\">4.</span> https://core.telegram.org/mtproto/TL [Back ↑](#2-2-4-dependent-type-theory-coq-and-tl)\n\n<span id=\"fn5\">5.</span> One can show that this encoding is optimal for approximately half of all edge labels of a Patricia tree with random or consecutive indices. Remaining edge labels are likely to be long (i.e., almost 256 bits long). Therefore, a nearly optimal encoding for edge labels is to use the above code with prefix 0 for \"short\" bit strings, and encode 1, then nine bits containing length $l=|s|$ of bitstring $s$, and then the $l$ bits of $s$ for \"long\" bitstrings (with $l\\geq10$). [Back ↑](#2-3-8-merkle-patricia-trees)\n\n<span id=\"fn6\">6.</span> A *light node* is a node that does not keep track of the full state of a shardchain; instead, it keeps minimal information such as the hashes of the several most recent blocks, and relies on information obtained from full nodes when it becomes necessary to inspect some parts of the full state. [Back ↑](#2-3-10-merkle-proofs)\n\n<span id=\"fn7\">7.</span> A *full node* is a node keeping track of the complete up-to-date state of the shardchain in question. [Back ↑](#2-3-10-merkle-proofs)\n\n<span id=\"fn8\">8.</span> These two descriptor bytes, present in any TVM cell, describe only the total number of references and the total number of raw bytes; references are kept together either before or after all raw bytes. [Back ↑](#2-3-12-peculiarities-of-ton-vm)\n\n<span id=\"fn9\">9.</span> Actually, $\\text{Leaf}$ and $\\text{Node}$ are constructors of an auxiliary type, $\\text{HashmapAux}(n,X)$. Type $\\text{Hashmap}(n,X)$ has constructors $\\text{Root}$ and $\\text{EmptyRoot}$, with $\\text{Root}$ containing a value of type $\\text{HashmapAux}(n,X)$. [Back ↑](#2-3-12-peculiarities-of-ton-vm)\n\n<span id=\"fn10\">10.</span> Logically; the \"bag of cells\" representation described in [2.5.5](#2-5-5-low-level-perspective%3A-bag-of-cells) identifies all duplicate cells, transforming this tree into a directed acyclic graph (dag) when serialized. [Back ↑](#2-3-14-tvm-cells)\n\n<span id=\"fn11\">11.</span> A more expensive alternative is to publish such a \"global\" smart contract in the masterchain. [Back ↑](#2-3-18-local-and-global-smart-contracts-smart-contract-instances)\n\n<span id=\"fn12\">12.</span> This is a sort of \"broadcast\" feature for all shards, and as such, it must be quite expensive. [Back ↑](#2-3-18-local-and-global-smart-contracts-smart-contract-instances)\n\n<span id=\"fn13\">13.</span> The above needs to be literally true only for the basic workchain and its shardchains; other workchains may provide other ways of creating messages. [Back ↑](#2-4-11-creating-messages-smart-contracts-and-transactions)\n\n<span id=\"fn14\">14.</span> As a degenerate case, this shardchain may coincide with the originating shardchain—for example, if we are working inside a workchain which has not yet been split. [Back ↑](#2-4-12-delivering-messages)\n\n<span id=\"fn15\">15.</span> This is not necessarily the final version of the algorithm used to compute the next hop for hypercube routing. In particular, hexadecimal digits may be replaced by $r$-bit groups, with $r$ a configurable parameter, not necessarily equal to four. [Back ↑](#2-4-19-hypercube-routing-slow-path-for-messages-with-assured-delivery)\n\n<span id=\"fn16\">16.</span> However, the validators have some incentive to do so as soon as possible, because they will be able to collect all forwarding fees associated with the message that have not yet been consumed along the slow path. [Back ↑](#2-4-20-instant-hypercube-routing-fast-path-for-messages)\n\n<span id=\"fn17\">17.</span> In fact, one might temporarily or permanently disable the \"instant delivery\" mechanism altogether, and the system would continue working, albeit more slowly. [Back ↑](#2-4-20-instant-hypercube-routing-fast-path-for-messages)\n\n<span id=\"fn18\">18.</span> One can show that, if Merkle proofs for all data stored in a tree of cells are needed equally often, one should use cells with $b+ch\\approx 2(h+r)$ to minimize average Merkle proof size, where $h=32$ is the hash size in bytes, and $r\\approx4$ is the \"byte size\" of a cell reference. In other words, a cell should contain either two references and a few raw bytes, or one reference and about 36 raw bytes, or no references at all with 72 raw bytes. [Back ↑](#2-5-5-low-level-perspective-bag-of-cells)\n\n<span id=\"fn19\">19.</span> A better implementation would be to keep the state of the smart contract as a serialized string, if it is small, or in a separate $B$-tree, if it is large; then the top-level structure representing the state of a blockchain would be a $B$-tree, whose leaves are allowed to contain references to other $B$-trees. [Back ↑](#2-5-5-low-level-perspective-bag-of-cells)\n\n<span id=\"fn20\">20.</span> It makes sense to generate and use a new key pair for every validator election. [Back ↑](#2-6-7-global-validator-set-election)\n\n<span id=\"fn21\">21.</span> A possible exception is the state of output queues of the neighboring shardchains, needed to guarantee the message ordering requirements described in [2.4.21](#2-4-21-collecting-input-messages-from-output-queues-of-neighboring-shardchains), because the size of Merkle proofs might become prohibitive in this case. [Back ↑](#2-6-11-validation-of-block-candidates)\n\n<span id=\"fn22\">22.</span> Actually, the shard configuration is completely determined by the last masterchain block; this simplifies getting access to the shard configuration. [Back ↑](#2-7-1-shard-configuration)\n\n<span id=\"fn23\">23.</span> Unless some validators are temporarily or permanently banned because of signing invalid blocks—then they are automatically excluded from all task groups. [Back ↑](#2-7-4-validator-task-groups-for-new-shardchains)\n\n<span id=\"fn24\">24.</span> More like 15, for the time being. However, some upgrades are being planned to make Ethereum transaction throughput several times larger. [Back ↑](#2-8-2-single-blockchain-vs-multi-blockchain-projects)\n\n<span id=\"fn25\">25.</span> Some people even claim DPOS block generation times of half a second, which does not seem realistic if validators are scattered across several continents. [Back ↑](#2-8-5-comparison-of-dpos-and-bft-pos)\n\n<span id=\"fn26\">26.</span> For instance, EOS, one of the best DPOS projects proposed up to this date, promises a 45-second confirmation and inter-blockchain interaction delay (cf. EOS White Paper, \"Transaction Confirmation\" and \"Latency of Interchain Communication\" sections). [Back ↑](#2-8-5-comparison-of-dpos-and-bft-pos)\n\n<span id=\"fn27\">27.</span> For example, the Plasma project plans to use the Ethereum blockchain as its (external) masterchain; it does not interact much with Ethereum otherwise, and it could have been suggested and implemented by a team unrelated to the Ethereum project. [Back ↑](#2-8-16-complications-of-changing-the-genome-of-a-blockchain-project)\n\n<span id=\"fn28\">28.</span> As of 2017, Ethereum is still struggling to transition from PoW to a combined PoW+PoS system; we hope it will become a truly PoS system someday. [Back ↑](#2-8-16-complications-of-changing-the-genome-of-a-blockchain-project)\n\n<span id=\"fn29\">29.</span> There are sharding proposals for Ethereum dating back to 2015; it is unclear how they might be implemented and deployed without disrupting Ethereum or creating an essentially independent parallel project. [Back ↑](#2-8-16-complications-of-changing-the-genome-of-a-blockchain-project)\n\n<span id=\"fn30\">30.</span> https://blog.ethereum.org/2015/08/01/introducing-casper-friendly-ghost/ [Back ↑](#2-9-5-casper)\n\n<span id=\"fn31\">31.</span> https://geti2p.net/en/docs/how/garlic-routing [Back ↑](#3-1-6-channel-as-a-tunnel-identifier)\n\n<span id=\"fn32\">32.</span> If there are sufficiently many nodes in a bucket, it can be subdivided further into, say, eight sub-buckets depending on the top four bits of the Kademlia distance. This would speed up DHT lookups. [Back ↑](#3-2-6-kademlia-routing-table)\n\n<span id=\"fn33\">33.</span> Alternatively, the abstract address might be stored in the DHT as explained in [3.2.12](#3-2-12-locating-services). [Back ↑](#3-3-5-joining-an-overlay-network)\n\n<span id=\"fn34\">34.</span> https://core.telegram.org/mtproto [Back ↑](#4-1-4-telegram-messenger-as-a-ton-service-mtproto-over-rldp)\n\n<span id=\"fn35\">35.</span> https://telegram.org/ [Back ↑](#4-1-4-telegram-messenger-as-a-ton-service-mtproto-over-rldp)\n\n<span id=\"fn36\">36.</span> TL-schemes can be TL-serialized themselves; cf. https://core.telegram.org/mtproto/TL-tl. [Back ↑](#4-3-14-public-interfaces-of-a-smart-contract)\n\n<span id=\"fn37\">37.</span> The maximum total amount of validator stakes is a configurable parameter of the blockchain, so this restriction can be enforced by the protocol if necessary. [Back ↑](#a-3-original-supply-mining-rewards-and-inflation)\n\n"
  },
  {
    "path": "foundations/whitepapers/tvm.mdx",
    "content": "---\ntitle: \"Telegram Open Network Virtual Machine\"\nsidebarTitle: \"TVM\"\ndescription: \"Whitepaper by Dr. Nikolai Durov\"\n---\n\n**Author**: Nikolai Durov <br />\n**Date**: March 23, 2020 <br />\n<Icon icon=\"file-pdf\" size={16} />: [Original whitepaper, PDF](/resources/pdfs/tvm.pdf)\n\n\n## Abstract\n\nThe aim of this text is to provide a description of the Telegram Open Network Virtual Machine (TON VM or TVM), used to execute smart contracts in the TON Blockchain.\n\n## Introduction\n\nThe primary purpose of the Telegram Open Network Virtual Machine (TON VM or TVM) is to execute smart-contract code in the TON Blockchain. TVM must support all operations required to parse incoming messages and persistent data, and to create new messages and modify persistent data.\n\nAdditionally, TVM must meet the following requirements:\n\n- It must provide for possible future extensions and improvements while retaining backward compatibility and interoperability, because the code of a smart contract, once committed into the blockchain, must continue working in a predictable manner regardless of any future modifications to the VM.\n- It must strive to attain high \"(virtual) machine code\" density, so that the code of a typical smart contract occupies as little persistent blockchain storage as possible.\n- It must be completely deterministic. In other words, each run of the same code with the same input data must produce the same result, regardless of specific software and hardware used.<a id=\"ref-fn1\"></a><sup>[1](#fn1)</sup>\n\nThe design of TVM is guided by these requirements. While this document describes a preliminary and experimental version of TVM,<a id=\"ref-fn2\"></a><sup>[2](#fn2)</sup> the backward compatibility mechanisms built into the system allow us to be relatively unconcerned with the efficiency of the operation encoding used for TVM code in this preliminary version.\n\nTVM is not intended to be implemented in hardware (e.g., in a specialized microprocessor chip); rather, it should be implemented in software running on conventional hardware. This consideration lets us incorporate some high-level concepts and operations in TVM that would require convoluted microcode in a hardware implementation but pose no significant problems for a software implementation. Such operations are useful for achieving high code density and minimizing the byte (or storage cell) profile of smart-contract code when deployed in the TON Blockchain.\n\n# 1   Overview\n\nThis chapter provides an overview of the main features and design principles of TVM. More detail on each topic is provided in subsequent chapters.\n\n## 1.0   Notation for bitstrings\n\nThe following notation is used for bit strings (or *bitstrings*)—i.e., finite strings consisting of binary digits (bits), $\\texttt{0}$ and $\\texttt{1}$—throughout this document.\n\n### 1.0.1. Hexadecimal notation for bitstrings\n\nWhen the length of a bitstring is a multiple of four, we subdivide it into groups of four bits and represent each group by one of sixteen hexadecimal digits $\\texttt{0}$--$\\texttt{9}$, $\\texttt{A}$--$\\texttt{F}$ in the usual manner: $\\texttt{0}_{16}\\leftrightarrow\\texttt{0000}$, $\\texttt{1}_{16}\\leftrightarrow\\texttt{0001}$, $\\ldots$, $\\texttt{F}_{16}\\leftrightarrow\\texttt{1111}$. The resulting hexadecimal string is our equivalent representation for the original binary string.\n\n### 1.0.2. Bitstrings of lengths not divisible by four\n\nIf the length of a binary string is not divisible by four, we augment it by one $\\texttt{1}$ and several (maybe zero) $\\texttt{0}$s at the end, so that its length becomes divisible by four, and then transform it into a string of hexadecimal digits as described above. To indicate that such a transformation has taken place, a special \"completion tag\" $\\texttt{\\_}$ is added to the end of the hexadecimal string. The reverse transformation (applied if the completion tag is present) consists in first replacing each hexadecimal digit by four corresponding bits, and then removing all trailing zeroes (if any) and the last $\\texttt{1}$ immediately preceding them (if the resulting bitstring is non-empty at this point).\n\nNotice that there are several admissible hexadecimal representations for the same bitstring. Among them, the shortest one is \"canonical\". It can be deterministically obtained by the above procedure.\n\nFor example, $\\texttt{8A}$ corresponds to binary string $\\texttt{10001010}$, while $\\texttt{8A\\_}$ and $\\texttt{8A0\\_}$ both correspond to $\\texttt{100010}$. An empty bitstring may be represented by either ' ', '$\\texttt{8\\_}$', '$\\texttt{0\\_}$', '$\\texttt{\\_}$', or '$\\texttt{00\\_}$'.\n\n### 1.0.3. Emphasizing that a string is a hexadecimal representation of a bitstring\n\nSometimes we need to emphasize that a string of hexadecimal digits (with or without a $\\texttt{\\_}$ at the end) is the hexadecimal representation of a bitstring. In such cases, we either prepend $\\texttt{x}$ to the resulting string (e.g., $\\texttt{x8A}$), or prepend $\\texttt{x\\{}$ and append $\\texttt{\\}}$ (e.g., $\\texttt{x\\{2D9\\_\\}}$, which is $\\texttt{00101101100}$). This should not be confused with hexadecimal numbers, usually prepended by $\\texttt{0x}$ (e.g., $\\texttt{0x2D9}$ or $\\texttt{0x2d9}$, which is the integer 729).\n\n### 1.0.4. Serializing a bitstring into a sequence of octets\n\nWhen a bitstring needs to be represented as a sequence of 8-bit bytes (octets), which take values in integers $0\\ldots255$, this is achieved essentially in the same fashion as above: we split the bitstring into groups of eight bits and interpret each group as the binary representation of an integer $0\\ldots255$. If the length of the bitstring is not a multiple of eight, the bitstring is augmented by a binary $\\texttt{1}$ and up to seven binary $\\texttt{0}$s before being split into groups. The fact that such a completion has been applied is usually reflected by a \"completion tag\" bit.\n\nFor instance, $\\texttt{00101101100}$ corresponds to the sequence of two octets $(\\texttt{0x2d}, \\texttt{0x90})$ (hexadecimal), or $(45,144)$ (decimal), along with a completion tag bit equal to $\\texttt{1}$ (meaning that the completion has been applied), which must be stored separately.\n\nIn some cases, it is more convenient to assume the completion is enabled by default rather than store an additional completion tag bit separately. Under such conventions, $8n$-bit strings are represented by $n+1$ octets, with the last octet always equal to $\\texttt{0x80}=128$.\n\n## 1.1   TVM is a stack machine\n\nFirst of all, *TVM is a stack machine*. This means that, instead of keeping values in some \"variables\" or \"general-purpose registers\", they are kept in a (LIFO) *stack*, at least from the \"low-level\" (TVM) perspective.<a id=\"ref-fn3\"></a><sup>[3](#fn3)</sup>\n\nMost operations and user-defined functions take their arguments from the top of the stack, and replace them with their result. For example, the integer addition primitive (built-in operation) $\\texttt{ADD}$ does not take any arguments describing which registers or immediate values should be added together and where the result should be stored. Instead, the two top values are taken from the stack, they are added together, and their sum is pushed into the stack in their place.\n\n### 1.1.1. TVM values\n\nThe entities that can be stored in the TVM stack will be called *TVM values*, or simply *values* for brevity. They belong to one of several predefined *value types*. Each value belongs to exactly one value type. The values are always kept on the stack along with tags uniquely determining their types, and all built-in TVM operations (or *primitives*) only accept values of predefined types.\n\nFor example, the integer addition primitive $\\texttt{ADD}$ accepts only two integer values, and returns one integer value as a result. One cannot supply $\\texttt{ADD}$ with two strings instead of two integers expecting it to concatenate these strings or to implicitly transform the strings into their decimal integer values; any attempt to do so will result in a run-time type-checking exception.\n\n### 1.1.2. Static typing, dynamic typing, and run-time type checking\n\nIn some respects TVM performs a kind of dynamic typing using run-time type checking. However, this does not make the TVM code a \"dynamically typed language\" like PHP or Javascript, because all primitives accept values and return results of predefined (value) types, each value belongs to strictly one type, and values are never implicitly converted from one type to another. If, on the other hand, one compares the TVM code to the conventional microprocessor machine code, one sees that the TVM mechanism of value tagging prevents, for example, using the address of a string as a number—or, potentially even more disastrously, using a number as the address of a string—thus eliminating the possibility of all sorts of bugs and security vulnerabilities related to invalid memory accesses, usually leading to memory corruption and segmentation faults. This property is highly desirable for a VM used to execute smart contracts in a blockchain. In this respect, TVM's insistence on tagging all values with their appropriate types, instead of reinterpreting the bit sequence in a register depending on the needs of the operation it is used in, is just an additional run-time type-safety mechanism.\n\nAn alternative would be to somehow analyze the smart-contract code for type correctness and type safety before allowing its execution in the VM, or even before allowing it to be uploaded into the blockchain as the code of a smart contract. Such a static analysis of code for a Turing-complete machine appears to be a time-consuming and non-trivial problem (likely to be equivalent to the stopping problem for Turing machines), something we would rather avoid in a blockchain smart-contract context.\n\nOne should bear in mind that one always can implement compilers from statically typed high-level smart-contract languages into the TVM code (and we do expect that most smart contracts for TON will be written in such languages), just as one can compile statically typed languages into conventional machine code (e.g., x86 architecture). If the compiler works correctly, the resulting machine code will never generate any run-time type-checking exceptions. All type tags attached to values processed by TVM will always have expected values and may be safely ignored during the analysis of the resulting TVM code, apart from the fact that the run-time generation and verification of these type tags by TVM will slightly slow down the execution of the TVM code.\n\n### 1.1.3. Preliminary list of value types\n\nA preliminary list of value types supported by TVM is as follows:\n\n- *Integer* — Signed 257-bit integers, representing integer numbers in the range $-2^{256}\\ldots2^{256}-1$, as well as a special \"not-a-number\" value $\\texttt{NaN}$.\n- *Cell* — A *TVM cell* consists of at most 1023 bits of data, and of at most four references to other cells. All persistent data (including TVM code) in the TON Blockchain is represented as a [collection of TVM cells](/foundations/whitepapers/ton#2-5-14-“everything-is-a-bag-of-cells”-philosophy).\n- *Tuple* — An ordered collection of up to 255 components, having arbitrary value types, possibly distinct. May be used to represent non-persistent values of arbitrary algebraic data types.\n- *Null* — A type with exactly one value $\\bot$, used for representing empty lists, empty branches of binary trees, absence of return value in some situations, and so on.\n- *Slice* — A *TVM cell slice*, or *slice* for short, is a contiguous \"sub-cell\" of an existing cell, containing some of its bits of data and some of its references. Essentially, a slice is a read-only view for a subcell of a cell. Slices are used for unpacking data previously stored (or serialized) in a cell or a tree of cells.\n- *Builder* — A *TVM cell builder*, or *builder* for short, is an \"incomplete\" cell that supports fast operations of appending bitstrings and cell references at its end. Builders are used for packing (or serializing) data from the top of the stack into new cells (e.g., before transferring them to persistent storage).\n- *Continuation* — Represents an \"execution token\" for TVM, which may be invoked (executed) later. As such, it generalizes function addresses (i.e., function pointers and references), subroutine return addresses, instruction pointer addresses, exception handler addresses, closures, partial applications, anonymous functions, and so on.\n\nThis list of value types is incomplete and may be extended in future revisions of TVM without breaking the old TVM code, due mostly to the fact that all originally defined primitives accept only values of types known to them and will fail (generate a type-checking exception) if invoked on values of new types. Furthermore, existing value types themselves can also be extended in the future: for example, 257-bit *Integer* might become 513-bit *LongInteger*, with originally defined arithmetic primitives failing if either of the arguments or the result does not fit into the original subtype *Integer*. Backward compatibility with respect to the introduction of new value types and extension of existing value types will be discussed [later](#5-1-4-changing-the-behavior-of-old-operations).\n\n## 1.2   Categories of TVM instructions\n\nTVM *instructions*, also called *primitives* and sometimes *(built-in) operations*, are the smallest operations atomically performed by TVM that can be present in the TVM code. They fall into several categories, depending on the [types of values](#1-1-3-preliminary-list-of-value-types) they work on. The most important of these categories are:\n\n- *Stack (manipulation) primitives* — Rearrange data in the TVM stack, so that the other primitives and user-defined functions can later be called with correct arguments. Unlike most other primitives, they are polymorphic, i.e., work with values of arbitrary types.\n- *Tuple (manipulation) primitives* — Construct, modify, and decompose *Tuple*s. Similarly to the stack primitives, they are polymorphic.\n- *Constant* or *literal primitives* — Push into the stack some \"constant\" or \"literal\" values embedded into the TVM code itself, thus providing arguments to the other primitives. They are somewhat similar to stack primitives, but are less generic because they work with values of specific types.\n- *Arithmetic primitives* — Perform the usual integer arithmetic operations on values of type *Integer*.\n- *Cell (manipulation) primitives* — Create new cells and store data in them (*cell creation primitives*) or read data from previously created cells (*cell parsing primitives*). Because all memory and persistent storage of TVM consists of cells, these cell manipulation primitives actually correspond to \"memory access instructions\" of other architectures. Cell creation primitives usually work with values of type *Builder*, while cell parsing primitives work with *Slice*s.\n- *Continuation* and *control flow primitives* — Create and modify *Continuation*s, as well as execute existing *Continuation*s in different ways, including conditional and repeated execution.\n- *Custom* or *application-specific primitives* — Efficiently perform specific high-level actions required by the application (in our case, the TON Blockchain), such as computing hash functions, performing elliptic curve cryptography, sending new blockchain messages, creating new smart contracts, and so on. These primitives correspond to standard library functions rather than microprocessor instructions.\n\n## 1.3   Control registers\n\nWhile TVM is a stack machine, some rarely changed values needed in almost all functions are better passed in certain special registers, and not near the top of the stack. Otherwise, a prohibitive number of stack reordering operations would be required to manage all these values.\n\nTo this end, the TVM model includes, apart from the stack, up to 16 special *control registers*, denoted by $\\texttt{c0}$ to $\\texttt{c15}$, or $\\texttt{c}(0)$ to $\\texttt{c}(15)$. The original version of TVM makes use of only some of these registers; the rest may be supported later.\n\n### 1.3.1. Values kept in control registers\n\nThe values kept in control registers are of the same types as those kept on the stack. However, some control registers accept only values of specific types, and any attempt to load a value of a different type will lead to an exception.\n\n### 1.3.2. List of control registers\n\nThe original version of TVM defines and uses the following control registers:\n\n- $\\texttt{c0}$ — Contains the *next continuation* or *return continuation* (similar to the subroutine return address in conventional designs). This value must be a *Continuation*.\n- $\\texttt{c1}$ — Contains the *alternative (return) continuation*; this value must be a *Continuation*. It is used in some (experimental) control flow primitives, allowing TVM to define and call \"subroutines with two exit points\".\n- $\\texttt{c2}$ — Contains the *exception handler*. This value is a *Continuation*, invoked whenever an exception is triggered.\n- $\\texttt{c3}$ — Contains the *current dictionary*, essentially a hashmap containing the code of all functions used in the program. This value is also a [Continuation](#4-6-functions%2C-recursion%2C-and-dictionaries), not a *Cell* as one might expect.\n- $\\texttt{c4}$ — Contains the *root of persistent data*, or simply the *data*. This value is a *Cell*. When the code of a smart contract is invoked, $\\texttt{c4}$ points to the root cell of its persistent data kept in the blockchain state. If the smart contract needs to modify this data, it changes $\\texttt{c4}$ before returning.\n- $\\texttt{c5}$ — Contains the *output actions*. It is also a *Cell* initialized by a reference to an empty cell, but its final value is considered one of the smart contract outputs. For instance, the $\\texttt{SENDMSG}$ primitive, specific for the TON Blockchain, simply inserts the message into a list stored in the output actions.\n- $\\texttt{c7}$ — Contains the *root of temporary data*. It is a *Tuple*, initialized by a reference to an empty *Tuple* before invoking the smart contract and discarded after its termination.<a id=\"ref-fn4\"></a><sup>[4](#fn4)</sup>\n\nMore control registers may be defined in the future for specific TON Blockchain or high-level programming language purposes, if necessary.\n\n## 1.4   Total state of TVM (SCCCG)\n\nThe total state of TVM consists of the following components:\n\n- *[Stack](#1-1-tvm-is-a-stack-machine)* — Contains zero or more [values](#1-1-1-tvm-values), each belonging to one of [value types](#1-1-3-preliminary-list-of-value-types).\n- *Control registers* $\\mathit{c0}$–$\\mathit{c15}$ — Contain some [specific values](#1-3-2-list-of-control-registers). (Only seven control registers are used in the current version.)\n- *Current continuation* $\\mathit{cc}$ — Contains the current continuation (i.e., the code that would be normally executed after the current primitive is completed). This component is similar to the instruction pointer register ($\\texttt{ip}$) in other architectures.\n- *Current codepage* $\\mathit{cp}$ — A special signed 16-bit integer value that selects the way the next TVM opcode will be decoded. For example, future versions of TVM might use different codepages to add new opcodes while preserving backward compatibility.\n- *Gas limits* $\\mathit{gas}$ — Contains four signed 64-bit integers: the current gas limit $g_l$, the maximal gas limit $g_m$, the remaining gas $g_r$, and the gas credit $g_c$. Always $0\\leq g_l\\leq g_m$, $g_c\\geq0$, and $g_r\\leq g_l+g_c$; $g_c$ is usually initialized by zero, $g_r$ is initialized by $g_l+g_c$ and gradually decreases as the TVM runs. When $g_r$ becomes negative or if the final value of $g_r$ is less than $g_c$, an *out of gas* exception is triggered.\n\nNotice that there is no \"return stack\" containing the return addresses of all previously called but unfinished functions. Instead, only [control register $\\texttt{c0}$](#4-1-9-subroutine-calls%3A-or-primitives) is used.\n\nAlso notice that there are no general-purpose registers, because [TVM is a stack machine](#1-1-tvm-is-a-stack-machine). So the above list, which can be summarized as \"stack, control, continuation, codepage, and gas\" (SCCCG), similarly to the classical SECD machine state (\"stack, environment, control, dump\"), is indeed the *total* state of TVM.<a id=\"ref-fn5\"></a><sup>[5](#fn5)</sup>\n\n## 1.5   Integer arithmetic\n\nAll arithmetic primitives of TVM operate on several arguments of type *Integer*, taken from the top of the stack, and return their results, of the same type, into the stack. Recall that *Integer* represents all integer values in the range $-2^{256}\\leq x<2^{256}$, and additionally contains a special value $\\texttt{NaN}$ (\"not-a-number\").\n\nIf one of the results does not fit into the supported range of integers—or if one of the arguments is a $\\texttt{NaN}$—then this result or all of the results are replaced by a $\\texttt{NaN}$, and (by default) an integer overflow exception is generated. However, special \"quiet\" versions of arithmetic operations will simply produce $\\texttt{NaN}$s and keep going. If these $\\texttt{NaN}$s end up being used in a \"non-quiet\" arithmetic operation, or in a non-arithmetic operation, an integer overflow exception will occur.\n\n### 1.5.1. Absence of automatic conversion of integers\n\nNotice that TVM *Integer*s are \"mathematical\" integers, and not 257-bit strings interpreted differently depending on the primitive used, as is common for other machine code designs. For example, TVM has only one multiplication primitive $\\texttt{MUL}$, rather than two ($\\texttt{MUL}$ for unsigned multiplication and $\\texttt{IMUL}$ for signed multiplication) as occurs, for example, in the popular x86 architecture.\n\n### 1.5.2. Automatic overflow checks\n\nNotice that all TVM arithmetic primitives perform overflow checks of the results. If a result does not fit into the *Integer* type, it is replaced by a $\\texttt{NaN}$, and (usually) an exception occurs. In particular, the result is *not* automatically reduced modulo $2^{256}$ or $2^{257}$, as is common for most hardware machine code architectures.\n\n### 1.5.3. Custom overflow checks\n\nIn addition to automatic overflow checks, TVM includes custom overflow checks, performed by primitives $\\texttt{FITS}$ $n$ and $\\texttt{UFITS}$ $n$, where $1\\leq n\\leq256$. These primitives check whether the value on (the top of) the stack is an integer $x$ in the range $-2^{n-1}\\leq x<2^{n-1}$ or $0\\leq x<2^n$, respectively, and replace the value with a $\\texttt{NaN}$ and (optionally) generate an integer overflow exception if this is not the case. This greatly simplifies the implementation of arbitrary $n$-bit integer types, signed or unsigned: the programmer or the compiler must insert appropriate $\\texttt{FITS}$ or $\\texttt{UFITS}$ primitives either after each arithmetic operation (which is more reasonable, but requires more checks) or before storing computed values and returning them from functions. This is important for smart contracts, where unexpected integer overflows happen to be among the most common source of bugs.\n\n### 1.5.4. Reduction modulo $2^n$\n\nTVM also has a primitive $\\texttt{MODPOW2}$ $n$, which reduces the integer at the top of the stack modulo $2^n$, with the result ranging from $0$ to $2^n-1$.\n\n### 1.5.5. *Integer* is 257-bit, not 256-bit\n\nOne can understand now why TVM's *Integer* is (signed) 257-bit, not 256-bit. The reason is that it is the smallest integer type containing both signed 256-bit integers and unsigned 256-bit integers, which does not require [automatic reinterpreting](#1-5-1-absence-of-automatic-conversion-of-integers) of the same 256-bit string depending on the operation used.\n\n### 1.5.6. Division and rounding\n\nThe most important division primitives are $\\texttt{DIV}$, $\\texttt{MOD}$, and $\\texttt{DIVMOD}$. All of them take two numbers from the stack, $x$ and $y$ ($y$ is taken from the top of the stack, and $x$ is originally under it), compute the quotient $q$ and remainder $r$ of the division of $x$ by $y$ (i.e., two integers such that $x=yq+r$ and $|r|<|y|$), and return either $q$, $r$, or both of them. If $y$ is zero, then all of the expected results are replaced by $\\texttt{NaN}$s, and (usually) an integer overflow exception is generated.\n\nThe implementation of division in TVM somewhat differs from most other implementations with regards to rounding. By default, these primitives round to $-\\infty$, meaning that $q=\\lfloor x/y\\rfloor$, and $r$ has the same sign as $y$. (Most conventional implementations of division use \"rounding to zero\" instead, meaning that $r$ has the same sign as $x$.) Apart from this \"floor rounding\", two other rounding modes are available, called \"ceiling rounding\" (with $q=\\lceil x/y\\rceil$, and $r$ and $y$ having opposite signs) and \"nearest rounding\" (with $q=\\lfloor x/y+1/2\\rfloor$ and $|r|\\leq|y|/2$). These rounding modes are selected by using other division primitives, with letters $\\texttt{C}$ and $\\texttt{R}$ appended to their mnemonics. For example, $\\texttt{DIVMODR}$ computes both the quotient and the remainder using rounding to the nearest integer.\n\n### 1.5.7. Combined multiply-divide, multiply-shift, and shift-divide operations\n\nTo simplify implementation of fixed-point arithmetic, TVM supports combined multiply-divide, multiply-shift, and shift-divide operations with double-length (i.e., 514-bit) intermediate product. For example, $\\texttt{MULDIVMODR}$ takes three integer arguments from the stack, $a$, $b$, and $c$, first computes $ab$ using a 514-bit intermediate result, and then divides $ab$ by $c$ using rounding to the nearest integer. If $c$ is zero or if the quotient does not fit into *Integer*, either two $\\texttt{NaN}$s are returned, or an integer overflow exception is generated, depending on whether a quiet version of the operation has been used. Otherwise, both the quotient and the remainder are pushed into the stack.\n\n---\n\n# 2   The stack\n\nThis chapter contains a general discussion and comparison of register and stack machines, expanded further in [Appendix C](#c-code-density-of-stack-and-register-machines), and describes the two main classes of stack manipulation primitives employed by TVM: the *basic* and the *compound stack manipulation primitives*. An informal explanation of their sufficiency for all stack reordering required for correctly invoking other primitives and user-defined functions is also provided. Finally, the problem of efficiently implementing TVM [stack manipulation primitives](#2-3-efficiency-of-stack-manipulation-primitives) will be discussed.\n\n## 2.1    Stack calling conventions\n\nA stack machine, such as TVM, uses the stack—and especially the values near the top of the stack—to pass arguments to called functions and primitives (such as built-in arithmetic operations) and receive their results. This section discusses the TVM stack calling conventions, introduces some notation, and compares TVM stack calling conventions with those of certain register machines.\n\n### 2.1.1. Notation for \"stack registers\"\n\nRecall that a stack machine, as opposed to a more conventional register machine, lacks general-purpose registers. However, one can treat the values near the top of the stack as a kind of \"stack registers\".\n\nWe denote by $\\texttt{s0}$ or $\\texttt{s}(0)$ the value at the top of the stack, by $\\texttt{s1}$ or $\\texttt{s}(1)$ the value immediately under it, and so on. The total number of values in the stack is called its *depth*. If the depth of the stack is $n$, then $\\texttt{s}(0)$, $\\texttt{s}(1)$, $\\ldots$, $\\texttt{s}(n-1)$ are well-defined, while $\\texttt{s}(n)$ and all subsequent $\\texttt{s}(i)$ with $i>n$ are not. Any attempt to use $\\texttt{s}(i)$ with $i\\geq n$ should produce a stack underflow exception.\n\nA compiler, or a human programmer in \"TVM code\", would use these \"stack registers\" to hold all declared variables and intermediate values, similarly to the way general-purpose registers are used on a register machine.\n\n### 2.1.2. Pushing and popping values\n\nWhen a value $x$ is *pushed* into a stack of depth $n$, it becomes the new $\\texttt{s0}$; at the same time, the old $\\texttt{s0}$ becomes the new $\\texttt{s1}$, the old $\\texttt{s1}$—the new $\\texttt{s2}$, and so on. The depth of the resulting stack is $n+1$.\n\nSimilarly, when a value $x$ is *popped* from a stack of depth $n\\geq1$, it is the old value of $\\texttt{s0}$ (i.e., the old value at the top of the stack). After this, it is removed from the stack, and the old $\\texttt{s1}$ becomes the new $\\texttt{s0}$ (the new value at the top of the stack), the old $\\texttt{s2}$ becomes the new $\\texttt{s1}$, and so on. The depth of the resulting stack is $n-1$.\n\nIf originally $n=0$, then the stack is *empty*, and a value cannot be popped from it. If a primitive attempts to pop a value from an empty stack, a *stack underflow* exception occurs.\n\n### 2.1.3. Notation for hypothetical general-purpose registers\n\nIn order to compare stack machines with sufficiently general register machines, we will denote the general-purpose registers of a register machine by $\\texttt{r0}$, $\\texttt{r1}$, and so on, or by $\\texttt{r}(0)$, $\\texttt{r}(1)$, $\\ldots$, $\\texttt{r}(n-1)$, where $n$ is the total number of registers. When we need a specific value of $n$, we will use $n=16$, corresponding to the very popular x86-64 architecture.\n\n### 2.1.4. The top-of-stack register $\\texttt{s0}$ vs. the accumulator register $\\texttt{r0}$\n\nSome register machine architectures require one of the arguments for most arithmetic and logical operations to reside in a special register called the *accumulator*. In our comparison, we will assume that the accumulator is the general-purpose register $\\texttt{r0}$; otherwise we could simply renumber the registers. In this respect, the accumulator is somewhat similar to the top-of-stack \"register\" $\\texttt{s0}$ of a stack machine, because virtually all operations of a stack machine both use $\\texttt{s0}$ as one of their arguments and return their result as $\\texttt{s0}$.\n\n### 2.1.5. Register calling conventions\n\nWhen compiled for a register machine, high-level language functions usually receive their arguments in certain registers in a predefined order. If there are too many arguments, these functions take the remainder from the stack (yes, a register machine usually has a stack, too!). Some register calling conventions pass no arguments in registers at all, however, and only use the stack (for example, the original calling conventions used in implementations of Pascal and C, although modern implementations of C use some registers as well).\n\nFor simplicity, we will assume that up to $m\\leq n$ function arguments are passed in registers, and that these registers are $\\texttt{r0}$, $\\texttt{r1}$, $\\ldots$, $\\texttt{r}(m-1)$, in that order (if some other registers are used, we can simply renumber them).<a id=\"ref-fn6\"></a><sup>[6](#fn6)</sup>\n\n### 2.1.6. Order of function arguments\n\nIf a function or primitive requires $m$ arguments $x_1$, $\\ldots$, $x_m$, they are pushed by the caller into the stack in the same order, starting from $x_1$. Therefore, when the function or primitive is invoked, its first argument $x_1$ is in $\\texttt{s}(m-1)$, its second argument $x_2$ is in $\\texttt{s}(m-2)$, and so on. The last argument $x_m$ is in $\\texttt{s0}$ (i.e., at the top of the stack). It is the called function or primitive's responsibility to remove its arguments from the stack.\n\nIn this respect the TVM stack calling conventions—obeyed, at least, by TVM primitives—match those of Pascal and Forth, and are the opposite of those of C (in which the arguments are pushed into the stack in the reverse order, and are removed by the caller after it regains control, not the callee).\n\nOf course, an implementation of a high-level language for TVM might choose some other calling conventions for its functions, different from the default ones. This might be useful for certain functions—for instance, if the total number of arguments depends on the value of the first argument, as happens for \"variadic functions\" such as $\\texttt{scanf}$ and $\\texttt{printf}$. In such cases, the first one or several arguments are better passed near the top of the stack, not somewhere at some unknown location deep in the stack.\n\n### 2.1.7. Arguments to arithmetic primitives on register machines\n\nOn a stack machine, built-in arithmetic primitives (such as $\\texttt{ADD}$ or $\\texttt{DIVMOD}$) follow the same calling conventions as user-defined functions. In this respect, user-defined functions (for example, a function computing the square root of a number) might be considered as \"extensions\" or \"custom upgrades\" of the stack machine. This is one of the clearest advantages of stack machines (and of stack programming languages such as Forth) compared to register machines.\n\nIn contrast, arithmetic instructions (built-in operations) on register machines usually get their parameters from general-purpose registers encoded in the full opcode. A binary operation, such as $\\texttt{SUB}$, thus requires two arguments, $\\texttt{r}(i)$ and $\\texttt{r}(j)$, with $i$ and $j$ specified by the instruction. A register $\\texttt{r}(k)$ for storing the result also must be specified. Arithmetic operations can take several possible forms, depending on whether $i$, $j$, and $k$ are allowed to take arbitrary values:\n\n- Three-address form — Allows the programmer to arbitrarily choose not only the two source registers $\\texttt{r}(i)$ and $\\texttt{r}(j)$, but also a separate destination register $\\texttt{r}(k)$. This form is common for most RISC processors, and for the XMM and AVX SIMD instruction sets in the x86-64 architecture.\n\n- Two-address form — Uses one of the two operand registers (usually $\\texttt{r}(i)$) to store the result of an operation, so that $k=i$ is never indicated explicitly. Only $i$ and $j$ are encoded inside the instruction. This is the most common form of arithmetic operations on register machines, and is quite popular on microprocessors (including the x86 family).\n\n- One-address form — Always takes one of the arguments from the accumulator $\\texttt{r0}$, and stores the result in $\\texttt{r0}$ as well; then $i=k=0$, and only $j$ needs to be specified by the instruction. This form is used by some simpler microprocessors (such as Intel 8080).\n\nNote that this flexibility is available only for built-in operations, but not for user-defined functions. In this respect, register machines are not as easily \"upgradable\" as stack machines.<a id=\"ref-fn7\"></a><sup>[7](#fn7)</sup>\n\n### 2.1.8. Return values of functions\n\nIn stack machines such as TVM, when a function or primitive needs to return a result value, it simply pushes it into the stack (from which all arguments to the function have already been removed). Therefore, the caller will be able to access the result value through the top-of-stack \"register\" $\\texttt{s0}$.\n\nThis is in complete accordance with Forth calling conventions, but differs slightly from Pascal and C calling conventions, where the accumulator register $\\texttt{r0}$ is normally used for the return value.\n\n### 2.1.9. Returning several values\n\nSome functions might want to return several values $y_1$, $\\ldots$, $y_k$, with $k$ not necessarily equal to one. In these cases, the $k$ return values are pushed into the stack in their natural order, starting from $y_1$.\n\nFor example, the \"divide with remainder\" primitive $\\texttt{DIVMOD}$ needs to return two values, the quotient $q$ and the remainder $r$. Therefore, $\\texttt{DIVMOD}$ pushes $q$ and $r$ into the stack, in that order, so that the quotient is available thereafter at $\\texttt{s1}$ and the remainder at $\\texttt{s0}$. The net effect of $\\texttt{DIVMOD}$ is to divide the original value of $\\texttt{s1}$ by the original value of $\\texttt{s0}$, and return the quotient in $\\texttt{s1}$ and the remainder in $\\texttt{s0}$. In this particular case the depth of the stack and the values of all other \"stack registers\" remain unchanged, because $\\texttt{DIVMOD}$ takes two arguments and returns two results. In general, the values of other \"stack registers\" that lie in the stack below the arguments passed and the values returned are shifted according to the change of the depth of the stack.\n\nIn principle, some primitives and user-defined functions might return a variable number of result values. In this respect, the remarks above about [variadic functions](#2-1-6-order-of-function-arguments) apply: the total number of result values and their types should be determined by the values near the top of the stack. (For example, one might push the return values $y_1$, $\\ldots$, $y_k$, and then push their total number $k$ as an integer. The caller would then determine the total number of returned values by inspecting $\\texttt{s0}$.)\n\nIn this respect TVM, again, faithfully observes Forth calling conventions.\n\n### 2.1.10. Stack notation\n\nWhen a stack of depth $n$ contains values $z_1$, $\\ldots$, $z_n$, in that order, with $z_1$ the deepest element and $z_n$ the top of the stack, the contents of the stack are often represented by a list $z_1$ $z_2$ $\\ldots$ $z_n$, in that order. When a primitive transforms the original stack state $S'$ into a new state $S''$, this is often written as $S'$ -- $S''$; this is the so-called *stack notation*. For example, the action of the division primitive $\\texttt{DIV}$ can be described by $S$ $x$ $y$ -- $S$ $\\lfloor x/y\\rfloor$, where $S$ is any list of values. This is usually abbreviated as $x$ $y$ -- $\\lfloor x/y\\rfloor$, tacitly assuming that all other values deeper in the stack remain intact.\n\nAlternatively, one can describe $\\texttt{DIV}$ as a primitive that runs on a stack $S'$ of depth $n\\geq2$, divides $\\texttt{s1}$ by $\\texttt{s0}$, and returns the floor-rounded quotient as $\\texttt{s0}$ of the new stack $S''$ of depth $n-1$. The new value of $\\texttt{s}(i)$ equals the old value of $\\texttt{s}(i+1)$ for $1\\leq i<n-1$. These descriptions are equivalent, but saying that $\\texttt{DIV}$ transforms $x$ $y$ into $\\lfloor x/y\\rfloor$, or $\\ldots$ $x$ $y$ into $\\ldots$ $\\lfloor x/y\\rfloor$, is more concise.\n\nThe stack notation is extensively used throughout [Appendix A](#a-instructions-and-opcodes), where all currently defined TVM primitives are listed.\n\n### 2.1.11. Explicitly defining the number of arguments to a function\n\nStack machines usually pass the current stack in its entirety to the invoked primitive or function. That primitive or function accesses only the several values near the top of the stack that represent its arguments, and pushes the return values in their place, by convention leaving all deeper values intact. Then the resulting stack, again in its entirety, is returned to the caller.\n\nMost TVM primitives behave in this way, and we expect most user-defined functions to be implemented under such conventions. However, TVM provides mechanisms to specify how many [arguments](#4-1-10-determining-the-number-of-arguments-passed-to-and%2For-return-values-accepted-from-a-subroutine) must be passed to a called function. When these mechanisms are employed, the specified number of values are moved from the caller's stack into the (usually initially empty) stack of the called function, while deeper values remain in the caller's stack and are inaccessible to the callee. The caller can also specify how many return values it expects from the called function.\n\nSuch argument-checking mechanisms might be useful, for example, for a library function that calls user-provided functions passed as arguments to it.\n\n## 2.2   Stack manipulation primitives\n\nA stack machine, such as TVM, employs a lot of stack manipulation primitives to rearrange arguments to other primitives and user-defined functions, so that they become located near the top of the stack in correct order. This section discusses which stack manipulation primitives are necessary and sufficient for achieving this goal, and which of them are used by TVM. Some examples of code using these primitives can be found in [Appendix C](#c-code-density-of-stack-and-register-machines).\n\n### 2.2.1. Basic stack manipulation primitives\n\nThe most important stack manipulation primitives used by TVM are the following:\n\n- *Top-of-stack exchange operation*: $\\texttt{XCHG s0,s}(i)$ or $\\texttt{XCHG s}(i)$ — Exchanges values of $\\texttt{s0}$ and $\\texttt{s}(i)$. When $i=1$, operation $\\texttt{XCHG s1}$ is traditionally denoted by $\\texttt{SWAP}$. When $i=0$, this is a $\\texttt{NOP}$ (an operation that does nothing, at least if the stack is non-empty).\n\n- *Arbitrary exchange operation*: $\\texttt{XCHG s}(i)\\texttt{,s}(j)$ — Exchanges values of $\\texttt{s}(i)$ and $\\texttt{s}(j)$. Notice that this operation is not strictly necessary, because it can be simulated by three top-of-stack exchanges: $\\texttt{XCHG s}(i)$; $\\texttt{XCHG s}(j)$; $\\texttt{XCHG s}(i)$. However, it is useful to have arbitrary exchanges as primitives, because they are required quite often.\n\n- *Push operation*: $\\texttt{PUSH s}(i)$ — Pushes a copy of the (old) value of $\\texttt{s}(i)$ into the stack. Traditionally, $\\texttt{PUSH s0}$ is also denoted by $\\texttt{DUP}$ (it duplicates the value at the top of the stack), and $\\texttt{PUSH s1}$ by $\\texttt{OVER}$.\n\n- *Pop operation*: $\\texttt{POP s}(i)$ — Removes the top-of-stack value and puts it into the (new) $\\texttt{s}(i-1)$, or the old $\\texttt{s}(i)$. Traditionally, $\\texttt{POP s0}$ is also denoted by $\\texttt{DROP}$ (it simply drops the top-of-stack value), and $\\texttt{POP s1}$ by $\\texttt{NIP}$.\n\nSome other \"unsystematic\" stack manipulation operations might be also defined (e.g., $\\texttt{ROT}$, with stack notation $a$ $b$ $c$ -- $b$ $c$ $a$). While such operations are defined in stack languages like Forth (where $\\texttt{DUP}$, $\\texttt{DROP}$, $\\texttt{OVER}$, $\\texttt{NIP}$ and $\\texttt{SWAP}$ are also present), they are not strictly necessary because the *basic stack manipulation primitives* listed above suffice to rearrange stack registers to allow any arithmetic primitives and user-defined functions to be invoked correctly.\n\n### 2.2.2. Basic stack manipulation primitives suffice\n\nA compiler or a human TVM-code programmer might use the basic stack primitives as follows.\n\nSuppose that the function or primitive to be invoked is to be passed, say, three arguments $x$, $y$, and $z$, currently located in stack registers $\\texttt{s}(i)$, $\\texttt{s}(j)$, and $\\texttt{s}(k)$. In this circumstance, the compiler (or programmer) might issue operation $\\texttt{PUSH s}(i)$ (if a copy of $x$ is needed after the call to this primitive) or $\\texttt{XCHG s}(i)$ (if it will not be needed afterwards) to put the first argument $x$ into the top of the stack. Then, the compiler (or programmer) could use either $\\texttt{PUSH s}(j')$ or $\\texttt{XCHG s}(j')$, where $j'=j$ or $j+1$, to put $y$ into the new top of the stack.<a id=\"ref-fn8\"></a><sup>[8](#fn8)</sup>\n\nProceeding in this manner, we see that we can put the original values of $x$, $y$, and $z$—or their copies, if needed—into locations $\\texttt{s2}$, $\\texttt{s1}$, and $\\texttt{s0}$, using a sequence of push and exchange operations ([2.2.4](#2-2-4-mnemonics-of-compound-stack-operations) and [2.2.5](#2-2-5-semantics-of-compound-stack-operations) for a more detailed explanation). In order to generate this sequence, the compiler will need to know only the three values $i$, $j$ and $k$, describing the old locations of variables or temporary values in question, and some flags describing whether each value will be needed thereafter or is needed only for this primitive or function call. The locations of other variables and temporary values will be affected in the process, but a compiler (or a human programmer) can easily track their new locations.\n\nSimilarly, if the results returned from a function need to be discarded or moved to other stack registers, a suitable sequence of exchange and pop operations will do the job. In the typical case of one return value in $\\texttt{s0}$, this is achieved either by an $\\texttt{XCHG s}(i)$ or a $\\texttt{POP s}(i)$ (in most cases, a $\\texttt{DROP}$) operation.<a id=\"ref-fn9\"></a><sup>[9](#fn9)</sup>\n\nRearranging the result value or values before returning from a function is essentially the same problem as arranging arguments for a function call, and is achieved similarly.\n\n### 2.2.3. Compound stack manipulation primitives\n\nIn order to improve the density of the TVM code and simplify development of compilers, compound stack manipulation primitives may be defined, each combining up to four exchange and push or exchange and pop basic primitives. Such compound stack operations might include, for example:\n\n- $\\texttt{XCHG2 s}(i)\\texttt{,s}(j)$ — Equivalent to $\\texttt{XCHG s1,s}(i)$; $\\texttt{XCHG s}(j)$.\n- $\\texttt{PUSH2 s}(i)\\texttt{,s}(j)$ — Equivalent to $\\texttt{PUSH s}(i)$; $\\texttt{PUSH s}(j+1)$.\n- $\\texttt{XCPU s}(i)\\texttt{,s}(j)$ — Equivalent to $\\texttt{XCHG s}(i)$; $\\texttt{PUSH s}(j)$.\n- $\\texttt{PUXC s}(i)\\texttt{,s}(j)$ — Equivalent to $\\texttt{PUSH s}(i)$; $\\texttt{SWAP}$; $\\texttt{XCHG s}(j+1)$. When $j\\neq i$ and $j\\neq0$, it is also equivalent to $\\texttt{XCHG s}(j)$; $\\texttt{PUSH s}(i)$; $\\texttt{SWAP}$.\n- $\\texttt{XCHG3 s}(i)\\texttt{,s}(j)\\texttt{,s}(k)$ — Equivalent to $\\texttt{XCHG s2,s}(i)$; $\\texttt{XCHG s1,s}(j)$; $\\texttt{XCHG s}(k)$.\n- $\\texttt{PUSH3 s}(i)\\texttt{,s}(j)\\texttt{,s}(k)$ — Equivalent to $\\texttt{PUSH s}(i)$; $\\texttt{PUSH s}(j+1)$; $\\texttt{PUSH s}(k+2)$.\n\nOf course, such operations make sense only if they admit a more compact encoding than the equivalent sequence of basic operations. For example, if all top-of-stack exchanges, $\\texttt{XCHG s1,s}(i)$ exchanges, and push and pop operations admit one-byte encodings, the only compound stack operations suggested above that might merit inclusion in the set of stack manipulation primitives are $\\texttt{PUXC}$, $\\texttt{XCHG3}$, and $\\texttt{PUSH3}$.\n\nThese compound stack operations essentially augment other primitives (instructions) in the code with the \"true\" locations of their operands, somewhat similarly to what happens with two-address or three-address register machine code. However, instead of encoding these locations inside the opcode of the arithmetic or another instruction, as is customary for register machines, we indicate these locations in a preceding compound stack manipulation operation. The advantage of such an approach is that [user-defined functions](#2-1-7-arguments-to-arithmetic-primitives-on-register-machines) (or rarely used specific primitives added in a [future version](#c-3-sample-non-leaf-function) of TVM) can benefit from it as well.\n\n### 2.2.4. Mnemonics of compound stack operations\n\nThe mnemonics of [compound stack](#2-2-3-compound-stack-manipulation-primitives) operations, some examples of which have been provided are created as follows.\n\nThe $\\gamma\\geq2$ formal arguments $\\texttt{s}(i_1)$, $\\ldots$, $\\texttt{s}(i_\\gamma)$ to such an operation $O$ represent the values in the original stack that will end up in $\\texttt{s}(\\gamma-1)$, $\\ldots$, $\\texttt{s0}$ after the execution of this compound operation, at least if all $i_\\nu$, $1\\leq\\nu\\leq\\gamma$, are distinct and at least $\\gamma$. The mnemonic itself of the operation $O$ is a sequence of $\\gamma$ two-letter strings $\\texttt{PU}$ and $\\texttt{XC}$, with $\\texttt{PU}$ meaning that the corresponding argument is to be PUshed (i.e., a copy is to be created), and $\\texttt{XC}$ meaning that the value is to be eXChanged (i.e., no other copy of the original value is created). Sequences of several $\\texttt{PU}$ or $\\texttt{XC}$ strings may be abbreviated to one $\\texttt{PU}$ or $\\texttt{XC}$ followed by the number of copies. (For instance, we write $\\texttt{PUXC2PU}$ instead of $\\texttt{PUXCXCPU}$.)\n\nAs an exception, if a mnemonic would consist of only $\\texttt{PU}$ or only $\\texttt{XC}$ strings, so that the compound operation is equivalent to a sequence of $m$ PUSHes or eXCHanGes, the notation $\\texttt{PUSH}m$ or $\\texttt{XCHG}m$ is used instead of $\\texttt{PU}m$ or $\\texttt{XC}m$.\n\n### 2.2.5. Semantics of compound stack operations\n\nEach compound $\\gamma$-ary operation $O$ $\\texttt{s}(i_1)$,$\\ldots$,$\\texttt{s}(i_\\gamma)$ is translated into an equivalent sequence of basic stack operations by induction in $\\gamma$ as follows:\n\n- As a base of induction, if $\\gamma=0$, the only nullary compound stack operation corresponds to an empty sequence of basic stack operations.\n\n- Equivalently, we might begin the induction from $\\gamma=1$. Then $\\texttt{PU s}(i)$ corresponds to the sequence consisting of one basic operation $\\texttt{PUSH s}(i)$, and $\\texttt{XC s}(i)$ corresponds to the one-element sequence consisting of $\\texttt{XCHG s}(i)$.\n\n- Otherwise, if $\\gamma\\geq2$, compound operation $O$ has one of two forms:\n\n  1. $O$ $\\texttt{s}(i_1)$,$\\ldots$,$\\texttt{s}(i_\\gamma)$, with $O=\\texttt{XC}O'$, where $O'$ is a compound operation of arity $\\gamma-1$ (i.e., the mnemonic of $O'$ consists of $\\gamma-1$ strings $\\texttt{XC}$ and $\\texttt{PU}$). Let $\\alpha$ be the total quantity of $\\texttt{PU}$shes in $O$, and $\\beta$ be that of e$\\texttt{XC}$hanges, so that $\\alpha+\\beta=\\gamma$. Then the original operation is translated into $\\texttt{XCHG s}(\\beta-1)\\texttt{,s}(i_1)$, followed by the translation of $O'$ $\\texttt{s}(i_2)$,$\\ldots$,$\\texttt{s}(i_\\gamma)$, defined by the induction hypothesis.\n\n  2. $O$ $\\texttt{s}(i_1)$,$\\ldots$,$\\texttt{s}(i_\\gamma)$, with $O=\\texttt{PU}O'$, where $O'$ is a compound operation of arity $\\gamma-1$. Then the original operation is translated into $\\texttt{PUSH s}(i_1)$; $\\texttt{XCHG s}(\\beta)$, followed by the translation of $O'$ $\\texttt{s}(i_2+1)$,$\\ldots$,$\\texttt{s}(i_\\gamma+1)$, defined by the induction hypothesis.<a id=\"ref-fn10\"></a><sup>[10](#fn10)</sup>\n\n### 2.2.6. Stack manipulation instructions are polymorphic\n\nNotice that the stack manipulation instructions are almost the only \"polymorphic\" primitives in TVM—i.e., they work with values of arbitrary types (including the value types that will appear only in future revisions of TVM). For example, $\\texttt{SWAP}$ always interchanges the two top values of the stack, even if one of them is an integer and the other is a cell. Almost all other instructions, especially the data processing instructions (including arithmetic instructions), require each of their arguments to be of some fixed type (possibly different for different arguments).\n\n## 2.3   Efficiency of stack manipulation primitives\n\nStack manipulation primitives employed by a stack machine, such as TVM, have to be implemented very efficiently, because they constitute more than half of all the instructions used in a typical program. In fact, TVM performs all these instructions in a (small) constant time, regardless of the values involved (even if they represent very large integers or very large trees of cells).\n\n### 2.3.1. Implementation of stack manipulation primitives: using references for operations instead of objects\n\nThe efficiency of TVM's implementation of stack manipulation primitives results from the fact that a typical TVM implementation keeps in the stack not the value objects themselves, but only the references (pointers) to such objects. Therefore, a $\\texttt{SWAP}$ instruction only needs to interchange the references at $\\texttt{s0}$ and $\\texttt{s1}$, not the actual objects they refer to.\n\n### 2.3.2.  Efficient implementation of $\\texttt{DUP}$ and $\\texttt{PUSH}$ instructions using copy-on-write\n\nFurthermore, a $\\texttt{DUP}$ (or, more generally, $\\texttt{PUSH s}(i)$) instruction, which appears to make a copy of a potentially large object, also works in small constant time, because it uses a copy-on-write technique of delayed copying: it copies only the reference instead of the object itself, but increases the \"reference counter\" inside the object, thus sharing the object between the two references. If an attempt to modify an object with a reference counter greater than one is detected, a separate copy of the object in question is made first (incurring a certain \"non-uniqueness penalty\" or \"copying penalty\" for the data manipulation instruction that triggered the creation of a new copy).\n\n### 2.3.3. Garbage collecting and reference counting\n\nWhen the reference counter of a TVM object becomes zero (for example, because the last reference to such an object has been consumed by a $\\texttt{DROP}$ operation or an arithmetic instruction), it is immediately freed. Because cyclic references are impossible in TVM data structures, this method of reference counting provides a fast and convenient way of freeing unused objects, replacing slow and unpredictable garbage collectors.\n\n### 2.3.4. Transparency of the implementation: Stack values are \"values\", not \"references\"\n\nRegardless of the implementation details just discussed, all stack values are really \"values\", not \"references\", from the perspective of the TVM programmer, similarly to the values of all types in functional programming languages. Any attempt to modify an existing object referred to from any other objects or stack locations will result in a transparent replacement of this object by its perfect copy before the modification is actually performed.\n\nIn other words, the programmer should always act as if the objects themselves were directly manipulated by stack, arithmetic, and other data transformation primitives, and treat the previous discussion only as an explanation of the high efficiency of the stack manipulation primitives.\n\n### 2.3.5. Absence of circular references\n\nOne might attempt to create a circular reference between two cells, $A$ and $B$, as follows: first create $A$ and write some data into it; then create $B$ and write some data into it, along with a reference to previously constructed cell $A$; finally, add a reference to $B$ into $A$. While it may seem that after this sequence of operations we obtain a cell $A$, which refers to $B$, which in turn refers to $A$, this is not the case. In fact, we obtain a new cell $A'$, which contains a copy of the data originally stored into cell $A$ along with a reference to cell $B$, which contains a reference to (the original) cell $A$.\n\nIn this way the transparent copy-on-write mechanism and the \"everything is a value\" paradigm enable us to create new cells using only previously constructed cells, thus forbidding the appearance of circular references. This property also applies to all other data structures: for instance, the absence of circular references enables TVM to use reference counting to immediately free unused memory instead of relying on garbage collectors. Similarly, this property is crucial for storing data in the TON Blockchain.\n\n---\n\n# 3   Cells, memory, and persistent storage\n\nThis chapter briefly describes TVM cells, used to represent all data structures inside the TVM memory and its persistent storage, and the basic operations used to create cells, write (or serialize) data into them, and read (or deserialize) data from them.\n\n## 3.1   Generalities on cells\n\nThis section presents a classification and general descriptions of cell types.\n\n### 3.1.1. TVM memory and persistent storage consist of cells\n\nRecall that the TVM memory and persistent storage consist of *(TVM) cells*. Each cell contains up to 1023 bits of data and up to four references to other cells.<a id=\"ref-fn11\"></a><sup>[11](#fn11)</sup> [Circular references](#2-3-5-absence-of-circular-references) are forbidden and cannot be created by means of TVM. In this way, all cells kept in TVM memory and persistent storage constitute a directed acyclic graph (DAG).\n\n### 3.1.2. Ordinary and exotic cells\n\nApart from the data and references, a cell has a *cell type*, encoded by an integer $-1\\ldots255$. A cell of type $-1$ is called *ordinary*; such cells do not require any special processing. Cells of other types are called *exotic*, and may be *loaded*—automatically replaced by other cells when an attempt to deserialize them (i.e., to convert them into a *Slice* by a $\\texttt{CTOS}$ instruction) is made. They may also exhibit a non-trivial behavior when their hashes are computed.\n\nThe most common use for exotic cells is to represent some other cells—for instance, cells present in an external library, or pruned from the original tree of cells when a Merkle proof has been created.\n\nThe type of an exotic cell is stored as the first eight data bits of its data. If an exotic cell has less than eight data bits, it is invalid.\n\n### 3.1.3. The level of a cell\n\nEvery cell $c$ has another attribute $\\text{Lvl}(c)$ called its *(de Brujn) level*, which currently takes integer values in the range $0\\ldots3$. The level of an ordinary cell is always equal to the maximum of the levels of all its children $c_i$:\n\n$$\n\\text{Lvl}(c)=\\max_{1\\leq i\\leq r}\\text{Lvl}(c_i) \\tag{1}\n$$\n\nfor an ordinary cell $c$ containing $r$ references to cells $c_1$, $\\ldots$, $c_r$. If $r=0$, $\\text{Lvl}(c)=0$. Exotic cells may have different rules for setting their level.\n\nA cell's level affects the number of *higher hashes* it has. More precisely, a level $l$ cell has $l$ higher hashes $\\text{Hash}_1(c)$, $\\ldots$, $\\text{Hash}_l(c)$ in addition to its representation hash $\\text{Hash}(c)=\\text{Hash}_\\infty(c)$. Cells of non-zero level appear inside *Merkle proofs* and *Merkle updates*, after some branches of the tree of cells representing a value of an abstract data type are pruned.\n\n### 3.1.4. Standard cell representation\n\nWhen a cell needs to be transferred by a network protocol or stored in a disk file, it must be *serialized*. The standard representation $\\text{CellRepr}(c)=\\text{CellRepr}_\\infty(c)$ of a cell $c$ as an octet (byte) sequence is constructed as follows:\n\n1. Two descriptor bytes $d_1$ and $d_2$ are serialized first. Byte $d_1$ equals $r+8s+32l$, where $0\\leq r\\leq 4$ is the quantity of cell references contained in the cell, $0\\leq l\\leq 3$ is the level of the cell, and $0\\leq s\\leq 1$ is $1$ for exotic cells and $0$ for ordinary cells. Byte $d_2$ equals $\\lfloor b/8\\rfloor+\\lceil b/8\\rceil$, where $0\\leq b\\leq 1023$ is the quantity of data bits in $c$.\n\n2. Then the data bits are serialized as $\\lceil b/8\\rceil$ 8-bit octets (bytes). If $b$ is not a multiple of eight, a binary $\\texttt{1}$ and up to six binary $\\texttt{0}$s are appended to the data bits. After that, the data is split into $\\lceil b/8\\rceil$ eight-bit groups, and each group is interpreted as an unsigned big-endian integer $0\\ldots 255$ and stored into an octet.\n\n3. Finally, each of the $r$ cell references is represented by 32 bytes containing the 256-bit [representation hash](#3-1-5-the-representation-hash-of-a-cell) $\\text{Hash}(c_i)$ of the cell $c_i$ referred to.\n\nIn this way, $2+\\lceil b/8\\rceil+32r$ bytes of $\\text{CellRepr}(c)$ are obtained.\n\n### 3.1.5. The representation hash of a cell\n\nThe 256-bit *representation hash* or simply *hash* $\\text{Hash}(c)$ of a cell $c$ is recursively defined as the SHA-256 of the standard representation of the cell $c$:\n\n$$\n\\text{Hash}(c):=\\text{Sha256}\\bigl(\\text{CellRepr}(c)\\bigr) \\tag{2}\n$$\n\nNotice that [cyclic cell references](#2-3-5-absence-of-circular-references) are not allowed and cannot be created by means of the TVM, so this recursion always ends, and the representation hash of any cell is well-defined.\n\n### 3.1.6. The higher hashes of a cell\n\nRecall that a cell $c$ of level $l$ has $l$ higher hashes $\\text{Hash}_i(c)$, $1\\leq i\\leq l$, as well. Exotic cells have their own rules for computing their higher hashes. Higher hashes $\\text{Hash}_i(c)$ of an ordinary cell $c$ are computed similarly to its representation hash, but using the higher hashes $\\text{Hash}_i(c_j)$ of its children $c_j$ instead of their representation hashes $\\text{Hash}(c_j)$. By convention, we set $\\text{Hash}_\\infty(c):=\\text{Hash}(c)$, and $\\text{Hash}_i(c):=\\text{Hash}_\\infty(c)=\\text{Hash}(c)$ for all $i>l$.<a id=\"ref-fn12\"></a><sup>[12](#fn12)</sup>\n\n### 3.1.7. Types of exotic cells\n\nTVM currently supports the following cell types:\n\n- Type $-1$: *Ordinary cell* — Contains up to 1023 bits of data and up to four cell references.\n\n- Type 1: *Pruned branch cell $c$* — May have any level $1\\leq l\\leq 3$. It contains exactly $8+256l$ data bits: first an 8-bit integer equal to 1 (representing the cell's type), then its $l$ higher hashes $\\text{Hash}_1(c)$, $\\ldots$, $\\text{Hash}_l(c)$. The level $l$ of a pruned branch cell may be called its *de Brujn index*, because it determines the outer Merkle proof or Merkle update during the construction of which the branch has been pruned. An attempt to load a pruned branch cell usually leads to an exception.\n\n- Type 2: *Library reference cell* — Always has level 0, and contains $8+256$ data bits, including its 8-bit type integer 2 and the representation hash $\\text{Hash}(c')$ of the library cell being referred to. When loaded, a library reference cell may be transparently replaced by the cell it refers to, if found in the current *library context*.\n\n- Type 3: *Merkle proof cell $c$* — Has exactly one reference $c_1$ and level $0\\leq l\\leq 3$, which must be one less than the level of its only child $c_1$:\n\n  $$\n  \\text{Lvl}(c)=\\max(\\text{Lvl}(c_1)-1,0) \\tag{3}\n  $$\n\n  The $8+256$ data bits of a Merkle proof cell contain its 8-bit type integer 3, followed by $\\text{Hash}_1(c_1)$ (assumed to be equal to $\\text{Hash}(c_1)$ if $\\text{Lvl}(c_1)=0$). The higher hashes $\\text{Hash}_i(c)$ of $c$ are computed similarly to the higher hashes of an ordinary cell, but with $\\text{Hash}_{i+1}(c_1)$ used instead of $\\text{Hash}_i(c_1)$. When loaded, a Merkle proof cell is replaced by $c_1$.\n\n- Type 4: *Merkle update cell $c$* — Has two children $c_1$ and $c_2$. Its level $0\\leq l\\leq 3$ is given by\n\n  $$\n  \\text{Lvl}(c)=\\max(\\text{Lvl}(c_1)-1,\\text{Lvl}(c_2)-1,0) \\tag{4}\n  $$\n\n  A Merkle update behaves like a Merkle proof for both $c_1$ and $c_2$, and contains $8+256+256$ data bits with $\\text{Hash}_1(c_1)$ and $\\text{Hash}_1(c_2)$. However, an extra requirement is that *all pruned branch cells $c'$ that are descendants of $c_2$ and are bound by $c$ must also be descendants of $c_1$.*<a id=\"ref-fn13\"></a><sup>[13](#fn13)</sup> When a Merkle update cell is loaded, it is replaced by $c_2$.\n\n### 3.1.8. All values of algebraic data types are trees of cells\n\nArbitrary values of arbitrary algebraic data types (e.g., all types used in functional programming languages) can be serialized into trees of cells (of level 0), and such representations are used for representing such values within TVM. The [copy-on-write mechanism](#2-3-2-efficient-implementation-of-and-instructions-using-copy-on-write) allows TVM to identify cells containing the same data and references, and to keep only one copy of such cells. This actually transforms a tree of cells into a directed acyclic graph (with the additional property that all its vertices be accessible from a marked vertex called the \"root\"). However, this is a storage optimization rather than an essential property of TVM. From the perspective of a TVM code programmer, one should think of TVM data structures as trees of cells.\n\n### 3.1.9. TVM code is a tree of cells\n\nThe TVM code itself is also represented by a tree of cells. Indeed, TVM code is simply a value of some complex algebraic data type, and as such, it can be serialized into a tree of cells.\n\nThe exact way in which the TVM code (e.g., TVM assembly code) is transformed into a tree of cells is explained later ([4.1.4](#4-1-4-normal-work-of-tvm%2C-or-the-main-loop) and [5.2](#5-2-instruction-encoding)), in sections discussing control flow instructions, continuations, and TVM instruction encoding.\n\n### 3.1.10. \"Everything is a bag of cells\" paradigm\n\nAll the data used by the TON Blockchain, including the blocks themselves and the blockchain state, can be represented—and are represented—as collections, or [bags of cells](/foundations/whitepapers/ton#2-5-14-“everything-is-a-bag-of-cells”-philosophy). We see that TVM's [structure of data](#3-1-8-all-values-of-algebraic-data-types-are-trees-of-cells) and [code](#3-1-9-tvm-code-is-a-tree-of-cells) nicely fits into this \"everything is a bag of cells\" paradigm. In this way, TVM can naturally be used to execute smart contracts in the TON Blockchain, and the TON Blockchain can be used to store the code and persistent data of these smart contracts between invocations of TVM. (Of course, both TVM and the TON Blockchain have been designed so that this would become possible.)\n\n## 3.2   Data manipulation instructions and cells\n\nThe next large group of TVM instructions consists of *data manipulation instructions*, also known as *cell manipulation instructions* or simply *cell instructions*. They correspond to memory access instructions of other architectures.\n\n### 3.2.1. Classes of cell manipulation instructions\n\nThe TVM cell instructions are naturally subdivided into two principal classes:\n\n- *Cell creation instructions* or *serialization instructions*, used to construct new cells from values previously kept in the stack and previously constructed cells.\n- *Cell parsing instructions* or *deserialization instructions*, used to extract data previously stored into cells by cell creation instructions.\n\nAdditionally, there are *exotic cell instructions* used to create and inspect [exotic cells](#3-1-2-ordinary-and-exotic-cells), which in particular are used to represent pruned branches of Merkle proofs and Merkle proofs themselves.\n\n### 3.2.2. *Builder* and *Slice* values\n\nCell creation instructions usually work with [Builder values](#1-1-3-preliminary-list-of-value-types), which can be kept only in the stack. Such values represent partially constructed cells, for which fast operations for appending bitstrings, integers, other cells, and references to other cells can be defined. Similarly, cell parsing instructions make heavy use of *Slice* values, which represent either the remainder of a partially parsed cell, or a value (subcell) residing inside such a cell and extracted from it by a parsing instruction.\n\n### 3.2.3. *Builder* and *Slice* values exist only as stack values\n\nNotice that *Builder* and *Slice* objects appear only as values in a TVM stack. They cannot be stored in \"memory\" (i.e., trees of cells) or \"persistent storage\" (which is also a bag of cells). In this sense, there are far more *Cell* objects than *Builder* or *Slice* objects in a TVM environment, but, somewhat paradoxically, a TVM program sees *Builder* and *Slice* objects in its stack more often than *Cell*s. In fact, a TVM program does not have much use for *Cell* values, because they are immutable and opaque; all cell manipulation primitives require that a *Cell* value be transformed into either a *Builder* or a *Slice* first, before it can be modified or inspected.\n\n### 3.2.4. TVM has no separate *Bitstring* value type\n\nNotice that TVM offers no separate bitstring value type. Instead, bitstrings are represented by *Slices* that happen to have no references at all, but can still contain up to 1023 data bits.\n\n### 3.2.5. Cells and cell primitives are bit-oriented, not byte-oriented\n\nAn important point is that *TVM regards data kept in cells as sequences (strings, streams) of (up to 1023) bits, not of bytes*. In other words, TVM is a *bit-oriented machine*, not a byte-oriented machine. If necessary, an application is free to use, say, 21-bit integer fields inside records serialized into TVM cells, thus using fewer persistent storage bytes to represent the same data.\n\n### 3.2.6. Taxonomy of cell creation (serialization) primitives\n\nCell creation primitives usually accept a *Builder* argument and an argument representing the value to be serialized. Additional arguments controlling some aspects of the serialization process (e.g., how many bits should be used for serialization) can be also provided, either in the stack or as an immediate value inside the instruction. The result of a cell creation primitive is usually another *Builder*, representing the concatenation of the original builder and the serialization of the value provided.\n\nTherefore, one can suggest a classification of cell serialization primitives according to the answers to the following questions:\n\n- Which is the type of values being serialized?\n- How many bits are used for serialization? If this is a variable number, does it come from the stack, or from the instruction itself?\n- What happens if the value does not fit into the prescribed number of bits? Is an exception generated, or is a success flag equal to zero silently returned in the top of stack?\n- What happens if there is insufficient space left in the *Builder*? Is an exception generated, or is a zero success flag returned along with the unmodified original *Builder*?\n\nThe mnemonics of cell serialization primitives usually begin with $\\texttt{ST}$. Subsequent letters describe the following attributes:\n\n- The type of values being serialized and the serialization format (e.g., $\\texttt{I}$ for signed integers, $\\texttt{U}$ for unsigned integers).\n- The source of the field width in bits to be used (e.g., $\\texttt{X}$ for integer serialization instructions means that the bit width $n$ is supplied in the stack; otherwise it has to be embedded into the instruction as an immediate value).\n- The action to be performed if the operation cannot be completed (by default, an exception is generated; \"quiet\" versions of serialization instructions are marked by a $\\texttt{Q}$ letter in their mnemonics).\n\nThis classification scheme is used to create a more complete taxonomy of [cell serialization primitives](#a-7-1-cell-serialization-primitives).\n\n### 3.2.7. Integer serialization primitives\n\nInteger serialization primitives can be classified according to the above taxonomy as well. For example:\n\n- There are signed and unsigned (big-endian) integer serialization primitives.\n- The size $n$ of the bit field to be used ($1\\leq n\\leq 257$ for signed integers, $0\\leq n\\leq 256$ for unsigned integers) can either come from the top of stack or be embedded into the instruction itself.\n- If the integer $x$ to be serialized is not in the range $-2^{n-1}\\leq x<2^{n-1}$ (for signed integer serialization) or $0\\leq x<2^n$ (for unsigned integer serialization), a range check exception is usually generated, and if $n$ bits cannot be stored into the provided *Builder*, a cell overflow exception is usually generated.\n- Quiet versions of serialization instructions do not throw exceptions; instead, they push $-1$ on top of the resulting *Builder* upon success, or return the original *Builder* with $0$ on top of it to indicate failure.\n\nInteger serialization instructions have mnemonics like $\\texttt{STU 20}$ (\"store an unsigned 20-bit integer value\") or $\\texttt{STIXQ}$ (\"quietly store an integer value of variable length provided in the stack\"). The full list of these [instructions](#a-7-1-cell-serialization-primitives)—includes their mnemonics, descriptions, and opcodes.\n\n### 3.2.8. Integers in cells are big-endian by default\n\nNotice that the default order of bits in *Integers* serialized into *Cells* is *big-endian*, not little-endian.<a id=\"ref-fn14\"></a><sup>[14](#fn14)</sup> In this respect *TVM is a big-endian machine*. However, this affects only the serialization of integers inside cells. The internal representation of the *Integer* value type is implementation-dependent and irrelevant for the operation of TVM. Besides, there are some special primitives such as $\\texttt{STULE}$ for (de)serializing little-endian integers, which must be stored into an integral number of bytes (otherwise \"little-endianness\" does not make sense, unless one is also willing to revert the order of bits inside octets). Such primitives are useful for interfacing with the little-endian world—for instance, for parsing custom-format messages arriving to a TON Blockchain smart contract from the outside world.\n\n### 3.2.9. Other serialization primitives\n\nOther cell creation primitives serialize bitstrings (i.e., cell slices without references), either taken from the stack or supplied as literal arguments; cell slices (which are concatenated to the cell builder in an obvious way); other *Builders* (which are also concatenated); and cell references ($\\texttt{STREF}$).\n\n### 3.2.10. Other cell creation primitives\n\nIn addition to the cell serialization primitives for certain built-in value types described above, there are simple primitives that create a new empty *Builder* and push it into the stack ($\\texttt{NEWC}$), or transform a *Builder* into a *Cell* ($\\texttt{ENDC}$), thus finishing the cell creation process. An $\\texttt{ENDC}$ can be combined with a $\\texttt{STREF}$ into a single instruction $\\texttt{ENDCST}$, which finishes the creation of a cell and immediately stores a reference to it in an \"outer\" *Builder*. There are also primitives that obtain the quantity of data bits or references already stored in a *Builder*, and check how many data bits or references can be stored.\n\n### 3.2.11. Taxonomy of cell deserialisation primitives\n\nCell parsing, or deserialization, [primitives](#3-2-6-taxonomy-of-cell-creation-serialization-primitives) can be classified with the following modifications:\n\n- They work with *Slices* (representing the remainder of the cell being parsed) instead of *Builders*.\n- They return deserialized values instead of accepting them as arguments.\n- They may come in two flavors, depending on whether they remove the deserialized portion from the *Slice* supplied (\"fetch operations\") or leave it unmodified (\"prefetch operations\").\n- Their mnemonics usually begin with $\\texttt{LD}$ (or $\\texttt{PLD}$ for prefetch operations) instead of $\\texttt{ST}$.\n\nFor example, an unsigned big-endian 20-bit integer previously serialized into a cell by a $\\texttt{STU 20}$ instruction is likely to be deserialized later by a matching $\\texttt{LDU 20}$ instruction.\n\nAgain, more detailed information about these instructions is provided in [A.7.2](#a-7-2-cell-deserialization-primitives).\n\n### 3.2.12. Other cell slice primitives\n\nIn addition to the cell deserialisation primitives outlined above, TVM provides some obvious primitives for initializing and completing the cell deserialization process. For instance, one can convert a *Cell* into a *Slice* ($\\texttt{CTOS}$), so that its deserialisation might begin; or check whether a *Slice* is empty, and generate an exception if it is not ($\\texttt{ENDS}$); or deserialize a cell reference and immediately convert it into a *Slice* ($\\texttt{LDREFTOS}$, equivalent to two instructions $\\texttt{LDREF}$ and $\\texttt{CTOS}$).\n\n### 3.2.13. Modifying a serialized value in a cell\n\nThe reader might wonder how the values serialized inside a cell may be modified. Suppose a cell contains three serialized 29-bit integers, $(x,y,z)$, representing the coordinates of a point in space, and we want to replace $y$ with $y'=y+1$, leaving the other coordinates intact. How would we achieve this?\n\nTVM does not offer any ways to modify existing values ([2.3.4](#2-3-4-transparency-of-the-implementation:-stack-values-are-“values”,-not-“references”) and [2.3.5](#2-3-5-absence-of-circular-references)), so our example can only be accomplished with a series of operations as follows:\n\n1. Deserialize the original cell into three *Integer*s $x$, $y$, $z$ in the stack (e.g., by $\\texttt{CTOS}$; $\\texttt{LDI 29}$; $\\texttt{LDI 29}$; $\\texttt{LDI 29}$; $\\texttt{ENDS}$).\n2. Increase $y$ by one (e.g., by $\\texttt{SWAP}$; $\\texttt{INC}$; $\\texttt{SWAP}$).\n3. Finally, serialize the resulting *Integer*s into a new cell (e.g., by $\\texttt{XCHG s2}$; $\\texttt{NEWC}$; $\\texttt{STI 29}$; $\\texttt{STI 29}$; $\\texttt{STI 29}$; $\\texttt{ENDC}$).\n\n### 3.2.14. Modifying the persistent storage of a smart contract\n\nIf the TVM code wants to modify its persistent storage, represented by the tree of cells rooted at $\\texttt{c4}$, it simply needs to rewrite control register $\\texttt{c4}$ by the root of the tree of cells containing the new value of its persistent storage. (If only part of the persistent storage needs to be [modified](#3-2-13-modifying-a-serialized-value-in-a-cell).)\n\n---\n\n## 3.3   Hashmaps, or dictionaries\n\n*Hashmaps*, or *dictionaries*, are a specific data structure represented by a tree of cells. Essentially, a hashmap represents a map from *keys*, which are bitstrings of either fixed or variable length, into *values* of an arbitrary type $X$, in such a way that fast lookups and modifications be possible. While any such structure might be inspected or modified with the aid of generic cell serialization and deserialization primitives, TVM introduces special primitives to facilitate working with these hashmaps.\n\n### 3.3.1. Basic hashmap types\n\nThe two most basic hashmap types predefined in TVM are *HashmapE* $n$ $X$ or *HashmapE*$(n,X)$, which represents a partially defined map from $n$-bit strings (called *keys*) for some fixed $0\\leq n\\leq 1023$ into *values* of some type $X$, and *Hashmap*$(n,X)$, which is similar to *HashmapE*$(n,X)$ but is not allowed to be empty (i.e., it must contain at least one key-value pair).\n\nOther hashmap types are also available—for example, one with keys of arbitrary length up to some predefined bound (up to 1023 bits).\n\n### 3.3.2. Hashmaps as Patricia trees\n\nThe abstract representation of a hashmap in TVM is a *Patricia tree*, or a *compact binary trie*. It is a binary tree with edges labelled by bitstrings, such that the concatenation of all edge labels on a path from the root to a leaf equals a key of the hashmap. The corresponding value is kept in this leaf (for hashmaps with keys of fixed length), or optionally in the intermediate vertices as well (for hashmaps with keys of variable length). Furthermore, any intermediate vertex must have two children, and the label of the left child must begin with a binary zero, while the label of the right child must begin with a binary one. This enables us not to store the first bit of the edge labels explicitly.\n\nIt is easy to see that any collection of key-value pairs (with distinct keys) is represented by a unique Patricia tree.\n\n### 3.3.3. Serialization of hashmaps\n\nThe serialization of a hashmap into a tree of cells (or, more generally, into a *Slice*) is defined by the following TL-B scheme:<a id=\"ref-fn15\"></a><sup>[15](#fn15)</sup>\n\n```\nbit#_ _:(## 1) = Bit;\n\nhm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l n) \n          {n = (~m) + l} node:(HashmapNode m X) = Hashmap n X;\n\nhmn_leaf#_ {X:Type} value:X = HashmapNode 0 X;\nhmn_fork#_ {n:#} {X:Type} left:^(Hashmap n X) \n           right:^(Hashmap n X) = HashmapNode (n + 1) X;\n\nhml_short$0 {m:#} {n:#} len:(Unary ~n) \n            s:(n * Bit) = HmLabel ~n m;\nhml_long$10 {m:#} n:(#<= m) s:(n * Bit) = HmLabel ~n m;\nhml_same$11 {m:#} v:Bit n:(#<= m) = HmLabel ~n m;\n\nunary_zero$0 = Unary ~0;\nunary_succ$1 {n:#} x:(Unary ~n) = Unary ~(n + 1);\n\nhme_empty$0 {n:#} {X:Type} = HashmapE n X;\nhme_root$1 {n:#} {X:Type} root:^(Hashmap n X) = HashmapE n X;\n\ntrue#_ = True;\n_ {n:#} _:(Hashmap n True) = BitstringSet n;\n```\n\n### 3.3.4. Brief explanation of TL-B schemes\n\nA TL-B scheme, like the one above, includes the following components.\n\nThe right-hand side of each \"equation\" is a *type*, either simple (such as $\\texttt{Bit}$ or $\\texttt{True}$) or parametrized (such as $\\texttt{Hashmap}$ $n$ $X$). The parameters of a type must be either natural numbers (i.e., non-negative integers, which are required to fit into 32 bits in practice), such as $n$ in $\\texttt{Hashmap}$ $n$ $X$, or other types, such as $X$ in $\\texttt{Hashmap}$ $n$ $X$.\n\nThe left-hand side of each equation describes a way to define, or even to serialize, a value of the type indicated in the right-hand side. Such a description begins with the name of a *constructor*, such as $\\texttt{hm\\_edge}$ or $\\texttt{hml\\_long}$, immediately followed by an optional *constructor tag*, such as #\\_ or \\$10, which describes the bitstring used to encode (serialize) the constructor in question. Such tags may be given in either binary (after a dollar sign) or [hexadecimal notation](#1-0-notation-for-bitstrings) (after a hash sign), using the conventions. If a tag is not explicitly provided, TL-B computes a default 32-bit constructor tag by hashing the text of the \"equation\" defining this constructor in a certain fashion. Therefore, empty tags must be explicitly provided by #\\_ or \\$\\_. All constructor names must be distinct, and constructor tags for the same type must constitute a prefix code (otherwise the deserialization would not be unique).\n\nThe constructor and its optional tag are followed by *field definitions*. Each field definition is of the form $\\textit{ident}:\\textit{type-expr}$, where $\\textit{ident}$ is an identifier with the name of the field<a id=\"ref-fn16\"></a><sup>[16](#fn16)</sup> (replaced by an underscore for anonymous fields), and $\\textit{type-expr}$ is the field's type. The type provided here is a *type expression*, which may include simple types or parametrized types with suitable parameters. *Variables*—i.e., the (identifiers of the) previously defined fields of types $\\#$ (natural numbers) or $\\textit{Type}$ (type of types)—may be used as parameters for the parametrized types. The serialization process recursively serializes each field according to its type, and the serialization of a value ultimately consists of the concatenation of bitstrings representing the constructor (i.e., the constructor tag) and the field values.\n\nSome fields may be *implicit*. Their definitions are surrounded by curly braces, which indicate that the field is not actually present in the serialization, but that its value must be deduced from other data (usually the parameters of the type being serialized).\n\nSome occurrences of \"variables\" (i.e., already-defined fields) are prefixed by a tilde. This indicates that the variable's occurrence is used in the opposite way of the default behavior: in the left-hand side of the equation, it means that the variable will be deduced (computed) based on this occurrence, instead of substituting its previously computed value; in the right-hand side, conversely, it means that the variable will not be deduced from the type being serialized, but rather that it will be computed during the deserialization process. In other words, a tilde transforms an \"input argument\" into an \"output argument\", and vice versa.<a id=\"ref-fn17\"></a><sup>[17](#fn17)</sup>\n\nFinally, some equalities may be included in curly brackets as well. These are certain \"equations\", which must be satisfied by the \"variables\" included in them. If one of the variables is prefixed by a tilde, its value will be uniquely determined by the values of all other variables participating in the equation (which must be known at this point) when the definition is processed from the left to the right.\n\nA caret (^) preceding a type $X$ means that instead of serializing a value of type $X$ as a bitstring inside the current cell, we place this value into a separate cell, and add a reference to it into the current cell. Therefore `^`$X$ means \"the type of references to cells containing values of type $X$\".\n\nParametrized type $\\texttt{\\#<= }p$ with $p:\\texttt{\\#}$ (this notation means \"$p$ of type $\\texttt{\\#}$\", i.e., a natural number) denotes the subtype of the natural numbers type $\\texttt{\\#}$, consisting of integers $0\\ldots p$; it is serialized into $\\lceil\\log_2(p+1)\\rceil$ bits as an unsigned big-endian integer. Type $\\texttt{\\#}$ by itself is serialized as an unsigned 32-bit integer. Parametrized type $\\texttt{\\#\\# }b$ with $b:\\texttt{\\#<=}31$ is equivalent to $\\texttt{\\#<= }2^b-1$ (i.e., it is an unsigned $b$-bit integer).\n\n### 3.3.5. Application to the serialization of hashmaps\n\nLet us explain the net result of applying the [general rules](#3-3-4-brief-explanation-of-tl-b-schemes) to the [TL-B scheme](#3-3-3-serialization-of-hashmaps).\n\nSuppose we wish to serialize a value of type *HashmapE* $n$ $X$ for some integer $0\\leq n\\leq 1023$ and some type $X$ (i.e., a dictionary with $n$-bit keys and values of type $X$, admitting an abstract representation as a [Patricia tree](#3-3-2-hashmaps-as-patricia-trees)).\n\nFirst of all, if our dictionary is empty, it is serialized into a single binary $\\texttt{0}$, which is the tag of nullary constructor $\\texttt{hme\\_empty}$. Otherwise, its serialization consists of a binary $\\texttt{1}$ (the tag of $\\texttt{hme\\_root}$), along with a reference to a cell containing the serialization of a value of type *Hashmap* $n$ $X$ (i.e., a necessarily non-empty dictionary).\n\nThe only way to serialize a value of type *Hashmap* $n$ $X$ is given by the $\\texttt{hm\\_edge}$ constructor, which instructs us to serialize first the label $\\texttt{label}$ of the edge leading to the root of the subtree under consideration (i.e., the common prefix of all keys in our (sub)dictionary). This label is of type $\\texttt{HmLabel}$ $l^\\perp$ $n$, which means that it is a bitstring of length at most $n$, serialized in such a way that the true length $l$ of the label, $0\\leq l\\leq n$, becomes known from the [serialization](#3-3-6-serialization-of-labels) of the label.\n\nThe label must be followed by the serialization of a $\\texttt{node}$ of type $\\texttt{HashmapNode}$ $m$ $X$, where $m=n-l$. It corresponds to a vertex of the Patricia tree, representing a non-empty subdictionary of the original dictionary with $m$-bit keys, obtained by removing from all the keys of the original subdictionary their common prefix of length $l$.\n\nIf $m=0$, a value of type $\\texttt{HashmapNode}$ $0$ $X$ is given by the $\\texttt{hmn\\_leaf}$ constructor, which describes a leaf of the Patricia tree—or, equivalently, a subdictionary with $0$-bit keys. A leaf simply consists of the corresponding $\\texttt{value}$ of type $X$ and is serialized accordingly.\n\nOn the other hand, if $m>0$, a value of type $\\texttt{HashmapNode}$ $m$ $X$ corresponds to a fork (i.e., an intermediate node) in the Patricia tree, and is given by the $\\texttt{hmn\\_fork}$ constructor. Its serialization consists of $\\texttt{left}$ and $\\texttt{right}$, two references to cells containing values of type $\\texttt{Hashmap}$ $m-1$ $X$, which correspond to the left and the right child of the intermediate node in question—or, equivalently, to the two subdictionaries of the original dictionary consisting of key-value pairs with keys beginning with a binary $\\texttt{0}$ or a binary $\\texttt{1}$, respectively. Because the first bit of all keys in each of these subdictionaries is known and fixed, it is removed, and the resulting (necessarily non-empty) subdictionaries are recursively serialized as values of type $\\texttt{Hashmap}$ $m-1$ $X$.\n\n### 3.3.6. Serialization of labels\n\nThere are several ways to serialize a label of length at most $n$, if its exact length is $l\\leq n$ (recall that the exact length must be deducible from the serialization of the label itself, while the upper bound $n$ is known before the label is serialized or deserialized). These ways are described by the three constructors $\\texttt{hml\\_short}$, $\\texttt{hml\\_long}$, and $\\texttt{hml\\_same}$ of type $\\texttt{HmLabel}$ $l^\\perp$ $n$:\n\n- $\\texttt{hml\\_short}$ — Describes a way to serialize \"short\" labels, of small length $l\\leq n$. Such a serialization consists of a binary $\\texttt{0}$ (the constructor tag of $\\texttt{hml\\_short}$), followed by $l$ binary $\\texttt{1}$s and one binary $\\texttt{0}$ (the unary representation of the length $l$), followed by $l$ bits comprising the label itself.\n\n- $\\texttt{hml\\_long}$ — Describes a way to serialize \"long\" labels, of arbitrary length $l\\leq n$. Such a serialization consists of a binary $\\texttt{10}$ (the constructor tag of $\\texttt{hml\\_long}$), followed by the big-endian binary representation of the length $0\\leq l\\leq n$ in $\\lceil\\log_2(n+1)\\rceil$ bits, followed by $l$ bits comprising the label itself.\n\n- $\\texttt{hml\\_same}$ — Describes a way to serialize \"long\" labels, consisting of $l$ repetitions of the same bit $v$. Such a serialization consists of $\\texttt{11}$ (the constructor tag of $\\texttt{hml\\_same}$), followed by the bit $v$, followed by the length $l$ stored in $\\lceil\\log_2(n+1)\\rceil$ bits as before.\n\nEach label can always be serialized in at least two different fashions, using $\\texttt{hml\\_short}$ or $\\texttt{hml\\_long}$ constructors. Usually the shortest serialization (and in the case of a tie—the lexicographically smallest among the shortest) is preferred and is generated by TVM hashmap primitives, while the other variants are still considered valid.\n\nThis label encoding scheme has been designed to be efficient for dictionaries with \"random\" keys (e.g., hashes of some data), as well as for dictionaries with \"regular\" keys (e.g., big-endian representations of integers in some range).\n\n### 3.3.7. An example of dictionary serialization\n\nConsider a dictionary with three 16-bit keys 13, 17, and 239 (considered as big-endian integers) and corresponding 16-bit values 169, 289, and 57121.\n\nIn binary form:\n\n```\n0000000000001101 => 0000000010101001\n0000000000010001 => 0000000100100001\n0000000011101111 => 1101111100100001\n```\n\nThe corresponding Patricia tree consists of a root $A$, two intermediate nodes $B$ and $C$, and three leaf nodes $D$, $E$, and $F$, corresponding to 13, 17, and 239, respectively. The root $A$ has only one child, $B$; the label on the edge $AB$ is $00000000=0^8$. The node $B$ has two children: its left child is an intermediate node $C$ with the edge $BC$ labelled by $(0)00$, while its right child is the leaf $F$ with $BF$ labelled by $(1)1101111$. Finally, $C$ has two leaf children $D$ and $E$, with $CD$ labelled by $(0)1101$ and $CE$—by $(1)0001$.\n\nThe corresponding value of type $\\texttt{HashmapE}$ 16 ($\\texttt{\\#\\#}$ 16) may be written in human-readable form as:\n\n```\n(hme_root$1 \n  root:^(hm_edge label:(hml_same$11 v:0 n:8) node:(hm_fork \n    left:^(hm_edge label:(hml_short$0 len:$110 s:$00) \n      node:(hm_fork\n        left:^(hm_edge label:(hml_long$10 n:4 s:$1101) \n          node:(hm_leaf value:169))\n        right:^(hm_edge label:(hml_long$10 n:4 s:$0001) \n          node:(hm_leaf value:289))))\n    right:^(hm_edge label:(hml_long$10 n:7 s:$1101111) \n      node:(hm_leaf value:57121)))))\n```\n\nThe serialization of this data structure into a tree of cells consists of six cells with the following binary data contained in them:\n\n```\nA := 1\nA.0 := 11 0 01000 \nA.0.0 := 0 110 00\nA.0.0.0 := 10 100 1101 0000000010101001\nA.0.0.1 := 10 100 0001 0000000100100001\nA.0.1 := 10 111 1101111 1101111100100001\n```\n\nHere $A$ is the root cell, $A.0$ is the cell at the first reference of $A$, $A.1$ is the cell at the second reference of $A$, and so on. This tree of cells can be represented more compactly using the [hexadecimal notation](#1-0-notation-for-bitstrings), using indentation to reflect the tree-of-cells structure:\n\n```\nC_\n C8\n  62_\n   A68054C_\n   A08090C_\n  BEFDF21\n```\n\nA total of 93 data bits and 5 references in 6 cells have been used to serialize this dictionary. Notice that a straightforward representation of three 16-bit keys and their corresponding 16-bit values would already require 96 bits (albeit without any references), so this particular serialization turns out to be quite efficient.\n\n\n### 3.3.8. Ways to describe the serialization of type $X$\n\nNotice that the built-in TVM primitives for dictionary manipulation need to know something about the serialization of type $X$; otherwise, they would not be able to work correctly with $\\mathit{Hashmap}$ $n$ $X$, because values of type $X$ are immediately contained in the Patricia tree leaf cells. There are several options available to describe the serialization of type $X$:\n\n- The simplest case is when $X = \\text{\\textasciicircum}Y$ for some other type $Y$. In this case the serialization of $X$ itself always consists of one reference to a cell, which in fact must contain a value of type $Y$, something that is not relevant for dictionary manipulation primitives.\n- Another simple case is when the serialization of any value of type $X$ always consists of $0\\leq b\\leq 1023$ data bits and $0\\leq r\\leq 4$ references. Integers $b$ and $r$ can then be passed to a dictionary manipulation primitive as a simple description of $X$. (Notice that the previous case corresponds to $b=0$, $r=1$.)\n- A more sophisticated case can be described by four integers $1\\leq b_0,b_1\\leq 1023$, $0\\leq r_0,r_1\\leq 4$, with $b_i$ and $r_i$ used when the first bit of the serialization equals $i$. When $b_0=b_1$ and $r_0=r_1$, this case reduces to the previous one.\n- Finally, the most general description of the serialization of a type $X$ is given by a *splitting function* $\\mathit{split}_X$ for $X$, which accepts one *Slice* parameter $s$, and returns two *Slice*s, $s'$ and $s''$, where $s'$ is the only prefix of $s$ that is the serialization of a value of type $X$, and $s''$ is the remainder of $s$. If no such prefix exists, the splitting function is expected to throw an exception. Notice that a compiler for a high-level language, which supports some or all algebraic TL-B types, is likely to automatically generate splitting functions for all types defined in the program.\n\n### 3.3.9. A simplifying assumption on the serialization of $X$\n\nOne may notice that values of type $X$ always occupy the remaining part of an $\\texttt{hm\\_edge}$/$\\texttt{hme\\_leaf}$ cell inside the serialization of a *HashmapE* $n$ $X$. Therefore, if we do not insist on strict validation of all dictionaries accessed, we may assume that everything left unparsed in an $\\texttt{hm\\_edge}$/$\\texttt{hme\\_leaf}$ cell after deserializing its $\\texttt{label}$ is a value of type $X$. This greatly simplifies the creation of dictionary manipulation primitives, because in most cases they turn out not to need any information about $X$ at all.\n\n### 3.3.10. Basic dictionary operations\n\nLet us present a classification of basic operations with dictionaries (i.e., values $D$ of type *HashmapE* $n$ $X$):\n\n- $\\text{Get}(D,k)$ — Given $D$:*HashmapE*$(n,X)$ and a key $k:n\\cdot\\texttt{bit}$, returns the corresponding value $D[k]:X^?$ kept in $D$.\n\n- $\\text{Set}(D,k,x)$ — Given $D$:*HashmapE*$(n,X)$, a key $k:n\\cdot\\texttt{bit}$, and a value $x:X$, sets $D'[k]$ to $x$ in a [copy](#2-3-4-transparency-of-the-implementation%3A-stack-values-are-“values”%2C-not-“references”) $D'$ of $D$, and returns the resulting dictionary $D'$.\n\n- $\\text{Add}(D,k,x)$ — Similar to $\\text{Set}$, but adds the key-value pair $(k,x)$ to $D$ only if key $k$ is absent in $D$.\n\n- $\\text{Replace}(D,k,x)$ — Similar to $\\text{Set}$, but changes $D'[k]$ to $x$ only if key $k$ is already present in $D$.\n\n- $\\text{GetSet}$, $\\text{GetAdd}$, $\\text{GetReplace}$ — Similar to $\\text{Set}$, $\\text{Add}$, and $\\text{Replace}$, respectively, but returns the old value of $D[k]$ as well.\n\n- $\\text{Delete}(D,k)$ — Deletes key $k$ from dictionary $D$, and returns the resulting dictionary $D'$.\n\n- $\\text{GetMin}(D)$, $\\text{GetMax}(D)$ — Gets the minimal or maximal key $k$ from dictionary $D$, along with the associated value $x:X$.\n\n- $\\text{RemoveMin}(D)$, $\\text{RemoveMax}(D)$ — Similar to $\\text{GetMin}$ and $\\text{GetMax}$, but also removes the key in question from dictionary $D$, and returns the modified dictionary $D'$. May be used to iterate over all elements of $D$, effectively using (a copy of) $D$ itself as an iterator.\n\n- $\\text{GetNext}(D,k)$ — Computes the minimal key $k'>k$ (or $k'\\geq k$ in a variant) and returns it along with the corresponding value $x':X$. May be used to iterate over all elements of $D$.\n\n- $\\text{GetPrev}(D,k)$ — Computes the maximal key $k'<k$ (or $k'\\leq k$ in a variant) and returns it along with the corresponding value $x':X$.\n\n- $\\text{Empty}(n)$ — Creates an empty dictionary $D$:*HashmapE*$(n,X)$.\n\n- $\\text{IsEmpty}(D)$ — Checks whether a dictionary is empty.\n\n- $\\text{Create}(n,\\{(k_i,x_i)\\})$ — Given $n$, creates a dictionary from a list $(k_i,x_i)$ of key-value pairs passed in stack.\n\n- $\\text{GetSubdict}(D,l,k_0)$ — Given $D$:*HashmapE*$(n,X)$ and some $l$-bit string $k_0:l\\cdot\\texttt{bit}$ for $0\\leq l\\leq n$, returns subdictionary $D'=D/k_0$ of $D$, consisting of keys beginning with $k_0$. The result $D'$ may be of either type *HashmapE*$(n,X)$ or type *HashmapE*$(n-l,X)$.\n\n- $\\text{ReplaceSubdict}(D,l,k_0,D')$ — Given $D$:*HashmapE*$(n,X)$, $0\\leq l\\leq n$, $k_0:l\\cdot\\texttt{bit}$, and $D'$:*HashmapE*$(n-l,X)$, replaces with $D'$ the subdictionary $D/k_0$ of $D$ consisting of keys beginning with $k_0$, and returns the resulting dictionary $D''$:*HashmapE*$(n,X)$. Some variants of $\\text{ReplaceSubdict}$ may also return the old value of the subdictionary $D/k_0$ in question.\n\n- $\\text{DeleteSubdict}(D,l,k_0)$ — Equivalent to $\\text{ReplaceSubdict}$ with $D'$ being an empty dictionary.\n\n- $\\text{Split}(D)$ — Given $D$:*HashmapE*$(n,X)$, returns $D_0:=D/0$ and $D_1:=D/1$:*HashmapE*$(n-1,X)$, the two subdictionaries of $D$ consisting of all keys beginning with $0$ and $1$, respectively.\n\n- $\\text{Merge}(D_0,D_1)$ — Given $D_0$ and $D_1$:*HashmapE*$(n-1,X)$, computes $D$:*HashmapE*$(n,X)$, such that $D/0=D_0$ and $D/1=D_1$.\n\n- $\\text{ForEach}(D,f)$ — Executes a function $f$ with two arguments $k$ and $x$, with $(k,x)$ running over all key-value pairs of a dictionary $D$ in lexicographical order.<a id=\"ref-fn18\"></a><sup>[18](#fn18)</sup>\n\n- $\\text{ForEachRev}(D,f)$ — Similar to $\\text{ForEach}$, but processes all key-value pairs in reverse order.\n\n- $\\text{TreeReduce}(D,o,f,g)$ — Given $D$:*HashmapE*$(n,X)$, a value $o:X$, and two functions $f:X\\to Y$ and $g:Y\\times Y\\to Y$, performs a \"tree reduction\" of $D$ by first applying $f$ to all the leaves, and then using $g$ to compute the value corresponding to a fork starting from the values assigned to its children.<a id=\"ref-fn19\"></a><sup>[19](#fn19)</sup>\n\n### 3.3.11. Taxonomy of dictionary primitives\n\nThe [dictionary primitives](#a-10-dictionary-manipulation-primitives), can be classified according to the following categories:\n\n- Which [dictionary operation](#3-3-10-basic-dictionary-operations) do they perform?\n- Are they specialized for the case $X = \\text{\\textasciicircum}Y$ If so, do they represent values of type $Y$ by *Cell*s or by *Slice*s? (Generic versions always represent values of type $X$ as *Slice*s.)\n- Are the dictionaries themselves passed and returned as *Cell*s or as *Slice*s? (Most primitives represent dictionaries as *Slice*s.)\n- Is the key length $n$ fixed inside the primitive, or is it passed in the stack?\n- Are the keys represented by *Slice*s, or by signed or unsigned *Integer*s?\n\nIn addition, TVM includes special serialization/deserialization primitives, such as $\\texttt{STDICT}$, $\\texttt{LDDICT}$, and $\\texttt{PLDDICT}$. They can be used to extract a dictionary from a serialization of an encompassing object, or to insert a dictionary into such a serialization.\n\n---\n\n## 3.4   Hashmaps with variable-length keys\n\nTVM provides some support for [dictionaries, or hashmaps](#3-3-hashmaps%2C-or-dictionaries), with variable-length keys, in addition to its support for dictionaries with fixed-length keys.\n\n### 3.4.1. Serialization of dictionaries with variable-length keys\n\nThe [serialization](#3-3-3-serialization-of-hashmaps) of a *VarHashmap* into a tree of cells (or, more generally, into a *Slice*) is defined by a TL-B scheme:\n\n```\nvhm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l n) \n           {n = (~m) + l} node:(VarHashmapNode m X) \n           = VarHashmap n X;\nvhmn_leaf$00 {n:#} {X:Type} value:X = VarHashmapNode n X;\nvhmn_fork$01 {n:#} {X:Type} left:^(VarHashmap n X) \n             right:^(VarHashmap n X) value:(Maybe X) \n             = VarHashmapNode (n + 1) X;\nvhmn_cont$1 {n:#} {X:Type} branch:bit child:^(VarHashmap n X) \n            value:X = VarHashmapNode (n + 1) X;\n\nnothing$0 {X:Type} = Maybe X;\njust$1 {X:Type} value:X = Maybe X;\n\nvhme_empty$0 {n:#} {X:Type} = VarHashmapE n X;\nvhme_root$1 {n:#} {X:Type} root:^(VarHashmap n X) \n            = VarHashmapE n X;\n```\n\n### 3.4.2. Serialization of prefix codes\n\nOne special case of a dictionary with variable-length keys is that of a *prefix code*, where the keys cannot be prefixes of each other. Values in such dictionaries may occur only in the leaves of a Patricia tree.\n\nThe serialization of a prefix code is defined by the following TL-B scheme:\n\n```\nphm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l n) \n           {n = (~m) + l} node:(PfxHashmapNode m X) \n           = PfxHashmap n X;\n\nphmn_leaf$0 {n:#} {X:Type} value:X = PfxHashmapNode n X;\nphmn_fork$1 {n:#} {X:Type} left:^(PfxHashmap n X) \n            right:^(PfxHashmap n X) = PfxHashmapNode (n + 1) X;\n\nphme_empty$0 {n:#} {X:Type} = PfxHashmapE n X;\nphme_root$1 {n:#} {X:Type} root:^(PfxHashmap n X) \n            = PfxHashmapE n X;\n```\n\n---\n\n# 4    Control flow, continuations, and exceptions\n\nThis chapter describes *continuations*, which may represent execution tokens and exception handlers in TVM. Continuations are deeply involved with the control flow of a TVM program; in particular, subroutine calls and conditional and iterated execution are implemented in TVM using special primitives that accept one or more continuations as their arguments.\n\nWe conclude this chapter with a discussion of the problem of recursion and of families of mutually recursive functions, exacerbated by the fact that cyclic references are not allowed in TVM data structures (including TVM code).\n\n## 4.1   Continuations and subroutines\n\nRecall that [Continuation values](#1-1-3-preliminary-list-of-value-types) represent \"execution tokens\" that can be executed later—for example, by $\\texttt{EXECUTE}$=$\\texttt{CALLX}$ (\"execute\" or \"call indirect\") or $\\texttt{JMPX}$ (\"jump indirect\") primitives. As such, the continuations are heavily used by control flow primitives, enabling subroutine calls, conditional expressions, loops, and so on.\n\n### 4.1.1. Ordinary continuations\n\nThe most common kind of continuations are the *ordinary continuations*, containing the following data:\n\n- A *Slice* $\\texttt{code}$ ([1.1.3](#1-1-3-preliminary-list-of-value-types) and [3.2.2](#3-2-2-builder-and-slice-values)), containing (the remainder of) the TVM code to be executed.\n- A (possibly empty) *Stack* $\\texttt{stack}$, containing the original contents of the stack for the code to be executed.\n- A (possibly empty) list $\\texttt{save}$ of pairs $(\\texttt{c}(i),v_i)$ (also called \"savelist\"), containing the values of control registers to be restored before the execution of the code.\n- A 16-bit integer value $\\texttt{cp}$, selecting the TVM codepage used to interpret the TVM code from $\\texttt{code}$.\n- An optional non-negative integer $\\texttt{nargs}$, indicating the number of arguments expected by the continuation.\n\n### 4.1.2. Simple ordinary continuations\n\nIn most cases, the ordinary continuations are the simplest ones, having empty $\\texttt{stack}$ and $\\texttt{save}$. They consist essentially of a reference $\\texttt{code}$ to (the remainder of) the code to be executed, and of the codepage $\\texttt{cp}$ to be used while decoding the instructions from this code.\n\n### 4.1.3. Current continuation cc\n\nThe \"current continuation\" $\\texttt{cc}$ is an important part of the total state of TVM, representing the code being executed right now. In particular, what we call [the current stack](#1-1-tvm-is-a-stack-machine) (or simply \"the stack\") when discussing all other primitives is in fact the stack of the current continuation. All other components of the total state of TVM may be also thought of as parts of the current continuation $\\texttt{cc}$; however, they may be extracted from the current continuation and kept separately as part of the total state for performance reasons. This is why we describe the stack, the control registers, and the codepage as separate parts of the [TVM state](#1-4-total-state-of-tvm-scccg).\n\n### 4.1.4. Normal work of TVM, or the main loop\n\nTVM usually performs the following operations:\n\nIf the current continuation $\\texttt{cc}$ is an ordinary one, it decodes the first instruction from the *Slice* $\\texttt{code}$, similarly to the way other cells are deserialized by TVM $\\texttt{LD*}$ primitives ([3.2](#3-2-data-manipulation-instructions-and-cells) and [3.2.11](#3-2-11-taxonomy-of-cell-deserialisation-primitives)): it decodes the opcode first, and then the parameters of the instruction (e.g., 4-bit fields indicating \"stack registers\" involved for stack manipulation primitives, or constant values for \"push constant\" or \"literal\" primitives). The remainder of the *Slice* is then put into the $\\texttt{code}$ of the new $\\texttt{cc}$, and the decoded operation is executed on the current stack. This entire process is repeated until there are no operations left in $\\texttt{cc.code}$.\n\nIf the $\\texttt{code}$ is empty (i.e., contains no bits of data and no references), or if a (rarely needed) explicit subroutine return ($\\texttt{RET}$) instruction is encountered, the current continuation is discarded, and the \"return continuation\" from control register $\\texttt{c0}$ is [loaded](#4-1-6-switching-to-another-continuation:-and) into $\\texttt{cc}$ instead.<a id=\"ref-fn20\"></a><sup>[20](#fn20)</sup> Then the execution continues by parsing operations from the new current continuation.\n\n### 4.1.5. Extraordinary continuations\n\nIn addition to the [ordinary continuations](#4-1-1-ordinary-continuations), TVM includes some *extraordinary continuations*, representing certain less common states. Examples of extraordinary continuations include:\n\n- The continuation $\\texttt{ec\\_quit}$ with its parameter set to zero, which represents the end of the work of TVM. This continuation is the original value of $\\texttt{c0}$ when TVM begins executing the code of a smart contract.\n- The continuation $\\texttt{ec\\_until}$, which contains references to two other continuations (ordinary or not) representing the body of the loop being executed and the code to be executed after the loop.\n\nExecution of an extraordinary continuation by TVM depends on its specific class, and [differs](#4-1-4-normal-work-of-tvm,-or-the-main-loop) from the operations for ordinary continuations.<a id=\"ref-fn21\"></a><sup>[21](#fn21)</sup>\n\n### 4.1.6. Switching to another continuation: $\\texttt{JMP}$ and $\\texttt{RET}$\n\nThe process of switching to another continuation $c$ may be performed by such instructions as $\\texttt{JMPX}$ (which takes $c$ from the stack) or $\\texttt{RET}$ (which uses $\\texttt{c0}$ as $c$). This process is slightly more complex than simply setting the value of $\\texttt{cc}$ to $c$: before doing this, either all values or the top $n$ values in the current stack are moved to the stack of the continuation $c$, and only then is the remainder of the current stack discarded.\n\nIf all values need to be moved (the most common case), and if the continuation $c$ has an empty stack (also the most common case; notice that extraordinary continuations are assumed to have an empty stack), then the new stack of $c$ equals the stack of the current continuation, so we can simply transfer the current stack in its entirety to $c$. (If we keep the current stack as a separate part of the total state of TVM, we have to do nothing at all.)\n\n### 4.1.7. Determining the number $n$ of arguments passed to the next continuation $c$\n\nBy default, $n$ equals the depth of the current stack. However, if $c$ has an explicit value of $\\texttt{nargs}$ (number of arguments to be provided), then $n$ is computed as $n'$, equal to $c$.$\\texttt{nargs}$ minus the current depth of $c$'s stack.\n\nFurthermore, there are special forms of $\\texttt{JMPX}$ and $\\texttt{RET}$ that provide an explicit value $n''$, the number of parameters from the current stack to be passed to continuation $c$. If $n''$ is provided, it must be less than or equal to the depth of the current stack, or else a stack underflow exception occurs. If both $n'$ and $n''$ are provided, we must have $n'\\leq n''$, in which case $n=n'$ is used. If $n''$ is provided and $n'$ is not, then $n=n''$ is used.\n\nOne could also imagine that the default value of $n''$ equals the depth of the original stack, and that $n''$ values are always removed from the top of the original stack even if only $n'$ of them are actually moved to the stack of the next continuation $c$. Even though the remainder of the current stack is discarded afterwards, this description will become useful later.\n\n### 4.1.8. Restoring control registers from the new continuation $c$\n\nAfter the new stack is computed, the values of control registers present in $c$.$\\texttt{save}$ are restored accordingly, and the current codepage $\\texttt{cp}$ is also set to $c$.$\\texttt{cp}$. Only then does TVM set $\\texttt{cc}$ equal to the new $c$ and begin its execution.<a id=\"ref-fn22\"></a><sup>[22](#fn22)</sup>\n\n### 4.1.9. Subroutine calls: $\\texttt{CALLX}$ or $\\texttt{EXECUTE}$ primitives\n\nThe execution of continuations as subroutines is slightly more complicated than switching to continuations.\n\nConsider the $\\texttt{CALLX}$ or $\\texttt{EXECUTE}$ primitive, which takes a continuation $c$ from the (current) stack and executes it as a subroutine.\n\nApart from doing the stack manipulations described in [4.1.6](#4-1-6-switching-to-another-continuation:-and) and [4.1.7](#4-1-7-determining-the-number-of-arguments-passed-to-the-next-continuation) and setting the new [control registers](#4-1-8-restoring-control-registers-from-the-new-continuation), these primitives perform several additional steps:\n\n1. After the top $n''$ values are [removed](#4-1-7-determining-the-number-of-arguments-passed-to-the-next-continuation) from the current stack, the (usually empty) remainder is not discarded, but instead is stored in the (old) current continuation $\\texttt{cc}$.  \n\n2. The old value of the special register $\\texttt{c0}$ is saved into the (previously empty) savelist $\\texttt{cc.save}$.\n\n3. The continuation $\\texttt{cc}$ thus modified is not discarded, but instead is set as the new $\\texttt{c0}$, which performs the role of \"next continuation\" or \"return continuation\" for the subroutine being called.\n\n4. After that, the switching to $c$ continues as before. In particular, some control registers are restored from $c$.$\\texttt{save}$, potentially overwriting the value of $\\texttt{c0}$ set in the previous step. (Therefore, a good optimization would be to check that $\\texttt{c0}$ is present in $c$.$\\texttt{save}$ from the very beginning, and skip the three previous steps as useless in this case.)\n\nIn this way, the called subroutine can return control to the caller by switching the current continuation to the return continuation saved in $\\texttt{c0}$. Nested subroutine calls work correctly because the previous value of $\\texttt{c0}$ ends up saved into the new $\\texttt{c0}$'s control register savelist $\\texttt{c0.save}$, from which it is restored later.\n\n### 4.1.10. Determining the number of arguments passed to and/or return values accepted from a subroutine\n\nSimilarly to $\\texttt{JMPX}$ and $\\texttt{RET}$, $\\texttt{CALLX}$ also has special (rarely used) forms, which allow us to explicitly specify the number $n''$ of arguments passed from the current stack to the called subroutine (by default, $n''$ equals the depth of the current stack, i.e., it is passed in its entirety). Furthermore, a second number $n'''$ can be specified, used to set $\\texttt{nargs}$ of the modified $\\texttt{cc}$ continuation before storing it into the new $\\texttt{c0}$; the new $\\texttt{nargs}$ equals the depth of the old stack minus $n''$ plus $n'''$. This means that the caller is willing to pass exactly $n''$ arguments to the called subroutine, and is willing to accept exactly $n'''$ results in their stead.\n\nSuch forms of $\\texttt{CALLX}$ and $\\texttt{RET}$ are mostly intended for library functions that accept functional arguments and want to invoke them safely. Another application is related to the \"virtualization support\" of TVM, which enables TVM code to run other TVM code inside a \"virtual TVM machine\". Such virtualization techniques might be useful for implementing sophisticated [payment channels](/foundations/whitepapers/ton#5-ton-payments) in the TON Blockchain.\n\n### 4.1.11. $\\texttt{CALLCC}$: call with current continuation\n\nNotice that TVM supports a form of the \"call with current continuation\" primitive. Namely, primitive $\\texttt{CALLCC}$ is similar to $\\texttt{CALLX}$ or $\\texttt{JMPX}$ in that it takes a continuation $c$ from the stack and switches to it; however, $\\texttt{CALLCC}$ does not discard the previous current continuation $c'$ (as $\\texttt{JMPX}$ does) and does not write $c'$ to $\\texttt{c0}$ (as $\\texttt{CALLX}$ does), but rather pushes $c'$ into the (new) stack as an extra argument to $c$. The primitive $\\texttt{JMPXDATA}$ does a similar thing, but pushes only the (remainder of the) code of the previous current continuation as a *Slice*.\n\n## 4.2   Control flow primitives: conditional and iterated execution\n\n### 4.2.1. Conditional execution: $\\texttt{IF}$, $\\texttt{IFNOT}$, $\\texttt{IFELSE}$\n\nAn important modification of $\\texttt{EXECUTE}$ (or $\\texttt{CALLX}$) consists in its conditional forms. For example, $\\texttt{IF}$ accepts an integer $x$ and a continuation $c$, and executes $c$ (in the same way as $\\texttt{EXECUTE}$ would do it) only if $x$ is non-zero; otherwise both values are simply discarded from the stack. Similarly, $\\texttt{IFNOT}$ accepts $x$ and $c$, but executes $c$ only if $x=0$. Finally, $\\texttt{IFELSE}$ accepts $x$, $c$, and $c'$, removes these values from the stack, and executes $c$ if $x\\neq0$ or $c'$ if $x=0$.\n\n### 4.2.2. Iterated execution and loops\n\nMore sophisticated modifications of $\\texttt{EXECUTE}$ include:\n\n- $\\texttt{REPEAT}$ — Takes an integer $n$ and a continuation $c$, and executes $c$ $n$ times.<a id=\"ref-fn23\"></a><sup>[23](#fn23)</sup>\n- $\\texttt{WHILE}$ — Takes $c'$ and $c''$, executes $c'$, and then takes the top value $x$ from the stack. If $x$ is non-zero, it executes $c''$ and then begins a new loop by executing $c'$ again; if $x$ is zero, it stops.\n- $\\texttt{UNTIL}$ — Takes $c$, executes it, and then takes the top integer $x$ from the stack. If $x$ is zero, a new iteration begins; if $x$ is non-zero, the previously executed code is resumed.\n\n### 4.2.3. Constant, or literal, continuations\n\nWe see that we can create arbitrarily complex conditional expressions and loops in the TVM code, provided we have a means to push constant continuations into the stack. In fact, TVM includes special versions of \"literal\" or \"constant\" primitives that cut the next $n$ bytes or bits from the remainder of the current code $\\texttt{cc.code}$ into a cell slice, and then push it into the stack not as a *Slice* (as a $\\texttt{PUSHSLICE}$ does) but as a simple ordinary *Continuation* (which has only $\\texttt{code}$ and $\\texttt{cp}$).\n\nThe simplest of these primitives is $\\texttt{PUSHCONT}$, which has an immediate argument $n$ describing the number of subsequent bytes (in a byte-oriented version of TVM) or bits to be converted into a simple continuation. Another primitive is $\\texttt{PUSHREFCONT}$, which removes the first cell reference from the current continuation $\\texttt{cc.code}$, converts the cell referred to into a cell slice, and finally converts the cell slice into a simple continuation.\n\n### 4.2.4. Constant continuations combined with conditional or iterated execution primitives\n\nBecause constant continuations are very often used as arguments to conditional or iterated execution primitives, combined versions of these primitives (e.g., $\\texttt{IFCONT}$ or $\\texttt{UNTILREFCONT}$) may be defined in a future revision of TVM, which combine a $\\texttt{PUSHCONT}$ or $\\texttt{PUSHREFCONT}$ with another primitive. If one inspects the resulting code, $\\texttt{IFCONT}$ looks very much like the more customary \"conditional-branch-forward\" instruction.\n\n## 4.3  Operations with continuations\n\n### 4.3.1  Continuations are opaque\n\nNotice that all continuations are *opaque*, at least in the current version of TVM, meaning that there is no way to modify a continuation or inspect its internal data. Almost the only use of a continuation is to supply it to a control flow primitive.\n\nWhile there are some arguments in favor of including support for non-opaque continuations in TVM (along with opaque continuations, which are required for virtualization), the current revision offers no such support.\n\n### 4.3.2. Allowed operations with continuations\n\nHowever, some operations with opaque continuations are still possible, mostly because they are equivalent to operations of the kind \"create a new continuation, which will do something special, and then invoke the original continuation\". Allowed operations with continuations include:\n\n- Push one or several values into the stack of a continuation $c$ (thus creating a partial application of a function, or a closure).\n- Set the saved value of a control register $\\texttt{c}(i)$ inside the savelist $c$.$\\texttt{save}$ of a continuation $c$. If there is already a value for the control register in question, this operation silently does nothing.\n\n### 4.3.3. Example: operations with control registers\n\nTVM has some primitives to set and inspect the values of control registers. The most important of them are $\\texttt{PUSH c}(i)$ (pushes the current value of $\\texttt{c}(i)$ into the stack) and $\\texttt{POP c}(i)$ (sets the value of $\\texttt{c}(i)$ from the stack, if the supplied value is of the correct type). However, there is also a modified version of the latter instruction, called $\\texttt{POPSAVE c}(i)$, which saves the old value of $\\texttt{c}(i)$ (for $i>0$) into the [continuation](#4-3-2-allowed-operations-with-continuations) at $\\texttt{c0}$ before setting the new value.\n\n### 4.3.4. Example: setting the number of arguments to a function in its code\n\nThe primitive $\\texttt{LEAVEARGS}$ $n$ demonstrates another application of continuations in an operation: it leaves only the top $n$ values of the current stack, and moves the remainder to the stack of the continuation in $\\texttt{c0}$. This primitive enables a called function to \"return\" unneeded arguments to its caller's stack, which is useful in some situations (e.g., those related to exception handling).\n\n### 4.3.5. Boolean circuits\n\nA continuation $c$ may be thought of as a piece of code with two optional exit points kept in the savelist of $c$: the principal exit point given by $c$.$\\texttt{c0}$:=$c$.$\\texttt{save}$($\\texttt{c0}$), and the auxiliary exit point given by $c$.$\\texttt{c1}$:=$c$.$\\texttt{save}$($\\texttt{c1}$). If executed, a continuation performs whatever action it was created for, and then (usually) transfers control to the principal exit point, or, on some occasions, to the auxiliary exit point. We sometimes say that a continuation $c$ with both exit points $c$.$\\texttt{c0}$ and $c$.$\\texttt{c1}$ defined is a *two-exit continuation*, or a *boolean circuit*, especially if the choice of the exit point depends on some internally-checked condition.\n\n### 4.3.6. Composition of continuations\n\nOne can *compose* two continuations $c$ and $c'$ simply by setting $c$.$\\texttt{c0}$ or $c$.$\\texttt{c1}$ to $c'$. This creates a new continuation denoted by $c\\circ_0c'$ or $c\\circ_1c'$, which differs from $c$ in its savelist. (Recall that if the savelist of $c$ already has an entry corresponding to the control register in question, such an operation silently [does nothing](#4-3-2-allowed-operations-with-continuations).\n\nBy composing continuations, one can build chains or other graphs, possibly with loops, representing the control flow. In fact, the resulting graph resembles a flow chart, with the boolean circuits corresponding to the \"condition nodes\" (containing code that will transfer control either to $\\texttt{c0}$ or to $\\texttt{c1}$ depending on some condition), and the one-exit continuations corresponding to the \"action nodes\".\n\n### 4.3.7. Basic continuation composition primitives\n\nTwo basic primitives for composing continuations are $\\texttt{COMPOS}$ (also known as $\\texttt{SETCONT c0}$ and $\\texttt{BOOLAND}$) and $\\texttt{COMPOSALT}$ (also known as $\\texttt{SETCONT c1}$ and $\\texttt{BOOLOR}$), which take $c$ and $c'$ from the stack, set $c$.$\\texttt{c0}$ or $c$.$\\texttt{c1}$ to $c'$, and return the resulting continuation $c''=c\\circ_0c'$ or $c\\circ_1c'$. All other continuation composition operations can be expressed in terms of these two primitives.\n\n### 4.3.8. Advanced continuation composition primitives\n\nHowever, TVM can compose continuations not only taken from stack, but also taken from $\\texttt{c0}$ or $\\texttt{c1}$, or from the current continuation $\\texttt{cc}$; likewise, the result may be pushed into the stack, stored into either $\\texttt{c0}$ or $\\texttt{c1}$, or used as the new current continuation (i.e., the control may be transferred to it). Furthermore, TVM can define conditional composition primitives, performing some of the above actions only if an integer value taken from the stack is non-zero.\n\nFor instance, $\\texttt{EXECUTE}$ can be described as $\\texttt{cc}\\leftarrow c\\circ_0\\texttt{cc}$, with continuation $c$ taken from the original stack. Similarly, $\\texttt{JMPX}$ is $\\texttt{cc}\\leftarrow c$, and $\\texttt{RET}$ (also known as $\\texttt{RETTRUE}$ in a boolean circuit context) is $\\texttt{cc}\\leftarrow\\texttt{c0}$. Other interesting primitives include $\\texttt{THENRET}$ ($c'\\leftarrow c\\circ_0\\texttt{c0}$) and $\\texttt{ATEXIT}$ ($\\texttt{c0}\\leftarrow c\\circ_0\\texttt{c0}$).\n\nFinally, some \"experimental\" primitives also involve $\\texttt{c1}$ and $\\circ_1$. For example:\n\n- $\\texttt{RETALT}$ or $\\texttt{RETFALSE}$ does $\\texttt{cc}\\leftarrow\\texttt{c1}$.\n- Conditional versions of $\\texttt{RET}$ and $\\texttt{RETALT}$ may also be useful: $\\texttt{RETBOOL}$ takes an integer $x$ from the stack, and performs $\\texttt{RETTRUE}$ if $x\\neq0$, $\\texttt{RETFALSE}$ otherwise.\n- $\\texttt{INVERT}$ does $\\texttt{c0}\\leftrightarrow\\texttt{c1}$; if the two continuations in $\\texttt{c0}$ and $\\texttt{c1}$ represent the two branches we should select depending on some boolean expression, $\\texttt{INVERT}$ negates this expression on the outer level.\n- $\\texttt{INVERTCONT}$ does $c$.$\\texttt{c0}\\leftrightarrow c$.$\\texttt{c1}$ to a continuation $c$ taken from the stack.\n- Variants of $\\texttt{ATEXIT}$ include $\\texttt{ATEXITALT}$ ($\\texttt{c1}\\leftarrow c\\circ_1\\texttt{c1}$) and $\\texttt{SETEXITALT}$ ($\\texttt{c1}\\leftarrow (c\\circ_0\\texttt{c0})\\circ_1\\texttt{c1}$).\n- $\\texttt{BOOLEVAL}$ takes a continuation $c$ from the stack and does $\\texttt{cc}\\leftarrow \\bigl((c\\circ_0(\\texttt{PUSH}\\,-1))\\circ_1(\\texttt{PUSH}\\,0)\\bigr)\\circ_0\\texttt{cc}$. If $c$ represents a boolean circuit, the net effect is to evaluate it and push either $-1$ or $0$ into the stack before continuing.\n\n\n## 4.4  Continuations as objects\n\n### 4.4.1. Representing objects using continuations\n\nObject-oriented programming in Smalltalk (or Objective C) style may be implemented with the aid of continuations. For this, an object is represented by a special continuation $o$. If it has any data fields, they can be kept in the stack of $o$, making $o$ a partial application (i.e., a continuation with a non-empty stack).\n\nWhen somebody wants to invoke a method $m$ of $o$ with arguments $x_1$, $x_2$, $\\ldots$, $x_n$, she pushes the arguments into the stack, then pushes a magic number corresponding to the method $m$, and then executes $o$ passing $n+1$ [arguments](#4-1-10-determining-the-number-of-arguments-passed-to-and%2For-return-values-accepted-from-a-subroutine). Then $o$ uses the top-of-stack integer $m$ to select the branch with the required method, and executes it. If $o$ needs to modify its state, it simply computes a new continuation $o'$ of the same sort (perhaps with the same code as $o$, but with a different initial stack). The new continuation $o'$ is returned to the caller along with whatever other return values need to be returned.\n\n### 4.4.2. Serializable objects\n\nAnother way of representing Smalltalk-style objects as continuations, or even as trees of cells, consists in using the $\\texttt{JMPREFDATA}$ primitive (a [variant](#4-1-11-%3A-call-with-current-continuation) of $\\texttt{JMPXDATA}$), which takes the first cell reference from the code of the current continuation, transforms the cell referred to into a simple ordinary continuation, and transfers control to it, first pushing the remainder of the current continuation as a *Slice* into the stack. In this way, an object might be represented by a cell $\\tilde o$ that contains $\\texttt{JMPREFDATA}$ at the beginning of its data, and the actual code of the object in the first reference (one might say that the first reference of cell $\\tilde o$ is the *class* of object $\\tilde o$). Remaining data and references of this cell will be used for storing the fields of the object.\n\nSuch objects have the advantage of being trees of cells, and not just continuations, meaning that they can be stored into the persistent storage of a TON smart contract.\n\n### 4.4.3. Unique continuations and capabilities\n\nIt might make sense (in a future revision of TVM) to mark some continuations as *unique*, meaning that they cannot be copied, even in a delayed manner, by increasing their reference counter to a value greater than one. If an opaque continuation is unique, it essentially becomes a *capability*, which can either be used by its owner exactly once or be transferred to somebody else.\n\nFor example, imagine a continuation that [represents](#4-4-1-representing-objects-using-continuations) the output stream to a printer (this is an example of a continuation used as an object). When invoked with one integer argument $n$, this continuation outputs the character with code $n$ to the printer, and returns a new continuation of the same kind reflecting the new state of the stream. Obviously, copying such a continuation and using the two copies in parallel would lead to some unintended side effects; marking it as unique would prohibit such adverse usage.\n\n## 4.5  Exception handling\n\nTVM's exception handling is quite simple and consists in a transfer of control to the continuation kept in control register $\\texttt{c2}$.\n\n### 4.5.1. Two arguments of the exception handler: exception parameter and exception number\n\nEvery exception is characterized by two arguments: the *exception number* (an *Integer*) and the *exception parameter* (any value, most often a zero *Integer*). Exception numbers 0–31 are reserved for TVM, while all other exception numbers are available for user-defined exceptions.\n\n### 4.5.2. Primitives for throwing an exception\n\nThere are several special primitives used for throwing an exception. The most general of them, $\\texttt{THROWANY}$, takes two arguments, $v$ and $0\\leq n<2^{16}$, from the stack, and throws the exception with number $n$ and value $v$. There are variants of this primitive that assume $v$ to be a zero integer, store $n$ as a literal value, and/or are conditional on an integer value taken from the stack. User-defined exceptions may use arbitrary values as $v$ (e.g., trees of cells) if needed.\n\n### 4.5.3. Exceptions generated by TVM\n\nOf course, some exceptions are generated by normal primitives. For example, an arithmetic overflow exception is generated whenever the result of an arithmetic operation does not fit into a signed 257-bit integer. In such cases, the arguments of the exception, $v$ and $n$, are determined by TVM itself.\n\n### 4.5.4. Exception handling\n\nThe exception handling itself consists in a control transfer to the exception handler—i.e., the continuation specified in control register $\\texttt{c2}$, with $v$ and $n$ supplied as the two arguments to this continuation, as if a $\\texttt{JMP}$ to $\\texttt{c2}$ had been requested with $n''=2$ arguments ([4.1.7](#4-1-7-determining-the-number-of-arguments-passed-to-the-next-continuation) and [4.1.6](#4-1-6-switching-to-another-continuation:-and)). As a consequence, $v$ and $n$ end up in the top of the stack of the exception handler. The remainder of the old stack is discarded.\n\nNotice that if the continuation in $\\texttt{c2}$ has a value for $\\texttt{c2}$ in its savelist, it will be used to set up the new value of $\\texttt{c2}$ before executing the exception handler. In particular, if the exception handler invokes $\\texttt{THROWANY}$, it will re-throw the original exception with the restored value of $\\texttt{c2}$. This trick enables the exception handler to handle only some exceptions, and pass the rest to an outer exception handler.\n\n### 4.5.5. Default exception handler\n\nWhen an instance of TVM is created, $\\texttt{c2}$ contains a reference to the \"default exception handler continuation\", which is an $\\texttt{ec\\_fatal}$ [extraordinary continuation](#4-1-5-extraordinary-continuations). Its execution leads to the termination of the execution of TVM, with the arguments $v$ and $n$ of the exception returned to the outside caller. In the context of the TON Blockchain, $n$ will be stored as a part of the transaction's result.\n\n### 4.5.6. $\\texttt{TRY}$ primitive\n\nA $\\texttt{TRY}$ primitive can be used to implement C++- like exception handling. This primitive accepts two continuations, $c$ and $c'$. It stores the old value of $\\texttt{c2}$ into the savelist of $c'$, sets $\\texttt{c2}$ to $c'$, and executes $c$ just as $\\texttt{EXECUTE}$ would, but additionally saving the old value of $\\texttt{c2}$ into the savelist of the new $\\texttt{c0}$ as well. Usually a version of the $\\texttt{TRY}$ primitive with an explicit number of arguments $n''$ passed to the continuation $c$ is used.\n\nThe net result is roughly equivalent to C$++$'s $\\texttt{try}$ \\{ $c$ \\} $\\texttt{catch(...)}$ \\{ $c'$ \\} operator.\n\n### 4.5.7. List of predefined exceptions\n\nPredefined exceptions of TVM correspond to exception numbers $n$ in the range 0–31. They include:\n\n- *Normal termination* ($n=0$) — Should never be generated, but it is useful for some tricks.\n- *Alternative termination* ($n=1$) — Again, should never be generated.\n- *Stack underflow* ($n=2$) — Not enough arguments in the stack for a primitive.\n- *Stack overflow* ($n=3$) — More values have been stored on a stack than allowed by this version of TVM.\n- *Integer overflow* ($n=4$) — Integer does not fit into $-2^{256}\\leq x<2^{256}$, or a division by zero has occurred.\n- *Range check error* ($n=5$) — Integer out of expected range.\n- *Invalid opcode* ($n=6$) — Instruction or its immediate arguments cannot be decoded.\n- *Type check error* ($n=7$) — An argument to a primitive is of incorrect value type.\n- *Cell overflow* ($n=8$) — Error in one of the serialization primitives.\n- *Cell underflow* ($n=9$) — Deserialization error.\n- *Dictionary error* ($n=10$) — Error while deserializing a dictionary object.\n- *Unknown error* ($n=11$) — Unknown error, may be thrown by user programs.\n- *Fatal error* ($n=12$) — Thrown by TVM in situations deemed impossible.\n- *Out of gas* ($n=13$) — Thrown by TVM when the remaining gas ($g_r$) becomes negative. This exception usually cannot be caught and leads to an immediate termination of TVM.\n\nMost of these exceptions have no parameter (i.e., use a zero integer instead). The order in which these exceptions are checked is outlined [below](#4-5-8-order-of-stack-underflow,-type-check,-and-range-check-exceptions).\n\n### 4.5.8. Order of stack underflow, type check, and range check exceptions\n\nAll TVM primitives first check whether the stack contains the required number of arguments, generating a stack underflow exception if this is not the case. Only then are the type tags of the arguments and their ranges (e.g., if a primitive expects an argument not only to be an *Integer*, but also to be in the range from 0 to 256) checked, starting from the value in the top of the stack (the last argument) and proceeding deeper into the stack. If an argument's type is incorrect, a type-checking exception is generated; if the type is correct, but the value does not fall into the expected range, a range check exception is generated.\n\nSome primitives accept a variable number of arguments, depending on the values of some small fixed subset of arguments located near the top of the stack. In this case, the above procedure is first run for all arguments from this small subset. Then it is repeated for the remaining arguments, once their number and types have been determined from the arguments already processed.\n\n## 4.6   Functions, recursion, and dictionaries\n\n### 4.6.1. The problem of recursion\n\nThe [conditional and iterated](#4-2-control-flow-primitives:-conditional-and-iterated-execution) execution primitives—along with the unconditional branch, call, and return [primitives](#4-1-continuations-and-subroutines)—enable one to implement more or less arbitrary code with nested loops and conditional expressions, with one notable exception: one can only create new constant continuations from parts of the current continuation. (In particular, one cannot invoke a subroutine from itself in this way.) Therefore, the code being executed—i.e., the current continuation—gradually becomes smaller and smaller.<a id=\"ref-fn24\"></a><sup>[24](#fn24)</sup>\n\n### 4.6.2. Y-combinator solution: pass a continuation as an argument to itself\n\nOne way of dealing with the problem of recursion is by passing a copy of the continuation representing the body of a recursive function as an extra argument to itself. Consider, for example, the following code for a factorial function:\n```\n71      PUSHINT 1\n9C      PUSHCONT {\n22        PUSH s2\n72        PUSHINT 2\nB9        LESS\nDC        IFRET\n59        ROTREV\n21        PUSH s1\nA8        MUL\n01        SWAP\nA5        DEC\n02        XCHG s2\n20        DUP\nD9        JMPX\n        }\n20      DUP\nD8      EXECUTE\n30      DROP\n31      NIP\n```\n\nThis roughly corresponds to defining an auxiliary function $\\mathit{body}$ with three arguments $n$, $x$, and $f$, such that $\\mathit{body}(n,x,f)$ equals $x$ if $n<2$ and $f(n-1,nx,f)$ otherwise, then invoking $\\mathit{body}(n,1,\\mathit{body})$ to compute the factorial of $n$.\n\nThe recursion is then implemented with the aid of the $\\texttt{DUP}$; $\\texttt{EXECUTE}$ construction, or $\\texttt{DUP}$; $\\texttt{JMPX}$ in the case of tail recursion. This trick is equivalent to applying $Y$-combinator to a function $\\mathit{body}$.\n\n### 4.6.3. A variant of Y-combinator solution\n\nAnother way of recursively computing the factorial, more closely following the classical recursive definition\n\n$$\n\\mathit{fact}(n):=\\begin{cases}1&\\quad\\text{if }n<2,\\\\n\\cdot\\mathit{fact}(n-1)&\\quad\\text{otherwise}\\end{cases} \\tag{5}\n$$\n\nis as follows:\n```asm\n9D      PUSHCONT {\n21        OVER\nC102      LESSINT 2\n92        PUSHCONT {\n5B          2DROP\n71          PUSHINT 1\n          }\nE0        IFJMP\n21        OVER\nA5        DEC\n01        SWAP\n20        DUP\nD8        EXECUTE\nA8        MUL\n        }\n20      DUP\nD9      JMPX\n```\n\nThis definition of the factorial function is two bytes shorter than the previous one, but it uses general recursion instead of tail recursion, so it cannot be easily transformed into a loop.\n\n### 4.6.4. Comparison: non-recursive definition of the factorial function\n\nIncidentally, a non-recursive definition of the factorial with the aid of a $\\texttt{REPEAT}$ loop is also possible, and it is much shorter than both recursive definitions:\n```asm\n71      PUSHINT 1\n01      SWAP\n20      DUP\n94      PUSHCONT {\n66        TUCK\nA8        MUL\n01        SWAP\nA5        DEC\n        }\nE4      REPEAT\n30      DROP\n```\n\n### 4.6.5. Several mutually recursive functions\n\nIf one has a collection $f_1$, $\\ldots$, $f_n$ of mutually recursive functions, one can use the same trick by passing the whole collection of continuations $\\{f_i\\}$ in the stack as an extra $n$ arguments to each of these functions. However, as $n$ grows, this becomes more and more cumbersome, since one has to reorder these extra arguments in the stack to work with the \"true\" arguments, and then push their copies into the top of the stack before any recursive call.\n\n### 4.6.6. Combining several functions into one tuple\n\nOne might also combine a collection of continuations representing functions $f_1$, $\\ldots$, $f_n$ into a \"tuple\" ${\\mathbf f}:=(f_1,\\ldots,f_n)$, and pass this tuple as one stack element ${\\mathbf f}$. For instance, when $n\\leq4$, each function can be represented by a cell $\\tilde f_i$ (along with the tree of cells rooted in this cell), and the tuple may be represented by a cell $\\tilde{\\mathbf f}$, which has references to its component cells $\\tilde f_i$. However, this would lead to the necessity of \"unpacking\" the needed component from this tuple before each recursive call.\n\n### 4.6.7. Combining several functions into a selector function\n\nAnother approach is to combine several functions $f_1$, $\\ldots$, $f_n$ into one \"selector function\" $f$, which takes an extra argument $i$, $1\\leq i\\leq n$, from the top of the stack, and invokes the appropriate function $f_i$. Stack machines such as TVM are well-suited to this approach, because they do not require the functions $f_i$ to have the same number and types of arguments. Using this approach, one would need to pass only one extra argument, $f$, to each of these functions, and push into the stack an extra argument $i$ before each recursive call to $f$ to select the correct function to be called.\n\n### 4.6.8. Using a dedicated register to keep the selector function\n\nHowever, even if we use one of the two previous approaches to combine all functions into one extra argument, passing this argument to all mutually recursive functions is still quite cumbersome and requires a lot of additional stack manipulation operations. Because this argument changes very rarely, one might use a dedicated register to keep it and transparently pass it to all functions called. This is the approach used by TVM by default.\n\n### 4.6.9. Special register $c3$ for the selector function\n\nIn fact, TVM uses a dedicated register $\\texttt{c3}$ to keep the continuation representing the current or global \"selector function\", which can be used to invoke any of a family of mutually recursive functions. [Special primitives](#a-8-7-dictionary-subroutine-calls-and-jumps) $\\texttt{CALL}$ $nn$ or $\\texttt{CALLDICT}$ $nn$ are equivalent to $\\texttt{PUSHINT}$ $nn$; $\\texttt{PUSH c3}$; $\\texttt{EXECUTE}$, and similarly $\\texttt{JMP}$ $nn$ or $\\texttt{JMPDICT}$ $nn$ are equivalent to $\\texttt{PUSHINT}$ $nn$; $\\texttt{PUSH c3}$; $\\texttt{JMPX}$. In this way a TVM program, which ultimately is a large collection of mutually recursive functions, may initialize $\\texttt{c3}$ with the correct selector function representing the family of all the functions in the program, and then use $\\texttt{CALL}$ $nn$ to invoke any of these functions by its index (sometimes also called the *selector* of a function).\n\n### 4.6.10. Initialization of $c3$\n\nA TVM program might initialize $\\texttt{c3}$ by means of a $\\texttt{POP c3}$ instruction. However, because this usually is the very first action undertaken by a program (e.g., a smart contract), TVM makes some provisions for the automatic initialization of $\\texttt{c3}$. Namely, $\\texttt{c3}$ is initialized by the code (the initial value of $\\texttt{cc}$) of the program itself, and an extra zero (or, in some cases, some other predefined number $s$) is pushed into the stack before the program's execution. This is approximately equivalent to invoking $\\texttt{JMPDICT 0}$ (or $\\texttt{JMPDICT}$ $s$) at the very beginning of a program—i.e., the function with index zero is effectively the `main()` function for the program.\n\n### 4.6.11. Creating selector functions and $\\texttt{switch}$ statements\n\nTVM makes special provisions for simple and concise implementation of selector functions (which usually constitute the top level of a TVM program) or, more generally, arbitrary `switch` or `case` statements (which are also useful in TVM programs). The most important [primitives](#a-8-2-conditional-control-flow-primitives) included for this purpose are $\\texttt{IFBITJMP}$, $\\texttt{IFNBITJMP}$, $\\texttt{IFBITJMPREF}$, and $\\texttt{IFNBITJMPREF}$. They effectively enable one to combine subroutines, kept either in separate cells or as subslices of certain cells, into a binary decision tree with decisions made according to the indicated bits of the integer passed in the top of the stack.\n\nAnother instruction, useful for the implementation of [sum-product](#a-7-2-cell-deserialization-primitives) types, is $\\texttt{PLDUZ}$. This instruction preloads the first several bits of a *Slice* into an *Integer*, which can later be inspected by $\\texttt{IFBITJMP}$ and other similar instructions.\n\n### 4.6.12. Alternative: using a hashmap to select the correct function\n\nYet another alternative is to use a [Hashmap](#3-3-hashmaps%2C-or-dictionaries) to hold the \"collection\" or \"dictionary\" of the code of all functions in a program, and use the [hashmap lookup primitives](#a-10-dictionary-manipulation-primitives) to select the code of the required function, which can then be $\\texttt{BLESS}$ed into a [continuation](#a-8-5-creating-simple-continuations-and-closures) and executed. Special combined \"lookup, bless, and execute\" primitives, such as $\\texttt{DICTIGETJMP}$ and $\\texttt{DICTIGETEXEC}$, are also [available](#a-10-11-special-dictionary-and-prefix-code-dictionary-operations%2C-and-constant-dictionaries). This approach may be more efficient for larger programs and `switch` statements.\n\n---\n\n# 5. Codepages and instruction encoding\n\nThis chapter describes the codepage mechanism, which allows TVM to be flexible and extendable while preserving backward compatibility with respect to previously generated code.\n\nWe also discuss some general considerations about instruction encodings (applicable to arbitrary machine code, not just TVM), as well as the implications of these considerations for TVM and the choices made while designing TVM's (experimental) codepage zero. The instruction encodings themselves are presented later in [Appendix A](#a-instructions-and-opcodes).\n\n## 5.1   Codepages and interoperability of different TVM versions\n\nThe *codepages* are an essential mechanism of backward compatibility and of future extensions to TVM. They enable transparent execution of code written for different revisions of TVM, with transparent interaction between instances of such code. The mechanism of the codepages, however, is general and powerful enough to enable some other originally unintended applications.\n\n### 5.1.1. Codepages in continuations\n\nEvery [ordinary continuation](#4-1-1-ordinary-continuations) contains a 16-bit *codepage* field $\\texttt{cp}$, which determines the codepage that will be used to execute its code. If a [continuation](#4-2-3-constant%2C-or-literal%2C-continuations) is created by a $\\texttt{PUSHCONT}$ or similar primitive, it usually inherits the current codepage (i.e., the codepage of $\\texttt{cc}$).<a id=\"ref-fn25\"></a><sup>[25](#fn25)</sup>\n\n### 5.1.2. Current codepage\n\nThe [current codepage](#1-4-total-state-of-tvm-scccg) $\\texttt{cp}$ is the codepage of the current continuation $\\texttt{cc}$. It determines the way the next instruction will be decoded from $\\texttt{cc.code}$, the remainder of the current continuation's code. Once the instruction has been decoded and executed, it determines the next value of the current codepage. In most cases, the current codepage is left unchanged.\n\nOn the other hand, all primitives that switch the current continuation load the new value of $\\texttt{cp}$ from the new current continuation. In this way, all code in continuations is always interpreted exactly as it was intended to be.\n\n### 5.1.3. Different versions of TVM may use different codepages\n\nDifferent versions of TVM may use different codepages for their code. For example, the original version of TVM might use codepage zero. A newer version might use codepage one, which contains all the previously defined opcodes, along with some newly defined ones, using some of the previously unused opcode space. A subsequent version might use yet another codepage, and so on.\n\nHowever, a newer version of TVM will execute old code for codepage zero exactly as before. If the old code contained an opcode used for some new operations that were undefined in the original version of TVM, it will still generate an invalid opcode exception, because the new operations are absent in codepage zero.\n\n### 5.1.4. Changing the behavior of old operations\n\nNew codepages can also change the effects of some operations present in the old codepages while preserving their opcodes and mnemonics.\n\nFor example, imagine a future 513-bit upgrade of TVM (replacing the current 257-bit design). It might use a 513-bit *Integer* type within the same arithmetic primitives as before. However, while the opcodes and instructions in the new codepage would look exactly like the old ones, they would work differently, accepting 513-bit integer arguments and results. On the other hand, during the execution of the same code in codepage zero, the new machine would generate exceptions whenever the integers used in arithmetic and other primitives do not fit into 257 bits.<a id=\"ref-fn26\"></a><sup>[26](#fn26)</sup> In this way, the upgrade would not change the behavior of the old code.\n\n### 5.1.5. Improving instruction encoding\n\nAnother application for codepages is to change instruction encodings, reflecting improved knowledge of the actual frequencies of such instructions in the code base. In this case, the new codepage will have exactly the same instructions as the old one, but with different encodings, potentially of differing lengths. For example, one might create an experimental version of the first version of TVM, using a (prefix) bitcode instead of the original bytecode, aiming to achieve higher code density.\n\n### 5.1.6. Making instruction encoding context-dependent\n\nAnother way of using codepages to improve code density is to use several codepages with different subsets of the whole instruction set defined in each of them, or with the whole instruction set defined, but with different length encodings for the same instructions in different codepages.\n\nImagine, for instance, a \"stack manipulation\" codepage, where stack manipulation primitives have short encodings at the expense of all other operations, and a \"data processing\" codepage, where all other operations are shorter at the expense of stack manipulation operations. If stack manipulation operations tend to come one after another, we can automatically switch to \"stack manipulation\" codepage after executing any such instruction. When a data processing instruction occurs, we switch back to \"data processing\" codepage. If conditional probabilities of the class of the next instruction depending on the class of the previous instruction are considerably different from corresponding unconditional probabilities, this technique—automatically switching into stack manipulation mode to rearrange the stack with shorter instructions, then switching back—might considerably improve the code density.\n\n### 5.1.7. Using codepages for status and control flags\n\nAnother potential application of multiple codepages inside the same revision of TVM consists in switching between several codepages depending on the result of the execution of some instructions.\n\nFor example, imagine a version of TVM that uses two new codepages, 2 and 3. Most operations do not change the current codepage. However, the integer comparison operations will switch to codepage 2 if the condition is false, and to codepage 3 if it is true. Furthermore, a new operation $\\texttt{?EXECUTE}$, similar to $\\texttt{EXECUTE}$, will indeed be equivalent to $\\texttt{EXECUTE}$ in codepage 3, but will instead be a $\\texttt{DROP}$ in codepage 2. Such a trick effectively uses bit 0 of the current codepage as a status flag.\n\nAlternatively, one might create a couple of codepages—say, 4 and 5—which differ only in their cell deserialisation primitives. For instance, in codepage 4 they might work as before, while in codepage 5 they might deserialize data not from the beginning of a *Slice*, but from its end. Two new instructions—say, $\\texttt{CLD}$ and $\\texttt{STD}$—might be used for switching to codepage 4 or codepage 5. Clearly, we have now described a status flag, affecting the execution of some instructions in a certain new manner.\n\n### 5.1.8. Setting the codepage in the code itself\n\nFor convenience, we reserve some opcode in all [codepages](#a-13-codepage-primitives)—say, $\\texttt{FF}$ $n$—for the instruction $\\texttt{SETCP}$ $n$, with $n$ from 0 to 255. Then by inserting such an instruction into the very beginning of (the main function of) a program (e.g., a TON Blockchain smart contract) or a library function, we can ensure that the code will always be executed in the intended codepage.\n\n## 5.2  Instruction encoding\n\nThis section discusses the general principles of instruction encoding valid for all codepages and all versions of TVM. Later, [5.3](#5-3-instruction-encoding-in-codepage-zero) discusses the choices made for the experimental \"codepage zero\".\n\n### 5.2.1. Instructions are encoded by a binary prefix code\n\nAll complete instructions (i.e., instructions along with all their parameters, such as the names of stack registers $s(i)$ or other embedded constants) of a TVM codepage are encoded by a *binary prefix code*. This means that a (finite) binary string (i.e., a bitstring) corresponds to each complete instruction, in such a way that binary strings corresponding to different complete instructions do not coincide, and no binary string among the chosen subset is a prefix of another binary string from this subset.\n\n### 5.2.2. Determining the first instruction from a code stream\n\nAs a consequence of this encoding method, any binary string admits at most one prefix, which is an encoding of some complete instruction. In particular, the code $\\texttt{cc.code}$ of the current continuation (which is a *Slice*, and thus a bitstring along with some cell references) admits at most one such prefix, which corresponds to the (uniquely determined) instruction that TVM will execute first. After execution, this prefix is removed from the code of the current continuation, and the next instruction can be decoded.\n\n### 5.2.3. Invalid opcode\n\nIf no prefix of $\\texttt{cc.code}$ encodes a valid instruction in the current codepage, an invalid opcode [exception](#4-5-7-list-of-predefined-exceptions) is generated. However, the case of an empty $\\texttt{cc.code}$ is treated [separately](#4-1-4-normal-work-of-tvm%2C-or-the-main-loop) (the exact behavior may depend on the current codepage).\n\n### 5.2.4. Special case: end-of-code padding\n\nAs an exception to the above rule, some codepages may accept some values of $\\texttt{cc.code}$ that are too short to be valid instruction encodings as additional variants of $\\texttt{NOP}$, thus effectively using the same procedure for them as for an empty $\\texttt{cc.code}$. Such bitstrings may be used for padding the code near its end.\n\nFor example, if [binary string](#1-0-3-emphasizing-that-a-string-is-a-hexadecimal-representation-of-a-bitstring) $\\texttt{00000000}$ (i.e., $\\texttt{x00}$, is used in a codepage to encode $\\texttt{NOP}$, its proper prefixes cannot encode any instructions. So this codepage may accept $\\texttt{0}$, $\\texttt{00}$, $\\texttt{000}$, $\\ldots$, $\\texttt{0000000}$ as variants of $\\texttt{NOP}$ if this is all that is left in $\\texttt{cc.code}$, instead of generating an invalid opcode exception.\n\nSuch a padding may be useful, for example, if the $\\texttt{PUSHCONT}$ primitive creates only [continuations](#4-2-3-constant%2C-or-literal%2C-continuations) with code consisting of an integral number of bytes, but not all instructions are encoded by an integral number of bytes.\n\n### 5.2.5. TVM code is a bitcode, not a bytecode\n\nRecall that TVM is a bit-oriented machine in the sense that its *Cell*s (and *Slice*s) are naturally considered as [sequences of bits](#3-2-5-cells-and-cell-primitives-are-bit-oriented,-not-byte-oriented), not just of octets (bytes). Because the TVM code is also kept in cells ([3.1.9](#3-1-9-tvm-code-is-a-tree-of-cells) and [4.1.4](#4-1-4-normal-work-of-tvm%2C-or-the-main-loop)), there is no reason to use only bitstrings of length divisible by eight as encodings of complete instructions. In other words, generally speaking, *the TVM code is a bitcode, not a bytecode*.\n\nThat said, some codepages (such as our experimental codepage zero) may opt to use a bytecode (i.e., to use only encodings consisting of an integral number of bytes)—either for simplicity, or for the ease of debugging and of studying memory (i.e., cell) dumps.<a id=\"ref-fn27\"></a><sup>[27](#fn27)</sup>\n\n### 5.2.6. Opcode space used by a complete instruction\n\nRecall from coding theory that the lengths of bitstrings $l_i$ used in a binary prefix code satisfy Kraft–McMillan inequality $\\sum_i2^{-l_i}\\leq1$. This is applicable in particular to the (complete) instruction encoding used by a TVM codepage. We say that *a particular complete instruction* (or, more precisely, *the encoding of a complete instruction*) *utilizes the portion $2^{-l}$ of the opcode space*, if it is encoded by an $l$-bit string. One can see that all complete instructions together utilize at most $1$ (i.e., \"at most the whole opcode space\").\n\n### 5.2.7. Opcode space used by an instruction, or a class of instructions\n\nThe above terminology is extended to instructions (considered with all admissible values of their parameters), or even classes of instructions (e.g., all arithmetic instructions). We say that an (incomplete) instruction, or a class of instructions, occupies portion $\\alpha$ of the opcode space, if $\\alpha$ is the sum of the portions of the opcode space occupied by all complete instructions belonging to that class.\n\n### 5.2.8. Opcode space for bytecodes\n\nA useful approximation of the above definitions is as follows: Consider all 256 possible values for the first byte of an instruction encoding. Suppose that $k$ of these values correspond to the specific instruction or class of instructions we are considering. Then this instruction or class of instructions occupies approximately the portion $k/256$ of the opcode space.\n\nThis approximation shows why all instructions cannot occupy together more than the portion $256/256=1$ of the opcode space, at least without compromising the uniqueness of instruction decoding.\n\n### 5.2.9. Almost optimal encodings\n\nCoding theory tells us that in an optimally dense encoding, the portion of the opcode space used by a complete instruction ($2^{-l}$, if the complete instruction is encoded in $l$ bits) should be approximately equal to the probability or frequency of its occurrence in real programs.<a id=\"ref-fn28\"></a><sup>[28](#fn28)</sup> The same should hold for (incomplete) instructions, or primitives (i.e., generic instructions without specified values of parameters), and for classes of instructions.\n\n### 5.2.10. Example: stack manipulation primitives\n\nFor instance, if stack manipulation instructions constitute approximately half of all instructions in a typical TVM program, one should allocate approximately half of the opcode space for encoding stack manipulation instructions. One might reserve the first bytes (\"opcodes\") $\\texttt{0x00}$-$\\texttt{0x7f}$ for such instructions. If a quarter of these instructions are $\\texttt{XCHG}$, it would make sense to reserve $\\texttt{0x00}$-$\\texttt{0x1f}$ for $\\texttt{XCHG}$s. Similarly, if half of all $\\texttt{XCHG}$s involve the top of stack $\\texttt{s0}$, it would make sense to use $\\texttt{0x00}$-$\\texttt{0x0f}$ to encode $\\texttt{XCHG s0,s}(i)$.\n\n### 5.2.11. Simple encodings of instructions\n\nIn most cases, *simple* encodings of complete instructions are used. Simple encodings begin with a fixed bitstring called the *opcode* of the instruction, followed by, say, 4-bit fields containing the indices $i$ of stack registers $\\texttt{s}(i)$ specified in the instruction, followed by all other constant (literal, immediate) parameters included in the complete instruction. While simple encodings may not be exactly optimal, they admit short descriptions, and their decoding and encoding can be easily implemented.\n\nIf a (generic) instruction uses a simple encoding with an $l$-bit opcode, then the instruction will utilize $2^{-l}$ portion of the opcode space. This observation might be useful for considerations described in [5.2.9](#5-2-9-almost-optimal-encodings) and [5.2.10](#5-2-10-example:-stack-manipulation-primitives).\n\n### 5.2.12. Optimizing code density further: Huffman codes\n\nOne might construct optimally dense binary code for the set of all complete instructions, provided their probabilities or frequences in real code are known. This is the well-known Huffman code (for the given probability distribution). However, such code would be highly unsystematic and hard to decode.\n\n### 5.2.13. Practical instruction encodings\n\nIn practice, instruction encodings used in TVM and other virtual machines offer a compromise between code density and ease of encoding and decoding. Such a compromise may be achieved by selecting [simple encodings](#5-2-11-simple-encodings-of-instructions) for all instructions (maybe with separate simple encodings for some often used variants, such as $\\texttt{XCHG s0,s}(i)$ among all $\\texttt{XCHG s}(i)\\texttt{,s}(j)$), and allocating opcode space for such simple encodings using the heuristics outlined in [5.2.9](#5-2-9-almost-optimal-encodings) and [5.2.10](#5-2-10-example:-stack-manipulation-primitives); this is the approach currently used in TVM.\n\n---\n\n## 5.3   Instruction encoding in codepage zero\n\nThis section provides details about the experimental instruction encoding for codepage zero, as described elsewhere in this [document](#a-instructions-and-opcodes) and used in the preliminary test version of TVM.\n\n### 5.3.1. Upgradability\n\nFirst of all, even if this preliminary version somehow gets into the production version of the TON Blockchain, the [codepage mechanism](#5-1-codepages-and-interoperability-of-different-tvm-versions) enables us to introduce better versions later without compromising backward compatibility.<a id=\"ref-fn29\"></a><sup>[29](#fn29)</sup> So in the meantime, we are free to experiment.\n\n### 5.3.2. Choice of instructions\n\nWe opted to include many \"experimental\" and not strictly necessary instructions in codepage zero just to see how they might be used in real code. For example, we have both the [basic](#2-2-1-basic-stack-manipulation-primitives) and the [compound](#2-2-3-compound-stack-manipulation-primitives) stack manipulation primitives, as well as some \"unsystematic\" ones such as $\\texttt{ROT}$ (mostly borrowed from Forth). If such primitives are rarely used, their inclusion just wastes some part of the opcode space and makes the encodings of other instructions slightly less effective, something we can afford at this stage of TVM's development.\n\n### 5.3.3. Using experimental instructions\n\nSome of these experimental instructions have been assigned quite long opcodes, just to fit more of them into the opcode space. One should not be afraid to use them just because they are long; if these instructions turn out to be useful, they will receive shorter opcodes in future revisions. Codepage zero is not meant to be fine-tuned in this respect.\n\n### 5.3.4. Choice of bytecode\n\nWe opted to use a bytecode (i.e., to use encodings of complete instructions of lengths divisible by eight). While this may not produce optimal code density, because such a length restriction makes it more difficult to match portions of opcode space used for the encoding of instructions with estimated frequencies of these instructions in TVM code [5.2.11](#5-2-11-simple-encodings-of-instructions) and [5.2.9](#5-2-9-almost-optimal-encodings)), such an approach has its advantages: it admits a simpler instruction decoder and simplifies [debugging](#5-2-5-tvm-code-is-a-bitcode%2C-not-a-bytecode).\n\nAfter all, we do not have enough data on the relative frequencies of different instructions right now, so our code density optimizations are likely to be very approximate at this stage. The ease of debugging and experimenting and the simplicity of implementation are more important at this point.\n\n### 5.3.5. Simple encodings for all instructions\n\nFor similar reasons, we opted to use simple encodings for all instructions ([5.2.11](#5-2-11-simple-encodings-of-instructions) and [5.2.13](#5-2-13-practical-instruction-encodings)), with separate [simple encodings](#5-2-13-practical-instruction-encodings) for some very frequently used subcases. That said, we tried to distribute opcode space using the heuristics described in [5.2.9](#5-2-9-almost-optimal-encodings) and [5.2.10](#5-2-10-example:-stack-manipulation-primitives).\n\n### 5.3.6. Lack of context-dependent encodings\n\nThis version of TVM also does not use [context-dependent encodings](#5-1-6-making-instruction-encoding-context-dependent). They may be added at a later stage, if deemed useful.\n\n### 5.3.7. The list of all instructions\n\nThe list of all instructions available in codepage zero, along with their encodings and (in some cases) short descriptions, may be found in [Appendix A](#a-instructions-and-opcodes).\n\n---\n\n\n# A   Instructions and opcodes\n\nThis appendix lists all [instructions](#5-3-instruction-encoding-in-codepage-zero) available in the (experimental) codepage zero of TVM.\n\nWe list the instructions in lexicographical opcode order. However, the opcode space is distributed in such way as to make all instructions in each category (e.g., arithmetic primitives) have neighboring opcodes. So we first list a number of stack manipulation primitives, then constant primitives, arithmetic primitives, comparison primitives, cell primitives, continuation primitives, dictionary primitives, and finally application-specific primitives.\n\nWe use [hexadecimal notation](#1-0-notation-for-bitstrings) for bitstrings. Stack registers $\\texttt{s}(i)$ usually have $0\\leq i\\leq 15$, and $i$ is encoded in a 4-bit field (or, on a few rare occasions, in an 8-bit field). Other immediate parameters are usually 4-bit, 8-bit, or variable length.\n\nThe [stack notation](#2-1-10-stack-notation) is extensively used throughout this appendix.\n\n## A.1  Gas prices\n\nThe gas price for most primitives equals the *basic gas price*, computed as $P_b:=10+b+5r$, where $b$ is the instruction length in bits and $r$ is the number of cell references included in the instruction. When the gas price of an instruction differs from this basic price, it is indicated in parentheses after its mnemonics, either as *($x$)*, meaning that the total gas price equals $x$, or as *(+$x$)*, meaning $P_b+x$. Apart from integer constants, the following expressions may appear:\n\n- $C_r$ — The total price of \"reading\" cells (i.e., transforming cell references into cell slices). Currently equal to 100 or 25 gas units per cell depending on whether it is the first time a cell with this hash is being \"read\" during the current run of the VM or not.\n- $L$ — The total price of loading cells. Depends on the loading action required.\n- $B_w$ — The total price of creating new *Builder*s. Currently equal to 0 gas units per builder.\n- $C_w$ — The total price of creating new *Cell*s from *Builder*s. Currently equal to 500 gas units per cell.\n\nBy default, the gas price of an instruction equals $P:=P_b+C_r+L+B_w+C_w$.\n\n## A.2   Stack manipulation primitives\n\nThis section includes both the [basic](#2-2-1-basic-stack-manipulation-primitives) and the [compound](#2-2-3-compound-stack-manipulation-primitives) stack manipulation primitives, as well as some \"unsystematic\" ones. Some compound stack manipulation primitives, such as $\\texttt{XCPU}$ or $\\texttt{XCHG2}$, turn out to have the same length as an equivalent sequence of simpler operations. We have included these primitives regardless, so that they can easily be allocated shorter opcodes in a future revision of TVM—or removed for good.\n\nSome stack manipulation instructions have two mnemonics: one Forth-style (e.g., $\\texttt{-ROT}$), the other conforming to the usual rules for identifiers (e.g., $\\texttt{ROTREV}$). Whenever a stack manipulation primitive (e.g., $\\texttt{PICK}$) accepts an integer parameter $n$ from the stack, it must be within the range $0\\ldots255$; otherwise a range check exception happens before any further checks.\n\n\n### A.2.1. Basic stack manipulation primitives\n\n- $\\texttt{00}$ — $\\texttt{NOP}$, does nothing.\n- $\\texttt{01}$ — $\\texttt{XCHG s1}$, also known as $\\texttt{SWAP}$.\n- $\\texttt{0}i$ — $\\texttt{XCHG s}(i)$ or $\\texttt{XCHG s0,s}(i)$, interchanges the top of the stack with $\\texttt{s}(i)$, $1\\leq i\\leq 15$.\n- $\\texttt{10}ij$ — $\\texttt{XCHG s}(i)\\texttt{,s}(j)$, $1\\leq i<j\\leq15$, interchanges $\\texttt{s}(i)$ with $\\texttt{s}(j)$.\n- $\\texttt{11}ii$ — $\\texttt{XCHG s0,s}(ii)$, with $0\\leq ii\\leq255$.\n- $\\texttt{1}i$ — $\\texttt{XCHG s1,s}(i)$, $2\\leq i\\leq 15$.\n- $\\texttt{2}i$ — $\\texttt{PUSH s}(i)$, $0\\leq i\\leq 15$, pushes a copy of the old $\\texttt{s}(i)$ into the stack.\n- $\\texttt{20}$ — $\\texttt{PUSH s0}$, also known as $\\texttt{DUP}$.\n- $\\texttt{21}$ — $\\texttt{PUSH s1}$, also known as $\\texttt{OVER}$.\n- $\\texttt{3}i$ — $\\texttt{POP s}(i)$, $0\\leq i\\leq 15$, pops the old top-of-stack value into the old $\\texttt{s}(i)$.\n- $\\texttt{30}$ — $\\texttt{POP s0}$, also known as $\\texttt{DROP}$, discards the top-of-stack value.\n- $\\texttt{31}$ — $\\texttt{POP s1}$, also known as $\\texttt{NIP}$.\n\n### A.2.2. Compound stack manipulation primitives\n\nParameters $i$, $j$, and $k$ of the following primitives all are 4-bit integers in the range $0\\ldots15$.\n\n- $\\texttt{4}ijk$ — $\\texttt{XCHG3 s}(i)\\texttt{,s}(j)\\texttt{,s}(k)$, equivalent to $\\texttt{XCHG s2,s}(i)$; $\\texttt{XCHG s1, s}(j)$; $\\texttt{XCHG s0,s}(k)$, with $0\\leq i,j,k\\leq 15$.\n- $\\texttt{50}ij$ — $\\texttt{XCHG2 s}(i)\\texttt{,s}(j)$, equivalent to $\\texttt{XCHG s1,s}(i)$; $\\texttt{XCHG s}(j)$.\n- $\\texttt{51}ij$ — $\\texttt{XCPU s}(i)\\texttt{,s}(j)$, equivalent to $\\texttt{XCHG s}(i)$; $\\texttt{PUSH s}(j)$.\n- $\\texttt{52}ij$ — $\\texttt{PUXC s}(i)\\texttt{,s}(j-1)$, equivalent to $\\texttt{PUSH s}(i)$; $\\texttt{SWAP}$; $\\texttt{XCHG s}(j)$.\n- $\\texttt{53}ij$ — $\\texttt{PUSH2 s}(i)\\texttt{,s}(j)$, equivalent to $\\texttt{PUSH s}(i)$; $\\texttt{PUSH s}(j+1)$.\n- $\\texttt{540}ijk$ — $\\texttt{XCHG3 s}(i)\\texttt{,s}(j)\\texttt{,s}(k)$ (long form).\n- $\\texttt{541}ijk$ — $\\texttt{XC2PU s}(i)\\texttt{,s}(j)\\texttt{,s}(k)$, equivalent to $\\texttt{XCHG2 s}(i)\\texttt{,s}(j)$; $\\texttt{PUSH s}(k)$.\n- $\\texttt{542}ijk$ — $\\texttt{XCPUXC s}(i)\\texttt{,s}(j)\\texttt{,s}(k-1)$, equivalent to $\\texttt{XCHG s1,s}(i)$; $\\texttt{PUXC s}(j)\\texttt{,s}(k-1)$.\n- $\\texttt{543}ijk$ — $\\texttt{XCPU2 s}(i)\\texttt{,s}(j)\\texttt{,s}(k)$, equivalent to $\\texttt{XCHG s}(i)$; $\\texttt{PUSH2 s}(j)\\texttt{, s}(k)$.\n- $\\texttt{544}ijk$ — $\\texttt{PUXC2 s}(i)\\texttt{,s}(j-1)\\texttt{,s}(k-1)$, equivalent to $\\texttt{PUSH s}(i)$; $\\texttt{XCHG s2}$; $\\texttt{XCHG2 s}(j)\\texttt{,s}(k)$.\n- $\\texttt{545}ijk$ — $\\texttt{PUXCPU s}(i)\\texttt{,s}(j-1)\\texttt{,s}(k-1)$, equivalent to $\\texttt{PUXC s}(i)\\texttt{,s}(j-1)$; $\\texttt{PUSH s}(k)$.\n- $\\texttt{546}ijk$ — $\\texttt{PU2XC s}(i)\\texttt{,s}(j-1)\\texttt{,s}(k-2)$, equivalent to $\\texttt{PUSH s}(i)$; $\\texttt{SWAP}$; $\\texttt{PUXC s}(j)\\texttt{,s}(k-1)$.\n- $\\texttt{547}ijk$ — $\\texttt{PUSH3 s}(i)\\texttt{,s}(j)\\texttt{,s}(k)$, equivalent to $\\texttt{PUSH s}(i)$; $\\texttt{PUSH2 s}(j+1)\\texttt{,s}(k+1)$.\n- $\\texttt{54C\\_}$ — unused.\n\n### A.2.3. Exotic stack manipulation primitives\n\n- $\\texttt{55}ij$ — $\\texttt{BLKSWAP}$ $i+1$,$j+1$, permutes two blocks $\\texttt{s}(j+i+1)\\ldots\\texttt{s}(j+1)$ and $\\texttt{s}(j)\\ldots\\texttt{s0}$, for $0\\leq i,j\\leq15$. Equivalent to $\\texttt{REVERSE}$ $i+1$,$j+1$; $\\texttt{REVERSE}$ $j+1$,0; $\\texttt{REVERSE}$ $i+j+2$,0.\n- $\\texttt{5513}$ — $\\texttt{ROT2}$ or $\\texttt{2ROT}$ ($a$ $b$ $c$ $d$ $e$ $f$ -- $c$ $d$ $e$ $f$ $a$ $b$), rotates the three topmost pairs of stack entries.\n- $\\texttt{550}i$ — $\\texttt{ROLL}$ $i+1$, rotates the top $i+1$ stack entries. Equivalent to $\\texttt{BLKSWAP 1}$,$i+1$.\n- $\\texttt{55}i\\texttt{0}$ — $\\texttt{ROLLREV}$ $i+1$ or $\\texttt{-ROLL}$ $i+1$, rotates the top $i+1$ stack entries in the other direction. Equivalent to $\\texttt{BLKSWAP}$ $i+1$,1.\n- $\\texttt{56}ii$ — $\\texttt{PUSH s}(ii)$ for $0\\leq ii\\leq 255$.\n- $\\texttt{57}ii$ — $\\texttt{POP s}(ii)$ for $0\\leq ii\\leq 255$.\n- $\\texttt{58}$ — $\\texttt{ROT}$ ($a$ $b$ $c$ -- $b$ $c$ $a$), equivalent to $\\texttt{BLKSWAP 1,2}$ or to $\\texttt{XCHG2 s2,s1}$.\n- $\\texttt{59}$ — $\\texttt{ROTREV}$ or $\\texttt{-ROT}$ ($a$ $b$ $c$ -- $c$ $a$ $b$), equivalent to $\\texttt{BLKSWAP 2,1}$ or to $\\texttt{XCHG2 s2,s2}$.\n- $\\texttt{5A}$ — $\\texttt{SWAP2}$ or $\\texttt{2SWAP}$ ($a$ $b$ $c$ $d$ -- $c$ $d$ $a$ $b$), equivalent to $\\texttt{BLKSWAP 2,2}$ or to $\\texttt{XCHG2 s3,s2}$.\n- $\\texttt{5B}$ — $\\texttt{DROP2}$ or $\\texttt{2DROP}$ ($a$ $b$ -- ), equivalent to $\\texttt{DROP}$; $\\texttt{DROP}$.\n- $\\texttt{5C}$ — $\\texttt{DUP2}$ or $\\texttt{2DUP}$ ($a$ $b$ -- $a$ $b$ $a$ $b$), equivalent to $\\texttt{PUSH2 s1,s0}$.\n- $\\texttt{5D}$ — $\\texttt{OVER2}$ or $\\texttt{2OVER}$ ($a$ $b$ $c$ $d$ -- $a$ $b$ $c$ $d$ $a$ $b$), equivalent to $\\texttt{PUSH2 s3,s2}$.\n- $\\texttt{5E}ij$ — $\\texttt{REVERSE}$ $i+2$,$j$, reverses the order of $\\texttt{s}(j+i+1)\\ldots\\texttt{s}(j)$ for $0\\leq i,j\\leq 15$; equivalent to a sequence of $\\lfloor i/2\\rfloor+1$ $\\texttt{XCHG}$s.\n- $\\texttt{5F0}i$ — $\\texttt{BLKDROP}$ $i$, equivalent to $\\texttt{DROP}$ performed $i$ times.\n- $\\texttt{5F}ij$ — $\\texttt{BLKPUSH}$ $i$,$j$, equivalent to $\\texttt{PUSH s}(j)$ performed $i$ times, $1\\leq i\\leq 15$, $0\\leq j\\leq 15$.\n- $\\texttt{60}$ — $\\texttt{PICK}$ or $\\texttt{PUSHX}$, pops integer $i$ from the stack, then performs $\\texttt{PUSH s}(i)$.\n- $\\texttt{61}$ — $\\texttt{ROLLX}$, pops integer $i$ from the stack, then performs $\\texttt{BLKSWAP 1}$,$i$.\n- $\\texttt{62}$ — $\\texttt{-ROLLX}$ or $\\texttt{ROLLREVX}$, pops integer $i$ from the stack, then performs $\\texttt{BLKSWAP}$ $i$,1.\n- $\\texttt{63}$ — $\\texttt{BLKSWX}$, pops integers $i$,$j$ from the stack, then performs $\\texttt{BLKSWAP}$ $i$,$j$.\n- $\\texttt{64}$ — $\\texttt{REVX}$, pops integers $i$,$j$ from the stack, then performs $\\texttt{REVERSE}$ $i$,$j$.\n- $\\texttt{65}$ — $\\texttt{DROPX}$, pops integer $i$ from the stack, then performs $\\texttt{BLKDROP}$ $i$.\n- $\\texttt{66}$ — $\\texttt{TUCK}$ ($a$ $b$ - $b$ $a$ $b$), equivalent to $\\texttt{SWAP}$; $\\texttt{OVER}$ or to $\\texttt{XCPU s1,s1}$.\n- $\\texttt{67}$ — $\\texttt{XCHGX}$, pops integer $i$ from the stack, then performs $\\texttt{XCHG s}(i)$.\n- $\\texttt{68}$ — $\\texttt{DEPTH}$, pushes the current depth of the stack.\n- $\\texttt{69}$ — $\\texttt{CHKDEPTH}$, pops integer $i$ from the stack, then checks whether there are at least $i$ elements, generating a stack underflow exception otherwise.\n- $\\texttt{6A}$ — $\\texttt{ONLYTOPX}$, pops integer $i$ from the stack, then removes all but the top $i$ elements.\n- $\\texttt{6B}$ — $\\texttt{ONLYX}$, pops integer $i$ from the stack, then leaves only the bottom $i$ elements. Approximately equivalent to $\\texttt{DEPTH}$; $\\texttt{SWAP}$; $\\texttt{SUB}$; $\\texttt{DROPX}$.\n- $\\texttt{6C00}$--$\\texttt{6C0F}$ — reserved for stack operations.\n- $\\texttt{6C}ij$ — $\\texttt{BLKDROP2}$ $i$,$j$, drops $i$ stack elements under the top $j$ elements, where $1\\leq i\\leq15$ and $0\\leq j\\leq 15$. Equivalent to $\\texttt{REVERSE}$ $i+j$,0; $\\texttt{BLKDROP}$ $i$; $\\texttt{REVERSE}$ $j$,0.\n\n## A.3   Tuple, List, and Null primitives\n\n*Tuple*s are ordered collections consisting of at most 255 TVM stack values of arbitrary types (not necessarily the same). Tuple primitives create, modify, and unpack *Tuple*s; they manipulate values of arbitrary types in the process, similarly to the stack primitives. We do not recommend using *Tuple*s of more than 15 elements.\n\nWhen a *Tuple* $t$ contains elements $x_1$, ..., $x_n$ (in that order), we write $t=(x_1,\\ldots,x_n)$; number $n\\geq0$ is the *length* of *Tuple* $t$. It is also denoted by $|t|$. *Tuple*s of length two are called *pairs*, and *Tuple*s of length three are *triples*.\n\nLisp-style lists are represented with the aid of pairs, i.e., tuples consisting of exactly two elements. An empty list is represented by a *Null* value, and a non-empty list is represented by pair $(h,t)$, where $h$ is the first element of the list, and $t$ is its tail.\n\n### A.3.1. Null primitives\n\nThe following primitives work with (the only) value $\\bot$ of type *Null*, useful for representing empty lists, empty branches of binary trees, and absence of values in *Maybe $X$* types. An empty *Tuple* created by $\\texttt{NIL}$ could have been used for the same purpose; however, *Null* is more efficient and costs less gas.\n\n- $\\texttt{6D}$ — $\\texttt{NULL}$ or $\\texttt{PUSHNULL}$ ( -- $\\bot$), pushes the only value of type *Null*.\n- $\\texttt{6E}$ — $\\texttt{ISNULL}$ ($x$ -- $?$), checks whether $x$ is a *Null*, and returns $-1$ or $0$ accordingly.\n\n### A.3.2. Tuple primitives\n\n- $\\texttt{6F0}n$ — $\\texttt{TUPLE}$ $n$ ($x_1$ $\\ldots$ $x_n$ -- $t$), creates a new *Tuple* $t=(x_1,\\ldots,x_n)$ containing $n$ values $x_1$, $\\ldots$, $x_n$, where $0\\leq n\\leq 15$.\n- $\\texttt{6F00}$ — $\\texttt{NIL}$ ( -- $t$), pushes the only *Tuple* $t=()$ of length zero.\n- $\\texttt{6F01}$ — $\\texttt{SINGLE}$ ($x$ -- $t$), creates a singleton $t:=(x)$, i.e., a *Tuple* of length one.\n- $\\texttt{6F02}$ — $\\texttt{PAIR}$ or $\\texttt{CONS}$ ($x$ $y$ -- $t$), creates pair $t:=(x,y)$.\n- $\\texttt{6F03}$ — $\\texttt{TRIPLE}$ ($x$ $y$ $z$ -- $t$), creates triple $t:=(x,y,z)$.\n- $\\texttt{6F1}k$ — $\\texttt{INDEX}$ $k$ ($t$ -- $x$), returns the $k$-th element of a *Tuple* $t$, where $0\\leq k\\leq 15$. In other words, returns $x_{k+1}$ if $t=(x_1,\\ldots,x_n)$. If $k\\geq n$, throws a range check exception.\n- $\\texttt{6F10}$ — $\\texttt{FIRST}$ or $\\texttt{CAR}$ ($t$ -- $x$), returns the first element of a *Tuple*.\n- $\\texttt{6F11}$ — $\\texttt{SECOND}$ or $\\texttt{CDR}$ ($t$ -- $y$), returns the second element of a *Tuple*.\n- $\\texttt{6F12}$ — $\\texttt{THIRD}$ ($t$ -- $z$), returns the third element of a *Tuple*.\n- $\\texttt{6F2}n$ — $\\texttt{UNTUPLE}$ $n$ ($t$ -- $x_1$ $\\ldots$ $x_n$), unpacks a *Tuple* $t=(x_1,\\ldots,x_n)$ of length equal to $0\\leq n\\leq 15$. If $t$ is not a *Tuple*, of if $|t|\\neq n$, a type check exception is thrown.\n- $\\texttt{6F21}$ — $\\texttt{UNSINGLE}$ ($t$ -- $x$), unpacks a singleton $t=(x)$.\n- $\\texttt{6F22}$ — $\\texttt{UNPAIR}$ or $\\texttt{UNCONS}$ ($t$ -- $x$ $y$), unpacks a pair $t=(x,y)$.\n- $\\texttt{6F23}$ — $\\texttt{UNTRIPLE}$ ($t$ -- $x$ $y$ $z$), unpacks a triple $t=(x,y,z)$.\n- $\\texttt{6F3}k$ — $\\texttt{UNPACKFIRST}$ $k$ ($t$ -- $x_1$ $\\ldots$ $x_k$), unpacks first $0\\leq k\\leq 15$ elements of a *Tuple* $t$. If $|t|<k$, throws a type check exception.\n- $\\texttt{6F30}$ — $\\texttt{CHKTUPLE}$ ($t$ -- ), checks whether $t$ is a *Tuple*.\n- $\\texttt{6F4}n$ — $\\texttt{EXPLODE}$ $n$ ($t$ -- $x_1$ $\\ldots$ $x_m$ $m$), unpacks a *Tuple* $t=(x_1,\\ldots,x_m)$ and returns its length $m$, but only if $m\\leq n\\leq 15$. Otherwise throws a type check exception.\n- $\\texttt{6F5}k$ — $\\texttt{SETINDEX}$ $k$ ($t$ $x$ -- $t'$), computes *Tuple* $t'$ that differs from $t$ only at position $t'_{k+1}$, which is set to $x$. In other words, $|t'|=|t|$, $t'_i=t_i$ for $i\\neq k+1$, and $t'_{k+1}=x$, for given $0\\leq k\\leq15$. If $k\\geq|t|$, throws a range check exception.\n- $\\texttt{6F50}$ — $\\texttt{SETFIRST}$ ($t$ $x$ -- $t'$), sets the first component of *Tuple* $t$ to $x$ and returns the resulting *Tuple* $t'$.\n- $\\texttt{6F51}$ — $\\texttt{SETSECOND}$ ($t$ $x$ -- $t'$), sets the second component of *Tuple* $t$ to $x$ and returns the resulting *Tuple* $t'$.\n- $\\texttt{6F52}$ — $\\texttt{SETTHIRD}$ ($t$ $x$ -- $t'$), sets the third component of *Tuple* $t$ to $x$ and returns the resulting *Tuple* $t'$.\n- $\\texttt{6F6}k$ — $\\texttt{INDEXQ}$ $k$ ($t$ -- $x$), returns the $k$-th element of a *Tuple* $t$, where $0\\leq n\\leq 15$. In other words, returns $x_{k+1}$ if $t=(x_1,\\ldots,x_n)$. If $k\\geq n$, or if $t$ is *Null*, returns a *Null* instead of $x$.\n- $\\texttt{6F7}k$ — $\\texttt{SETINDEXQ}$ $k$ ($t$ $x$ -- $t'$), sets the $k$-th component of *Tuple* $t$ to $x$, where $0\\leq k<16$, and returns the resulting *Tuple* $t'$. If $|t|\\leq k$, first extends the original *Tuple* to length $k+1$ by setting all new components to *Null*. If the original value of $t$ is *Null*, treats it as an empty *Tuple*. If $t$ is not *Null* or *Tuple*, throws an exception. If $x$ is *Null* and either $|t|\\leq k$ or $t$ is *Null*, then always returns $t'=t$ (and does not consume tuple creation gas).\n- $\\texttt{6F80}$ — $\\texttt{TUPLEVAR}$ ($x_1$ $\\ldots$ $x_n$ $n$ -- $t$), creates a new *Tuple* $t$ of length $n$ similarly to $\\texttt{TUPLE}$, but with $0\\leq n\\leq 255$ taken from the stack.\n- $\\texttt{6F81}$ — $\\texttt{INDEXVAR}$ ($t$ $k$ -- $x$), similar to $\\texttt{INDEX}$ $k$, but with $0\\leq k\\leq 254$ taken from the stack.\n- $\\texttt{6F82}$ — $\\texttt{UNTUPLEVAR}$ ($t$ $n$ -- $x_1$ $\\ldots$ $x_n$), similar to $\\texttt{UNTUPLE}$ $n$, but with $0\\leq n\\leq 255$ taken from the stack.\n- $\\texttt{6F83}$ — $\\texttt{UNPACKFIRSTVAR}$ ($t$ $n$ -- $x_1$ $\\ldots$ $x_n$), similar to $\\texttt{UNPACKFIRST}$ $n$, but with $0\\leq n\\leq 255$ taken from the stack.\n- $\\texttt{6F84}$ — $\\texttt{EXPLODEVAR}$ ($t$ $n$ -- $x_1$ $\\ldots$ $x_m$ $m$), similar to $\\texttt{EXPLODE}$ $n$, but with $0\\leq n\\leq 255$ taken from the stack.\n- $\\texttt{6F85}$ — $\\texttt{SETINDEXVAR}$ ($t$ $x$ $k$ -- $t'$), similar to $\\texttt{SETINDEX}$ $k$, but with $0\\leq k\\leq 254$ taken from the stack.\n- $\\texttt{6F86}$ — $\\texttt{INDEXVARQ}$ ($t$ $k$ -- $x$), similar to $\\texttt{INDEXQ}$ $n$, but with $0\\leq k\\leq 254$ taken from the stack.\n- $\\texttt{6F87}$ — $\\texttt{SETINDEXVARQ}$ ($t$ $x$ $k$ -- $t'$), similar to $\\texttt{SETINDEXQ}$ $k$, but with $0\\leq k\\leq 254$ taken from the stack.\n- $\\texttt{6F88}$ — $\\texttt{TLEN}$ ($t$ -- $n$), returns the length of a *Tuple*.\n- $\\texttt{6F89}$ — $\\texttt{QTLEN}$ ($t$ -- $n$ or $-1$), similar to $\\texttt{TLEN}$, but returns $-1$ if $t$ is not a *Tuple*.\n- $\\texttt{6F8A}$ — $\\texttt{ISTUPLE}$ ($t$ -- $?$), returns $-1$ or $0$ depending on whether $t$ is a *Tuple*.\n- $\\texttt{6F8B}$ — $\\texttt{LAST}$ ($t$ -- $x$), returns the last element $t_{|t|}$ of a non-empty *Tuple* $t$.\n- $\\texttt{6F8C}$ — $\\texttt{TPUSH}$ or $\\texttt{COMMA}$ ($t$ $x$ -- $t'$), appends a value $x$ to a *Tuple* $t=(x_1,\\ldots,x_n)$, but only if the resulting *Tuple* $t'=(x_1,\\ldots,x_n,x)$ is of length at most 255. Otherwise throws a type check exception.\n- $\\texttt{6F8D}$ — $\\texttt{TPOP}$ ($t$ -- $t'$ $x$), detaches the last element $x=x_n$ from a non-empty *Tuple* $t=(x_1,\\ldots,x_n)$, and returns both the resulting *Tuple* $t'=(x_1,\\ldots,x_{n-1})$ and the original last element $x$.\n- $\\texttt{6FA0}$ — $\\texttt{NULLSWAPIF}$ ($x$ -- $x$ or $\\bot$ $x$), pushes a *Null* under the topmost *Integer* $x$, but only if $x\\neq0$.\n- $\\texttt{6FA1}$ — $\\texttt{NULLSWAPIFNOT}$ ($x$ -- $x$ or $\\bot$ $x$), pushes a *Null* under the topmost *Integer* $x$, but only if $x=0$. May be used for stack alignment after quiet primitives such as $\\texttt{PLDUXQ}$.\n- $\\texttt{6FA2}$ — $\\texttt{NULLROTRIF}$ ($x$ $y$ -- $x$ $y$ or $\\bot$ $x$ $y$), pushes a *Null* under the second stack entry from the top, but only if the topmost *Integer* $y$ is non-zero.\n- $\\texttt{6FA3}$ — $\\texttt{NULLROTRIFNOT}$ ($x$ $y$ -- $x$ $y$ or $\\bot$ $x$ $y$), pushes a *Null* under the second stack entry from the top, but only if the topmost *Integer* $y$ is zero. May be used for stack alignment after quiet primitives such as $\\texttt{LDUXQ}$.\n- $\\texttt{6FA4}$ — $\\texttt{NULLSWAPIF2}$ ($x$ -- $x$ or $\\bot$ $\\bot$ $x$), pushes two *Null*s under the topmost *Integer* $x$, but only if $x\\neq0$. Equivalent to $\\texttt{NULLSWAPIF}$; $\\texttt{NULLSWAPIF}$.\n- $\\texttt{6FA5}$ — $\\texttt{NULLSWAPIFNOT2}$ ($x$ -- $x$ or $\\bot$ $\\bot$ $x$), pushes two *Null*s under the topmost *Integer* $x$, but only if $x=0$. Equivalent to $\\texttt{NULLSWAPIFNOT}$; $\\texttt{NULLSWAPIFNOT}$.\n- $\\texttt{6FA6}$ — $\\texttt{NULLROTRIF2}$ ($x$ $y$ -- $x$ $y$ or $\\bot$ $\\bot$ $x$ $y$), pushes two *Null*s under the second stack entry from the top, but only if the topmost *Integer* $y$ is non-zero. Equivalent to $\\texttt{NULLROTRIF}$; $\\texttt{NULLROTRIF}$.\n- $\\texttt{6FA7}$ — $\\texttt{NULLROTRIFNOT2}$ ($x$ $y$ -- $x$ $y$ or $\\bot$ $\\bot$ $x$ $y$), pushes two *Null*s under the second stack entry from the top, but only if the topmost *Integer* $y$ is zero. Equivalent to $\\texttt{NULLROTRIFNOT}$; $\\texttt{NULLROTRIFNOT}$.\n- $\\texttt{6FB}ij$ — $\\texttt{INDEX2}$ $i$,$j$ ($t$ -- $x$), recovers $x=(t_{i+1})_{j+1}$ for $0\\leq i,j\\leq 3$. Equivalent to $\\texttt{INDEX}$ $i$; $\\texttt{INDEX}$ $j$.\n- $\\texttt{6FB4}$ — $\\texttt{CADR}$ ($t$ -- $x$), recovers $x=(t_2)_1$.\n- $\\texttt{6FB5}$ — $\\texttt{CDDR}$ ($t$ -- $x$), recovers $x=(t_2)_2$.\n- $\\texttt{6FE\\_}ijk$ — $\\texttt{INDEX3}$ $i$,$j$,$k$ ($t$ -- $x$), recovers $x=\\bigl((t_{i+1})_{j+1}\\bigr)_{k+1}$ for $0\\leq i,j,k\\leq3$. Equivalent to $\\texttt{INDEX2}$ $i$,$j$; $\\texttt{INDEX}$ $k$.\n- $\\texttt{6FD4}$ — $\\texttt{CADDR}$ ($t$ -- $x$), recovers $x=\\bigl((t_2)_2\\bigr)_1$.\n- $\\texttt{6FD5}$ — $\\texttt{CDDDR}$ ($t$ -- $x$), recovers $x=\\bigl((t_2)_2\\bigr)_2$.\n\n---\n\n## A.4  Constant, or literal primitives\n\nThe following primitives push into the stack one literal (or unnamed constant) of some type and range, stored as a part (an immediate argument) of the instruction. Therefore, if the immediate argument is absent or too short, an \"invalid or too short opcode\" exception (code 6) is thrown.\n\n### A.4.1. Integer and boolean constants\n\n- $\\texttt{7}i$ — $\\texttt{PUSHINT}$ $x$ with $-5\\leq x\\leq 10$, pushes integer $x$ into the stack; here $i$ equals four lower-order bits of $x$ (i.e., $i=x\\bmod 16$).\n- $\\texttt{70}$ — $\\texttt{ZERO}$, $\\texttt{FALSE}$, or $\\texttt{PUSHINT 0}$, pushes a zero.\n- $\\texttt{71}$ — $\\texttt{ONE}$ or $\\texttt{PUSHINT 1}$.\n- $\\texttt{72}$ — $\\texttt{TWO}$ or $\\texttt{PUSHINT 2}$.\n- $\\texttt{7A}$ — $\\texttt{TEN}$ or $\\texttt{PUSHINT}$ 10.\n- $\\texttt{7F}$ — $\\texttt{TRUE}$ or $\\texttt{PUSHINT -1}$.\n- $\\texttt{80}xx$ — $\\texttt{PUSHINT}$ $xx$ with $-128\\leq xx\\leq127$.\n- $\\texttt{81}xxxx$ — $\\texttt{PUSHINT}$ $xxxx$ with $-2^{15}\\leq xxxx<2^{15}$ a signed 16-bit big-endian integer.\n- $\\texttt{81FC18}$ — $\\texttt{PUSHINT}$ $-1000$.\n- $\\texttt{82}lxxx$ — $\\texttt{PUSHINT}$ $xxx$, where 5-bit $0\\leq l\\leq30$ determines the length $n=8l+19$ of signed big-endian integer $xxx$. The total length of this instruction is $l+4$ bytes or $n+13=8l+32$ bits.\n- $\\texttt{821005F5E100}$ — $\\texttt{PUSHINT}$ $10^8$.\n- $\\texttt{83}xx$ — $\\texttt{PUSHPOW2}$ $xx+1$, (quietly) pushes $2^{xx+1}$ for $0\\leq xx\\leq255$.\n- $\\texttt{83FF}$ — $\\texttt{PUSHNAN}$, pushes a $\\texttt{NaN}$.\n- $\\texttt{84}xx$ — $\\texttt{PUSHPOW2DEC}$ $xx+1$, pushes $2^{xx+1}-1$ for $0\\leq xx\\leq 255$.\n- $\\texttt{85}xx$ — $\\texttt{PUSHNEGPOW2}$ $xx+1$, pushes $-2^{xx+1}$ for $0\\leq xx\\leq 255$.\n- $\\texttt{86}$, $\\texttt{87}$ — reserved for integer constants.\n\n### A.4.2. Constant slices, continuations, cells, and references\n\nMost of the instructions listed below push literal slices, continuations, cells, and cell references, stored as immediate arguments to the instruction. Therefore, if the immediate argument is absent or too short, an \"invalid or too short opcode\" exception (code $6$) is thrown.\n\n- $\\texttt{88}$ — $\\texttt{PUSHREF}$, pushes the first reference of $\\texttt{cc.code}$ into the stack as a *Cell* (and removes this reference from the current continuation).\n- $\\texttt{89}$ — $\\texttt{PUSHREFSLICE}$, similar to $\\texttt{PUSHREF}$, but converts the cell into a *Slice*.\n- $\\texttt{8A}$ — $\\texttt{PUSHREFCONT}$, similar to $\\texttt{PUSHREFSLICE}$, but makes a simple ordinary *Continuation* out of the cell.\n- $\\texttt{8B}xsss$ — $\\texttt{PUSHSLICE sss}$, pushes the (prefix) subslice of $\\texttt{cc.code}$ consisting of its first $8x+4$ bits and no references (i.e., essentially a bitstring), where $0\\leq x\\leq15$. A completion tag is assumed, meaning that all trailing zeroes and the last binary one (if present) are removed from this bitstring. If the original bitstring consists only of zeroes, an empty slice will be pushed.\n- $\\texttt{8B08}$ — $\\texttt{PUSHSLICE x8\\_}$, pushes an empty slice (bitstring ' ').\n- $\\texttt{8B04}$ — $\\texttt{PUSHSLICE x4\\_}$, pushes bitstring $\\texttt{'0'}$.\n- $\\texttt{8B0C}$ — $\\texttt{PUSHSLICE xC\\_}$, pushes bitstring $\\texttt{'1'}$.\n- $\\texttt{8C}rxxssss$ — $\\texttt{PUSHSLICE ssss}$, pushes the (prefix) subslice of $\\texttt{cc.code}$ consisting of its first $1\\leq r+1\\leq 4$ references and up to first $8xx+1$ bits of data, with $0\\leq xx\\leq 31$. A completion tag is also assumed.\n- $\\texttt{8C01}$ is equivalent to $\\texttt{PUSHREFSLICE}$.\n- $\\texttt{8D}rxxsssss$ — $\\texttt{PUSHSLICE sssss}$, pushes the subslice of $\\texttt{cc.code}$ consisting of $0\\leq r\\leq 4$ references and up to $8xx+6$ bits of data, with $0\\leq xx\\leq 127$. A completion tag is assumed.\n- $\\texttt{8DE\\_}$ — unused (reserved).\n- $\\texttt{8F\\_}rxxcccc$ — $\\texttt{PUSHCONT cccc}$, where $cccc$ is the simple ordinary continuation made from the first $0\\leq r\\leq 3$ references and the first $0\\leq xx\\leq 127$ bytes of $\\texttt{cc.code}$.\n- $\\texttt{9}xccc$ — $\\texttt{PUSHCONT ccc}$, pushes an $x$-byte continuation for $0\\leq x\\leq 15$.\n\n## A.5  Arithmetic primitives\n\n### A.5.1. Addition, subtraction, multiplication\n\n- $\\texttt{A0}$ — $\\texttt{ADD}$ ($x$ $y$ -- $x+y$), adds together two integers.\n- $\\texttt{A1}$ — $\\texttt{SUB}$ ($x$ $y$ -- $x-y$).\n- $\\texttt{A2}$ — $\\texttt{SUBR}$ ($x$ $y$ -- $y-x$), equivalent to $\\texttt{SWAP}$; $\\texttt{SUB}$.\n- $\\texttt{A3}$ — $\\texttt{NEGATE}$ ($x$ -- $-x$), equivalent to $\\texttt{MULCONST}$ $-1$ or to $\\texttt{ZERO}$; $\\texttt{SUBR}$. Notice that it triggers an integer overflow exception if $x=-2^{256}$.\n- $\\texttt{A4}$ — $\\texttt{INC}$ ($x$ -- $x+1$), equivalent to $\\texttt{ADDCONST 1}$.\n- $\\texttt{A5}$ — $\\texttt{DEC}$ ($x$ -- $x-1$), equivalent to $\\texttt{ADDCONST}$ $-1$.\n- $\\texttt{A6}cc$ — $\\texttt{ADDCONST}$ $cc$ ($x$ -- $x+cc$), $-128\\leq cc\\leq127$.\n- $\\texttt{A7}cc$ — $\\texttt{MULCONST}$ $cc$ ($x$ -- $x\\cdot cc$), $-128\\leq cc\\leq127$.\n- $\\texttt{A8}$ — $\\texttt{MUL}$ ($x$ $y$ -- $xy$).\n\n### A.5.2. Division\n\nThe general encoding of a $\\texttt{DIV}$, $\\texttt{DIVMOD}$, or $\\texttt{MOD}$ operation is $\\texttt{A9}mscdf$, with an optional pre-multiplication and an optional replacement of the division or multiplication by a shift. Variable one- or two-bit fields $m$, $s$, $c$, $d$, and $f$ are as follows:\n\n- $0\\leq m\\leq1$ — Indicates whether there is pre-multiplication ($\\texttt{MULDIV}$ operation and its variants), possibly replaced by a left shift.\n- $0\\leq s\\leq2$ — Indicates whether either the multiplication or the division have been replaced by shifts: $s=0$—no replacement, $s=1$—division replaced by a right shift, $s=2$—multiplication replaced by a left shift (possible only for $m=1$).\n- $0\\leq c\\leq1$ — Indicates whether there is a constant one-byte argument $tt$ for the shift operator (if $s\\neq0$). For $s=0$, $c=0$. If $c=1$, then $0\\leq tt\\leq 255$, and the shift is performed by $tt+1$ bits. If $s\\neq0$ and $c=0$, then the shift amount is provided to the instruction as a top-of-stack *Integer* in range $0\\ldots256$.\n- $1\\leq d\\leq3$ — Indicates which results of division are required: $1$—only the quotient, $2$—only the remainder, $3$—both.\n- $0\\leq f\\leq2$ — Rounding mode: $0$—floor, $1$—nearest integer, $2$—ceiling ([1.5.6](#1-5-6-division-and-rounding)).\n\nExamples:\n\n- $\\texttt{A904}$ — $\\texttt{DIV}$ ($x$ $y$ -- $q:=\\lfloor x/y\\rfloor$).\n- $\\texttt{A905}$ — $\\texttt{DIVR}$ ($x$ $y$ -- $q':=\\lfloor x/y+1/2\\rfloor$).\n- $\\texttt{A906}$ — $\\texttt{DIVC}$ ($x$ $y$ -- $q'':=\\lceil x/y\\rceil$).\n- $\\texttt{A908}$ — $\\texttt{MOD}$ ($x$ $y$ -- $r$), where $q:=\\lfloor x/y\\rfloor$, $r:=x\\bmod y:=x-yq$.\n- $\\texttt{A90C}$ — $\\texttt{DIVMOD}$ ($x$ $y$ -- $q$ $r$), where $q:=\\lfloor x/y\\rfloor$, $r:=x-yq$.\n- $\\texttt{A90D}$ — $\\texttt{DIVMODR}$ ($x$ $y$ -- $q'$ $r'$), where $q':=\\lfloor x/y+1/2\\rfloor$, $r':=x-yq'$.\n- $\\texttt{A90E}$ — $\\texttt{DIVMODC}$ ($x$ $y$ -- $q''$ $r''$), where $q'':=\\lceil x/y\\rceil$, $r'':=x-yq''$.\n- $\\texttt{A924}$ — same as $\\texttt{RSHIFT}$: ($x$ $y$ -- $\\lfloor x\\cdot 2^{-y}\\rfloor$) for $0\\leq y\\leq 256$.\n- $\\texttt{A934}tt$ — same as $\\texttt{RSHIFT}$ $tt+1$: ($x$ -- $\\lfloor x\\cdot 2^{-tt-1}\\rfloor$).\n- $\\texttt{A938}tt$ — $\\texttt{MODPOW2}$ $tt+1$: ($x$ -- $x\\bmod 2^{tt+1}$).\n- $\\texttt{A985}$ — $\\texttt{MULDIVR}$ ($x$ $y$ $z$ -- $q'$), where $q'=\\lfloor xy/z+1/2\\rfloor$.\n- $\\texttt{A988}$ — $\\texttt{MULMOD}$ ($x$ $y$ $z$ -- $r$), where $r=xy\\bmod z=xy-qz$, $q=\\lfloor xy/z\\rfloor$. This operation always succeeds for $z\\neq0$ and returns the correct value of $r$, even if the intermediate result $xy$ or the quotient $q$ do not fit into 257 bits.\n- $\\texttt{A98C}$ — $\\texttt{MULDIVMOD}$ ($x$ $y$ $z$ -- $q$ $r$), where $q:=\\lfloor x\\cdot y/z\\rfloor$, $r:=x\\cdot y\\bmod z$ (same as $\\texttt{*/MOD}$ in Forth).\n- $\\texttt{A9A4}$ — $\\texttt{MULRSHIFT}$ ($x$ $y$ $z$ -- $\\lfloor xy\\cdot2^{-z}\\rfloor$) for $0\\leq z\\leq 256$.\n- $\\texttt{A9A5}$ — $\\texttt{MULRSHIFTR}$ ($x$ $y$ $z$ -- $\\lfloor xy\\cdot2^{-z}+1/2\\rfloor$) for $0\\leq z\\leq 256$.\n- $\\texttt{A9B4}tt$ — $\\texttt{MULRSHIFT}$ $tt+1$ ($x$ $y$ -- $\\lfloor xy\\cdot 2^{-tt-1}\\rfloor$).\n- $\\texttt{A9B5}tt$ — $\\texttt{MULRSHIFTR}$ $tt+1$ ($x$ $y$ -- $\\lfloor xy\\cdot 2^{-tt-1}+1/2\\rfloor$).\n- $\\texttt{A9C4}$ — $\\texttt{LSHIFTDIV}$ ($x$ $y$ $z$ -- $\\lfloor 2^zx/y\\rfloor$) for $0\\leq z\\leq 256$.\n- $\\texttt{A9C5}$ — $\\texttt{LSHIFTDIVR}$ ($x$ $y$ $z$ -- $\\lfloor 2^zx/y+1/2\\rfloor$) for $0\\leq z\\leq 256$.\n- $\\texttt{A9D4}tt$ — $\\texttt{LSHIFTDIV}$ $tt+1$ ($x$ $y$ -- $\\lfloor 2^{tt+1}x/y\\rfloor$).\n- $\\texttt{A9D5}tt$ — $\\texttt{LSHIFTDIVR}$ $tt+1$ ($x$ $y$ -- $\\lfloor 2^{tt+1}x/y+1/2\\rfloor$).\n\nThe most useful of these operations are $\\texttt{DIV}$, $\\texttt{DIVMOD}$, $\\texttt{MOD}$, $\\texttt{DIVR}$, $\\texttt{DIVC}$, $\\texttt{MODPOW2}$ $t$, and $\\texttt{RSHIFTR}$ $t$ (for integer arithmetic); and $\\texttt{MULDIVMOD}$, $\\texttt{MULDIV}$, $\\texttt{MULDIVR}$, $\\texttt{LSHIFTDIVR}$ $t$, and $\\texttt{MULRSHIFTR}$ $t$ (for fixed-point arithmetic).\n\n### A.5.3. Shifts, logical operations\n\n- $\\texttt{AA}cc$ — $\\texttt{LSHIFT}$ $cc+1$ ($x$ -- $x\\cdot2^{cc+1}$), $0\\leq cc\\leq255$.\n- $\\texttt{AA00}$ — $\\texttt{LSHIFT 1}$, equivalent to $\\texttt{MULCONST 2}$ or to Forth's $\\texttt{2*}$.\n- $\\texttt{AB}cc$ — $\\texttt{RSHIFT}$ $cc+1$ ($x$ -- $\\lfloor x\\cdot2^{-cc-1}\\rfloor$), $0\\leq cc\\leq255$.\n- $\\texttt{AC}$ — $\\texttt{LSHIFT}$ ($x$ $y$ -- $x\\cdot 2^y$), $0\\leq y\\leq 1023$.\n- $\\texttt{AD}$ — $\\texttt{RSHIFT}$ ($x$ $y$ -- $\\lfloor x\\cdot 2^{-y}\\rfloor$), $0\\leq y\\leq 1023$.\n- $\\texttt{AE}$ — $\\texttt{POW2}$ ($y$ -- $2^y$), $0\\leq y\\leq1023$, equivalent to $\\texttt{ONE}$; $\\texttt{SWAP}$; $\\texttt{LSHIFT}$.\n- $\\texttt{AF}$ — reserved.\n- $\\texttt{B0}$ — $\\texttt{AND}$ ($x$ $y$ -- $x\\&y$), bitwise \"and\" of two signed integers $x$ and $y$, sign-extended to infinity.\n- $\\texttt{B1}$ — $\\texttt{OR}$ ($x$ $y$ -- $x\\vee y$), bitwise \"or\" of two integers.\n- $\\texttt{B2}$ — $\\texttt{XOR}$ ($x$ $y$ -- $x\\oplus y$), bitwise \"xor\" of two integers.\n- $\\texttt{B3}$ — $\\texttt{NOT}$ ($x$ -- $x\\oplus-1=-1-x$), bitwise \"not\" of an integer.\n- $\\texttt{B4}cc$ — $\\texttt{FITS}$ $cc+1$ ($x$ -- $x$), checks whether $x$ is a $cc+1$-bit signed integer for $0\\leq cc\\leq 255$ (i.e., whether $-2^{cc}\\leq x<2^{cc}$). If not, either triggers an integer overflow exception, or replaces $x$ with a $\\texttt{NaN}$ (quiet version).\n- $\\texttt{B400}$ — $\\texttt{FITS 1}$ or $\\texttt{CHKBOOL}$ ($x$ -- $x$), checks whether $x$ is a \"boolean value\" (i.e., either 0 or -1).\n- $\\texttt{B5}cc$ — $\\texttt{UFITS}$ $cc+1$ ($x$ -- $x$), checks whether $x$ is a $cc+1$-bit unsigned integer for $0\\leq cc\\leq 255$ (i.e., whether $0\\leq x<2^{cc+1}$).\n- $\\texttt{B500}$ — $\\texttt{UFITS 1}$ or $\\texttt{CHKBIT}$, checks whether $x$ is a binary digit (i.e., zero or one).\n- $\\texttt{B600}$ — $\\texttt{FITSX}$ ($x$ $c$ -- $x$), checks whether $x$ is a $c$-bit signed integer for $0\\leq c\\leq 1023$.\n- $\\texttt{B601}$ — $\\texttt{UFITSX}$ ($x$ $c$ -- $x$), checks whether $x$ is a $c$-bit unsigned integer for $0\\leq c\\leq 1023$.\n- $\\texttt{B602}$ — $\\texttt{BITSIZE}$ ($x$ -- $c$), computes smallest $c\\geq0$ such that $x$ fits into a $c$-bit signed integer ($-2^{c-1}\\leq c<2^{c-1}$).\n- $\\texttt{B603}$ — $\\texttt{UBITSIZE}$ ($x$ -- $c$), computes smallest $c\\geq0$ such that $x$ fits into a $c$-bit unsigned integer ($0\\leq x<2^c$), or throws a range check exception.\n- $\\texttt{B608}$ — $\\texttt{MIN}$ ($x$ $y$ -- $x$ or $y$), computes the minimum of two integers $x$ and $y$.\n- $\\texttt{B609}$ — $\\texttt{MAX}$ ($x$ $y$ -- $x$ or $y$), computes the maximum of two integers $x$ and $y$.\n- $\\texttt{B60A}$ — $\\texttt{MINMAX}$ or $\\texttt{INTSORT2}$ ($x$ $y$ -- $x$ $y$ or $y$ $x$), sorts two integers. Quiet version of this operation returns two $\\texttt{NaN}$s if any of the arguments are $\\texttt{NaN}$s.\n- $\\texttt{B60B}$ — $\\texttt{ABS}$ ($x$ -- $|x|$), computes the absolute value of an integer $x$.\n\n### A.5.4. Quiet arithmetic primitives\n\nWe opted to make all arithmetic operations \"non-quiet\" (signaling) by default, and create their quiet counterparts by means of a prefix. Such an encoding is definitely sub-optimal. It is not yet clear whether it should be done in this way, or in the opposite way by making all arithmetic operations quiet by default, or whether quiet and non-quiet operations should be given opcodes of equal length; this can only be settled by practice.\n\n- $\\texttt{B7}xx$ — $\\texttt{QUIET}$ prefix, transforming any arithmetic operation into its \"quiet\" variant, indicated by prefixing a `Q` to its mnemonic. Such operations return $\\texttt{NaN}$s instead of throwing integer overflow exceptions if the results do not fit in *Integer*s, or if one of their arguments is a $\\texttt{NaN}$. Notice that this does not extend to shift amounts and other parameters that must be within a small range (e.g., 0--1023). Also notice that this does not disable type-checking exceptions if a value of a type other than *Integer* is supplied.\n- $\\texttt{B7A0}$ — $\\texttt{QADD}$ ($x$ $y$ -- $x+y$), always works if $x$ and $y$ are *Integer*s, but returns a $\\texttt{NaN}$ if the addition cannot be performed.\n- $\\texttt{B7A8}$ — $\\texttt{QMUL}$ ($x$ $y$ -- $xy$), returns the product of $x$ and $y$ if $-2^{256}\\leq xy<2^{256}$. Otherwise returns a $\\texttt{NaN}$, even if $x=0$ and $y$ is a $\\texttt{NaN}$.\n- $\\texttt{B7A904}$ — $\\texttt{QDIV}$ ($x$ $y$ -- $\\lfloor x/y\\rfloor$), returns a $\\texttt{NaN}$ if $y=0$, or if $y=-1$ and $x=-2^{256}$, or if either of $x$ or $y$ is a $\\texttt{NaN}$.\n- $\\texttt{B7A98C}$ — $\\texttt{QMULDIVMOD}$ ($x$ $y$ $z$ -- $q$ $r$), where $q:=\\lfloor x\\cdot y/z\\rfloor$, $r:=x\\cdot y\\bmod z$. If $z=0$, or if at least one of $x$, $y$, or $z$ is a $\\texttt{NaN}$, both $q$ and $r$ are set to $\\texttt{NaN}$. Otherwise the correct value of $r$ is always returned, but $q$ is replaced with $\\texttt{NaN}$ if $q<-2^{256}$ or $q\\geq2^{256}$.\n- $\\texttt{B7B0}$ — $\\texttt{QAND}$ ($x$ $y$ -- $x\\&y$), bitwise \"and\" (similar to $\\texttt{AND}$), but returns a $\\texttt{NaN}$ if either $x$ or $y$ is a $\\texttt{NaN}$ instead of throwing an integer overflow exception. However, if one of the arguments is zero, and the other is a $\\texttt{NaN}$, the result is zero.\n- $\\texttt{B7B1}$ — $\\texttt{QOR}$ ($x$ $y$ -- $x\\vee y$), bitwise \"or\". If $x=-1$ or $y=-1$, the result is always $-1$, even if the other argument is a $\\texttt{NaN}$.\n- $\\texttt{B7B507}$ — $\\texttt{QUFITS 8}$ ($x$ -- $x'$), checks whether $x$ is an unsigned byte (i.e., whether $0\\leq x<2^8$), and replaces $x$ with a $\\texttt{NaN}$ if this is not the case; leaves $x$ intact otherwise (i.e., if $x$ is an unsigned byte or a $\\texttt{NaN}$).\n\n## A.6  Comparison primitives\n\n### A.6.1. Integer comparison\n\nAll integer comparison primitives return integer $-1$ (\"true\") or $0$ (\"false\") to indicate the result of the comparison. We do not define their \"boolean circuit\" counterparts, which would transfer control to $\\texttt{c0}$ or $\\texttt{c1}$ depending on the result of the comparison. If needed, such instructions can be simulated with the aid of $\\texttt{RETBOOL}$.\n\nQuiet versions of integer comparison primitives are also available, encoded with the aid of the $\\texttt{QUIET}$ prefix ($\\texttt{B7}$). If any of the integers being compared are $\\texttt{NaN}$s, the result of a quiet comparison will also be a $\\texttt{NaN}$ (\"undefined\"), instead of a $-1$ (\"yes\") or $0$ (\"no\"), thus effectively supporting ternary logic.\n\n- $\\texttt{B8}$ — $\\texttt{SGN}$ ($x$ -- $\\text{sgn}(x)$), computes the sign of an integer $x$: $-1$ if $x<0$, $0$ if $x=0$, $1$ if $x>0$.\n- $\\texttt{B9}$ — $\\texttt{LESS}$ ($x$ $y$ -- $x<y$), returns $-1$ if $x<y$, $0$ otherwise.\n- $\\texttt{BA}$ — $\\texttt{EQUAL}$ ($x$ $y$ -- $x=y$), returns $-1$ if $x=y$, $0$ otherwise.\n- $\\texttt{BB}$ — $\\texttt{LEQ}$ ($x$ $y$ -- $x\\leq y$).\n- $\\texttt{BC}$ — $\\texttt{GREATER}$ ($x$ $y$ -- $x>y$).\n- $\\texttt{BD}$ — $\\texttt{NEQ}$ ($x$ $y$ -- $x\\neq y$), equivalent to $\\texttt{EQUAL}$; $\\texttt{NOT}$.\n- $\\texttt{BE}$ — $\\texttt{GEQ}$ ($x$ $y$ -- $x\\geq y$), equivalent to $\\texttt{LESS}$; $\\texttt{NOT}$.\n- $\\texttt{BF}$ — $\\texttt{CMP}$ ($x$ $y$ -- $\\text{sgn}(x-y)$), computes the sign of $x-y$: $-1$ if $x<y$, $0$ if $x=y$, $1$ if $x>y$. No integer overflow can occur here unless $x$ or $y$ is a $\\texttt{NaN}$.\n- $\\texttt{C0}yy$ — $\\texttt{EQINT}$ $yy$ ($x$ -- $x=yy$) for $-2^7\\leq yy<2^7$.\n- $\\texttt{C000}$ — $\\texttt{ISZERO}$, checks whether an integer is zero. Corresponds to Forth's $\\texttt{0=}$.\n- $\\texttt{C1}yy$ — $\\texttt{LESSINT}$ $yy$ ($x$ -- $x<yy$) for $-2^7\\leq yy<2^7$.\n- $\\texttt{C100}$ — $\\texttt{ISNEG}$, checks whether an integer is negative. Corresponds to Forth's $\\texttt{0<}$.\n- $\\texttt{C101}$ — $\\texttt{ISNPOS}$, checks whether an integer is non-positive.\n- $\\texttt{C2}yy$ — $\\texttt{GTINT}$ $yy$ ($x$ -- $x>yy$) for $-2^7\\leq yy<2^7$.\n- $\\texttt{C200}$ — $\\texttt{ISPOS}$, checks whether an integer is positive. Corresponds to Forth's $\\texttt{0>}$.\n- $\\texttt{C2FF}$ — $\\texttt{ISNNEG}$, checks whether an integer is non-negative.\n- $\\texttt{C3}yy$ — $\\texttt{NEQINT}$ $yy$ ($x$ -- $x\\neq yy$) for $-2^7\\leq yy<2^7$.\n- $\\texttt{C4}$ — $\\texttt{ISNAN}$ ($x$ -- $x=\\texttt{NaN}$), checks whether $x$ is a $\\texttt{NaN}$.\n- $\\texttt{C5}$ — $\\texttt{CHKNAN}$ ($x$ -- $x$), throws an arithmetic overflow exception if $x$ is a $\\texttt{NaN}$.\n- $\\texttt{C6}$ — reserved for integer comparison.\n\n### A.6.2. Other comparison\n\nMost of these \"other comparison\" primitives actually compare the data portions of *Slice*s as bitstrings.\n\n- $\\texttt{C700}$ — $\\texttt{SEMPTY}$ ($s$ -- $s=\\emptyset$), checks whether a *Slice* $s$ is empty (i.e., contains no bits of data and no cell references).\n- $\\texttt{C701}$ — $\\texttt{SDEMPTY}$ ($s$ -- $s\\approx\\emptyset$), checks whether *Slice* $s$ has no bits of data.\n- $\\texttt{C702}$ — $\\texttt{SREMPTY}$ ($s$ -- $r(s)=0$), checks whether *Slice* $s$ has no references.\n- $\\texttt{C703}$ — $\\texttt{SDFIRST}$ ($s$ -- $s_0=1$), checks whether the first bit of *Slice* $s$ is a one.\n- $\\texttt{C704}$ — $\\texttt{SDLEXCMP}$ ($s$ $s'$ -- $c$), compares the data of $s$ lexicographically with the data of $s'$, returning $-1$, 0, or 1 depending on the result.\n- $\\texttt{C705}$ — $\\texttt{SDEQ}$ ($s$ $s'$ -- $s\\approx s'$), checks whether the data parts of $s$ and $s'$ coincide, equivalent to $\\texttt{SDLEXCMP}$; $\\texttt{ISZERO}$.\n- $\\texttt{C708}$ — $\\texttt{SDPFX}$ ($s$ $s'$ -- $?$), checks whether $s$ is a prefix of $s'$.\n- $\\texttt{C709}$ — $\\texttt{SDPFXREV}$ ($s$ $s'$ -- $?$), checks whether $s'$ is a prefix of $s$, equivalent to $\\texttt{SWAP}$; $\\texttt{SDPFX}$.\n- $\\texttt{C70A}$ — $\\texttt{SDPPFX}$ ($s$ $s'$ -- $?$), checks whether $s$ is a proper prefix of $s'$ (i.e., a prefix distinct from $s'$).\n- $\\texttt{C70B}$ — $\\texttt{SDPPFXREV}$ ($s$ $s'$ -- $?$), checks whether $s'$ is a proper prefix of $s$.\n- $\\texttt{C70C}$ — $\\texttt{SDSFX}$ ($s$ $s'$ -- $?$), checks whether $s$ is a suffix of $s'$.\n- $\\texttt{C70D}$ — $\\texttt{SDSFXREV}$ ($s$ $s'$ -- $?$), checks whether $s'$ is a suffix of $s$.\n- $\\texttt{C70E}$ — $\\texttt{SDPSFX}$ ($s$ $s'$ -- $?$), checks whether $s$ is a proper suffix of $s'$.\n- $\\texttt{C70F}$ — $\\texttt{SDPSFXREV}$ ($s$ $s'$ -- $?$), checks whether $s'$ is a proper suffix of $s$.\n- $\\texttt{C710}$ — $\\texttt{SDCNTLEAD0}$ ($s$ -- $n$), returns the number of leading zeroes in $s$.\n- $\\texttt{C711}$ — $\\texttt{SDCNTLEAD1}$ ($s$ -- $n$), returns the number of leading ones in $s$.\n- $\\texttt{C712}$ — $\\texttt{SDCNTTRAIL0}$ ($s$ -- $n$), returns the number of trailing zeroes in $s$.\n- $\\texttt{C713}$ — $\\texttt{SDCNTTRAIL1}$ ($s$ -- $n$), returns the number of trailing ones in $s$.\n\n## A.7 Cell primitives\n\nThe cell primitives are mostly either *cell serialization primitives*, which work with *Builder*s, or *cell deserialization primitives*, which work with *Slice*s.\n\n### A.7.1. Cell serialization primitives\n\nAll these primitives first check whether there is enough space in the Builder, and only then check the range of the value being serialized.\n\n- $\\texttt{C8}$ — $\\texttt{NEWC}$ ( -- $b$), creates a new empty *Builder*.\n- $\\texttt{C9}$ — $\\texttt{ENDC}$ ($b$ -- $c$), converts a *Builder* into an ordinary *Cell*.\n- $\\texttt{CA}cc$ — $\\texttt{STI}$ $cc+1$ ($x$ $b$ -- $b'$), stores a signed $cc+1$-bit integer $x$ into *Builder* $b$ for $0\\leq cc\\leq 255$, throws a range check exception if $x$ does not fit into $cc+1$ bits.\n- $\\texttt{CB}cc$ — $\\texttt{STU}$ $cc+1$ ($x$ $b$ -- $b'$), stores an unsigned $cc+1$-bit integer $x$ into *Builder* $b$. In all other respects it is similar to $\\texttt{STI}$.\n- $\\texttt{CC}$ — $\\texttt{STREF}$ ($c$ $b$ -- $b'$), stores a reference to *Cell* $c$ into *Builder* $b$.\n- $\\texttt{CD}$ — $\\texttt{STBREFR}$ or $\\texttt{ENDCST}$ ($b$ $b''$ -- $b$), equivalent to $\\texttt{ENDC}$; $\\texttt{SWAP}$; $\\texttt{STREF}$.\n- $\\texttt{CE}$ — $\\texttt{STSLICE}$ ($s$ $b$ -- $b'$), stores *Slice* $s$ into *Builder* $b$.\n- $\\texttt{CF00}$ — $\\texttt{STIX}$ ($x$ $b$ $l$ -- $b'$), stores a signed $l$-bit integer $x$ into $b$ for $0\\leq l\\leq 257$.\n- $\\texttt{CF01}$ — $\\texttt{STUX}$ ($x$ $b$ $l$ -- $b'$), stores an unsigned $l$-bit integer $x$ into $b$ for $0\\leq l\\leq 256$.\n- $\\texttt{CF02}$ — $\\texttt{STIXR}$ ($b$ $x$ $l$ -- $b'$), similar to $\\texttt{STIX}$, but with arguments in a different order.\n- $\\texttt{CF03}$ — $\\texttt{STUXR}$ ($b$ $x$ $l$ -- $b'$), similar to $\\texttt{STUX}$, but with arguments in a different order.\n- $\\texttt{CF04}$ — $\\texttt{STIXQ}$ ($x$ $b$ $l$ -- $x$ $b$ $f$ or $b'$ $0$), a quiet version of $\\texttt{STIX}$. If there is no space in $b$, sets $b'=b$ and $f=-1$. If $x$ does not fit into $l$ bits, sets $b'=b$ and $f=1$. If the operation succeeds, $b'$ is the new *Builder* and $f=0$. However, $0\\leq l\\leq 257$, with a range check exception if this is not so.\n- $\\texttt{CF05}$ — $\\texttt{STUXQ}$ ($x$ $b$ $l$ -- $b'$ $f$).\n- $\\texttt{CF06}$ — $\\texttt{STIXRQ}$ ($b$ $x$ $l$ -- $b$ $x$ $f$ or $b'$ $0$).\n- $\\texttt{CF07}$ — $\\texttt{STUXRQ}$ ($b$ $x$ $l$ -- $b$ $x$ $f$ or $b'$ $0$).\n- $\\texttt{CF08}cc$ — a longer version of $\\texttt{STI}$ $cc+1$.\n- $\\texttt{CF09}cc$ — a longer version of $\\texttt{STU}$ $cc+1$.\n- $\\texttt{CF0A}cc$ — $\\texttt{STIR}$ $cc+1$ ($b$ $x$ -- $b'$), equivalent to $\\texttt{SWAP}$; $\\texttt{STI}$ $cc+1$.\n- $\\texttt{CF0B}cc$ — $\\texttt{STUR}$ $cc+1$ ($b$ $x$ -- $b'$), equivalent to $\\texttt{SWAP}$; $\\texttt{STU}$ $cc+1$.\n- $\\texttt{CF0C}cc$ — $\\texttt{STIQ}$ $cc+1$ ($x$ $b$ -- $x$ $b$ $f$ or $b'$ $0$).\n- $\\texttt{CF0D}cc$ — $\\texttt{STUQ}$ $cc+1$ ($x$ $b$ -- $x$ $b$ $f$ or $b'$ $0$).\n- $\\texttt{CF0E}cc$ — $\\texttt{STIRQ}$ $cc+1$ ($b$ $x$ -- $b$ $x$ $f$ or $b'$ $0$).\n- $\\texttt{CF0F}cc$ — $\\texttt{STURQ}$ $cc+1$ ($b$ $x$ -- $b$ $x$ $f$ or $b'$ $0$).\n- $\\texttt{CF10}$ — a longer version of $\\texttt{STREF}$ ($c$ $b$ -- $b'$).\n- $\\texttt{CF11}$ — $\\texttt{STBREF}$ ($b'$ $b$ -- $b''$), equivalent to $\\texttt{SWAP}$; $\\texttt{STBREFREV}$.\n- $\\texttt{CF12}$ — a longer version of $\\texttt{STSLICE}$ ($s$ $b$ -- $b'$).\n- $\\texttt{CF13}$ — $\\texttt{STB}$ ($b'$ $b$ -- $b''$), appends all data from *Builder* $b'$ to *Builder* $b$.\n- $\\texttt{CF14}$ — $\\texttt{STREFR}$ ($b$ $c$ -- $b'$).\n- $\\texttt{CF15}$ — $\\texttt{STBREFR}$ ($b$ $b'$ -- $b''$), a longer encoding of $\\texttt{STBREFR}$.\n- $\\texttt{CF16}$ — $\\texttt{STSLICER}$ ($b$ $s$ -- $b'$).\n- $\\texttt{CF17}$ — $\\texttt{STBR}$ ($b$ $b'$ -- $b''$), concatenates two *Builder*s, equivalent to $\\texttt{SWAP}$; $\\texttt{STB}$.\n- $\\texttt{CF18}$ — $\\texttt{STREFQ}$ ($c$ $b$ -- $c$ $b$ $-1$ or $b'$ $0$).\n- $\\texttt{CF19}$ — $\\texttt{STBREFQ}$ ($b'$ $b$ -- $b'$ $b$ $-1$ or $b''$ $0$).\n- $\\texttt{CF1A}$ — $\\texttt{STSLICEQ}$ ($s$ $b$ -- $s$ $b$ $-1$ or $b'$ $0$).\n- $\\texttt{CF1B}$ — $\\texttt{STBQ}$ ($b'$ $b$ -- $b'$ $b$ $-1$ or $b''$ $0$).\n- $\\texttt{CF1C}$ — $\\texttt{STREFRQ}$ ($b$ $c$ -- $b$ $c$ $-1$ or $b'$ $0$).\n- $\\texttt{CF1D}$ — $\\texttt{STBREFRQ}$ ($b$ $b'$ -- $b$ $b'$ $-1$ or $b''$ $0$).\n- $\\texttt{CF1E}$ — $\\texttt{STSLICERQ}$ ($b$ $s$ -- $b$ $s$ $-1$ or $b''$ $0$).\n- $\\texttt{CF1F}$ — $\\texttt{STBRQ}$ ($b$ $b'$ -- $b$ $b'$ $-1$ or $b''$ $0$).\n- $\\texttt{CF20}$ — $\\texttt{STREFCONST}$, equivalent to $\\texttt{PUSHREF}$; $\\texttt{STREFR}$.\n- $\\texttt{CF21}$ — $\\texttt{STREF2CONST}$, equivalent to $\\texttt{STREFCONST}$; $\\texttt{STREFCONST}$.\n- $\\texttt{CF23}$ — $\\texttt{ENDXC}$ ($b$ $x$ -- $c$), if $x\\neq0$, creates a *special* or [exotic cell](#3-1-2-ordinary-and-exotic-cells) from *Builder* $b$. The type of the exotic cell must be stored in the first 8 bits of $b$. If $x=0$, it is equivalent to $\\texttt{ENDC}$. Otherwise some validity checks on the data and references of $b$ are performed before creating the exotic cell.\n- $\\texttt{CF28}$ — $\\texttt{STILE4}$ ($x$ $b$ -- $b'$), stores a little-endian signed 32-bit integer.\n- $\\texttt{CF29}$ — $\\texttt{STULE4}$ ($x$ $b$ -- $b'$), stores a little-endian unsigned 32-bit integer.\n- $\\texttt{CF2A}$ — $\\texttt{STILE8}$ ($x$ $b$ -- $b'$), stores a little-endian signed 64-bit integer.\n- $\\texttt{CF2B}$ — $\\texttt{STULE8}$ ($x$ $b$ -- $b'$), stores a little-endian unsigned 64-bit integer.\n- $\\texttt{CF30}$ — $\\texttt{BDEPTH}$ ($b$ -- $x$), returns the depth of *Builder* $b$. If no cell references are stored in $b$, then $x=0$; otherwise $x$ is one plus the maximum of depths of cells referred to from $b$.\n- $\\texttt{CF31}$ — $\\texttt{BBITS}$ ($b$ -- $x$), returns the number of data bits already stored in *Builder* $b$.\n- $\\texttt{CF32}$ — $\\texttt{BREFS}$ ($b$ -- $y$), returns the number of cell references already stored in $b$.\n- $\\texttt{CF33}$ — $\\texttt{BBITREFS}$ ($b$ -- $x$ $y$), returns the numbers of both data bits and cell references in $b$.\n- $\\texttt{CF35}$ — $\\texttt{BREMBITS}$ ($b$ -- $x'$), returns the number of data bits that can still be stored in $b$.\n- $\\texttt{CF36}$ — $\\texttt{BREMREFS}$ ($b$ -- $y'$).\n- $\\texttt{CF37}$ — $\\texttt{BREMBITREFS}$ ($b$ -- $x'$ $y'$).\n- $\\texttt{CF38}cc$ — $\\texttt{BCHKBITS}$ $cc+1$ ($b$ --), checks whether $cc+1$ bits can be stored into $b$, where $0\\leq cc\\leq 255$.\n- $\\texttt{CF39}$ — $\\texttt{BCHKBITS}$ ($b$ $x$ -- ), checks whether $x$ bits can be stored into $b$, $0\\leq x\\leq 1023$. If there is no space for $x$ more bits in $b$, or if $x$ is not within the range $0\\ldots1023$, throws an exception.\n- $\\texttt{CF3A}$ — $\\texttt{BCHKREFS}$ ($b$ $y$ -- ), checks whether $y$ references can be stored into $b$, $0\\leq y\\leq 7$.\n- $\\texttt{CF3B}$ — $\\texttt{BCHKBITREFS}$ ($b$ $x$ $y$ -- ), checks whether $x$ bits and $y$ references can be stored into $b$, $0\\leq x\\leq 1023$, $0\\leq y\\leq 7$.\n- $\\texttt{CF3C}cc$ — $\\texttt{BCHKBITSQ}$ $cc+1$ ($b$ -- $?$), checks whether $cc+1$ bits can be stored into $b$, where $0\\leq cc\\leq 255$.\n- $\\texttt{CF3D}$ — $\\texttt{BCHKBITSQ}$ ($b$ $x$ -- $?$), checks whether $x$ bits can be stored into $b$, $0\\leq x\\leq 1023$.\n- $\\texttt{CF3E}$ — $\\texttt{BCHKREFSQ}$ ($b$ $y$ -- $?$), checks whether $y$ references can be stored into $b$, $0\\leq y\\leq 7$.\n- $\\texttt{CF3F}$ — $\\texttt{BCHKBITREFSQ}$ ($b$ $x$ $y$ -- $?$), checks whether $x$ bits and $y$ references can be stored into $b$, $0\\leq x\\leq 1023$, $0\\leq y\\leq 7$.\n- $\\texttt{CF40}$ — $\\texttt{STZEROES}$ ($b$ $n$ -- $b'$), stores $n$ binary zeroes into *Builder* $b$.\n- $\\texttt{CF41}$ — $\\texttt{STONES}$ ($b$ $n$ -- $b'$), stores $n$ binary ones into *Builder* $b$.\n- $\\texttt{CF42}$ — $\\texttt{STSAME}$ ($b$ $n$ $x$ -- $b'$), stores $n$ binary $x$es ($0\\leq x\\leq1$) into *Builder* $b$.\n- $\\texttt{CFC0\\_xysss}$ — $\\texttt{STSLICECONST}$ $sss$ ($b$ -- $b'$), stores a constant subslice $sss$ consisting of $0\\leq x\\leq 3$ references and up to $8y+1$ data bits, with $0\\leq y\\leq 7$. Completion bit is assumed.\n- $\\texttt{CF81}$ — $\\texttt{STSLICECONST '0'}$ or $\\texttt{STZERO}$ ($b$ -- $b'$), stores one binary zero.\n- $\\texttt{CF83}$ — $\\texttt{STSLICECONST '1'}$ or $\\texttt{STONE}$ ($b$ -- $b'$), stores one binary one.\n- $\\texttt{CFA2}$ — equivalent to $\\texttt{STREFCONST}$.\n- $\\texttt{CFA3}$ — almost equivalent to $\\texttt{STSLICECONST '1'}$; $\\texttt{STREFCONST}$.\n- $\\texttt{CFC2}$ — equivalent to $\\texttt{STREF2CONST}$.\n- $\\texttt{CFE2}$ — $\\texttt{STREF3CONST}$.\n\n### A.7.2. Cell deserialization primitives\n\n- $\\texttt{D0}$ — $\\texttt{CTOS}$ ($c$ -- $s$), converts a *Cell* into a *Slice*. Notice that $c$ must be either an ordinary cell, or an [exotic cell](#3-1-2-ordinary-and-exotic-cells) which is automatically *loaded* to yield an ordinary cell $c'$, converted into a *Slice* afterwards.\n- $\\texttt{D1}$ — $\\texttt{ENDS}$ ($s$ -- ), removes a *Slice* $s$ from the stack, and throws an exception if it is not empty.\n- $\\texttt{D2}$ $cc$ — $\\texttt{LDI}$ $cc+1$ ($s$ -- $x$ $s'$), loads (i.e., parses) a signed $cc+1$-bit integer $x$ from *Slice* $s$, and returns the remainder of $s$ as $s'$.\n- $\\texttt{D3}$ $cc$ — $\\texttt{LDU}$ $cc+1$ ($s$ -- $x$ $s'$), loads an unsigned $cc+1$-bit integer $x$ from *Slice* $s$.\n- $\\texttt{D4}$ — $\\texttt{LDREF}$ ($s$ -- $c$ $s'$), loads a cell reference $c$ from $s$.\n- $\\texttt{D5}$ — $\\texttt{LDREFRTOS}$ ($s$ -- $s'$ $s''$), equivalent to $\\texttt{LDREF}$; $\\texttt{SWAP}$; $\\texttt{CTOS}$.\n- $\\texttt{D6}$ $cc$ — $\\texttt{LDSLICE}$ $cc+1$ ($s$ -- $s''$ $s'$), cuts the next $cc+1$ bits of $s$ into a separate *Slice* $s''$.\n- $\\texttt{D700}$ — $\\texttt{LDIX}$ ($s$ $l$ -- $x$ $s'$), loads a signed $l$-bit ($0\\leq l\\leq 257$) integer $x$ from *Slice* $s$, and returns the remainder of $s$ as $s'$.\n- $\\texttt{D701}$ — $\\texttt{LDUX}$ ($s$ $l$ -- $x$ $s'$), loads an unsigned $l$-bit integer $x$ from (the first $l$ bits of) $s$, with $0\\leq l\\leq 256$.\n- $\\texttt{D702}$ — $\\texttt{PLDIX}$ ($s$ $l$ -- $x$), preloads a signed $l$-bit integer from *Slice* $s$, for $0\\leq l\\leq 257$.\n- $\\texttt{D703}$ — $\\texttt{PLDUX}$ ($s$ $l$ -- $x$), preloads an unsigned $l$-bit integer from $s$, for $0\\leq l\\leq 256$.\n- $\\texttt{D704}$ — $\\texttt{LDIXQ}$ ($s$ $l$ -- $x$ $s'$ $-1$ or $s$ $0$), quiet version of $\\texttt{LDIX}$: loads a signed $l$-bit integer from $s$ similarly to $\\texttt{LDIX}$, but returns a success flag, equal to $-1$ on success or to $0$ on failure (if $s$ does not have $l$ bits), instead of throwing a cell underflow exception.\n- $\\texttt{D705}$ — $\\texttt{LDUXQ}$ ($s$ $l$ -- $x$ $s'$ $-1$ or $s$ $0$), quiet version of $\\texttt{LDUX}$.\n- $\\texttt{D706}$ — $\\texttt{PLDIXQ}$ ($s$ $l$ -- $x$ $-1$ or $0$), quiet version of $\\texttt{PLDIX}$.\n- $\\texttt{D707}$ — $\\texttt{PLDUXQ}$ ($s$ $l$ -- $x$ $-1$ or $0$), quiet version of $\\texttt{PLDUX}$.\n- $\\texttt{D708}$ $cc$ — $\\texttt{LDI}$ $cc+1$ ($s$ -- $x$ $s'$), a longer encoding for $\\texttt{LDI}$.\n- $\\texttt{D709}$ $cc$ — $\\texttt{LDU}$ $cc+1$ ($s$ -- $x$ $s'$), a longer encoding for $\\texttt{LDU}$.\n- $\\texttt{D70A}$ $cc$ — $\\texttt{PLDI}$ $cc+1$ ($s$ -- $x$), preloads a signed $cc+1$-bit integer from *Slice* $s$.\n- $\\texttt{D70B}$ $cc$ — $\\texttt{PLDU}$ $cc+1$ ($s$ -- $x$), preloads an unsigned $cc+1$-bit integer from $s$.\n- $\\texttt{D70C}$ $cc$ — $\\texttt{LDIQ}$ $cc+1$ ($s$ -- $x$ $s'$ $-1$ or $s$ $0$), a quiet version of $\\texttt{LDI}$.\n- $\\texttt{D70D}$ $cc$ — $\\texttt{LDUQ}$ $cc+1$ ($s$ -- $x$ $s'$ $-1$ or $s$ $0$), a quiet version of $\\texttt{LDU}$.\n- $\\texttt{D70E}$ $cc$ — $\\texttt{PLDIQ}$ $cc+1$ ($s$ -- $x$ $-1$ or $0$), a quiet version of $\\texttt{PLDI}$.\n- $\\texttt{D70F}$ $cc$ — $\\texttt{PLDUQ}$ $cc+1$ ($s$ -- $x$ $-1$ or $0$), a quiet version of $\\texttt{PLDU}$.\n- $\\texttt{D714\\_}c$ — $\\texttt{PLDUZ}$ $32(c+1)$ ($s$ -- $s$ $x$), preloads the first $32(c+1)$ bits of *Slice* $s$ into an unsigned integer $x$, for $0\\leq c\\leq 7$. If $s$ is shorter than necessary, missing bits are assumed to be zero. This operation is intended to be used along with $\\texttt{IFBITJMP}$ and similar instructions.\n- $\\texttt{D718}$ — $\\texttt{LDSLICEX}$ ($s$ $l$ -- $s''$ $s'$), loads the first $0\\leq l\\leq 1023$ bits from *Slice* $s$ into a separate *Slice* $s''$, returning the remainder of $s$ as $s'$.\n- $\\texttt{D719}$ — $\\texttt{PLDSLICEX}$ ($s$ $l$ -- $s''$), returns the first $0\\leq l\\leq 1023$ bits of $s$ as $s''$.\n- $\\texttt{D71A}$ — $\\texttt{LDSLICEXQ}$ ($s$ $l$ -- $s''$ $s'$ $-1$ or $s$ $0$), a quiet version of $\\texttt{LDSLICEX}$.\n- $\\texttt{D71B}$ — $\\texttt{PLDSLICEXQ}$ ($s$ $l$ -- $s'$ $-1$ or $0$), a quiet version of $\\texttt{LDSLICEXQ}$.\n- $\\texttt{D71C}$ $cc$ — $\\texttt{LDSLICE}$ $cc+1$ ($s$ -- $s''$ $s'$), a longer encoding for $\\texttt{LDSLICE}$.\n- $\\texttt{D71D}$ $cc$ — $\\texttt{PLDSLICE}$ $cc+1$ ($s$ -- $s''$), returns the first $0<cc+1\\leq 256$ bits of $s$ as $s''$.\n- $\\texttt{D71E}$ $cc$ — $\\texttt{LDSLICEQ}$ $cc+1$ ($s$ -- $s''$ $s'$ $-1$ or $s$ $0$), a quiet version of $\\texttt{LDSLICE}$.\n- $\\texttt{D71F}$ $cc$ — $\\texttt{PLDSLICEQ}$ $cc+1$ ($s$ -- $s''$ $-1$ or $0$), a quiet version of $\\texttt{PLDSLICE}$.\n- $\\texttt{D720}$ — $\\texttt{SDCUTFIRST}$ ($s$ $l$ -- $s'$), returns the first $0\\leq l\\leq 1023$ bits of $s$. It is equivalent to $\\texttt{PLDSLICEX}$.\n- $\\texttt{D721}$ — $\\texttt{SDSKIPFIRST}$ ($s$ $l$ -- $s'$), returns all but the first $0\\leq l\\leq 1023$ bits of $s$. It is equivalent to $\\texttt{LDSLICEX}$; $\\texttt{NIP}$.\n- $\\texttt{D722}$ — $\\texttt{SDCUTLAST}$ ($s$ $l$ -- $s'$), returns the last $0\\leq l\\leq 1023$ bits of $s$.\n- $\\texttt{D723}$ — $\\texttt{SDSKIPLAST}$ ($s$ $l$ -- $s'$), returns all but the last $0\\leq l\\leq 1023$ bits of $s$.\n- $\\texttt{D724}$ — $\\texttt{SDSUBSTR}$ ($s$ $l$ $l'$ -- $s'$), returns $0\\leq l'\\leq 1023$ bits of $s$ starting from offset $0\\leq l\\leq 1023$, thus extracting a bit substring out of the data of $s$.\n- $\\texttt{D726}$ — $\\texttt{SDBEGINSX}$ ($s$ $s'$ -- $s''$), checks whether $s$ begins with (the data bits of) $s'$, and removes $s'$ from $s$ on success. On failure throws a cell deserialization exception. Primitive $\\texttt{SDPFXREV}$ can be considered a quiet version of $\\texttt{SDBEGINSX}$.\n- $\\texttt{D727}$ — $\\texttt{SDBEGINSXQ}$ ($s$ $s'$ -- $s''$ $-1$ or $s$ $0$), a quiet version of $\\texttt{SDBEGINSX}$.\n- $\\texttt{D72A\\_}xsss$ — $\\texttt{SDBEGINS}$ ($s$ -- $s''$), checks whether $s$ begins with constant bitstring $sss$ of length $8x+3$ (with continuation bit assumed), where $0\\leq x\\leq 127$, and removes $sss$ from $s$ on success.\n- $\\texttt{D72802}$ — $\\texttt{SDBEGINS '0'}$ ($s$ -- $s''$), checks whether $s$ begins with a binary zero.\n- $\\texttt{D72806}$ — $\\texttt{SDBEGINS '1'}$ ($s$ -- $s''$), checks whether $s$ begins with a binary one.\n- $\\texttt{D72E\\_}xsss$ — $\\texttt{SDBEGINSQ}$ ($s$ -- $s''$ $-1$ or $s$ $0$), a quiet version of $\\texttt{SDBEGINS}$.\n- $\\texttt{D730}$ — $\\texttt{SCUTFIRST}$ ($s$ $l$ $r$ -- $s'$), returns the first $0\\leq l\\leq 1023$ bits and first $0\\leq r\\leq 4$ references of $s$.\n- $\\texttt{D731}$ — $\\texttt{SSKIPFIRST}$ ($s$ $l$ $r$ -- $s'$).\n- $\\texttt{D732}$ — $\\texttt{SCUTLAST}$ ($s$ $l$ $r$ -- $s'$), returns the last $0\\leq l\\leq 1023$ data bits and last $0\\leq r\\leq 4$ references of $s$.\n- $\\texttt{D733}$ — $\\texttt{SSKIPLAST}$ ($s$ $l$ $r$ -- $s'$).\n- $\\texttt{D734}$ — $\\texttt{SUBSLICE}$ ($s$ $l$ $r$ $l'$ $r'$ -- $s'$), returns $0\\leq l'\\leq 1023$ bits and $0\\leq r'\\leq 4$ references from *Slice* $s$, after skipping the first $0\\leq l\\leq 1023$ bits and first $0\\leq r\\leq 4$ references.\n- $\\texttt{D736}$ — $\\texttt{SPLIT}$ ($s$ $l$ $r$ -- $s'$ $s''$), splits the first $0\\leq l\\leq 1023$ data bits and first $0\\leq r\\leq 4$ references from $s$ into $s'$, returning the remainder of $s$ as $s''$.\n- $\\texttt{D737}$ — $\\texttt{SPLITQ}$ ($s$ $l$ $r$ -- $s'$ $s''$ $-1$ or $s$ $0$), a quiet version of $\\texttt{SPLIT}$.\n- $\\texttt{D739}$ — $\\texttt{XCTOS}$ ($c$ -- $s$ $?$), transforms an ordinary or exotic cell into a *Slice*, as if it were an ordinary cell. A flag is returned indicating whether $c$ is exotic. If that be the case, its type can later be deserialized from the first eight bits of $s$.\n- $\\texttt{D73A}$ — $\\texttt{XLOAD}$ ($c$ -- $c'$), loads an exotic cell $c$ and returns an ordinary cell $c'$. If $c$ is already ordinary, does nothing. If $c$ cannot be loaded, throws an exception.\n- $\\texttt{D73B}$ — $\\texttt{XLOADQ}$ ($c$ -- $c'$ $-1$ or $c$ $0$), loads an exotic cell $c$ as $\\texttt{XLOAD}$, but returns 0 on failure.\n- $\\texttt{D741}$ — $\\texttt{SCHKBITS}$ ($s$ $l$ -- ), checks whether there are at least $l$ data bits in *Slice* $s$. If this is not the case, throws a cell deserialisation (i.e., cell underflow) exception.\n- $\\texttt{D742}$ — $\\texttt{SCHKREFS}$ ($s$ $r$ -- ), checks whether there are at least $r$ references in *Slice* $s$.\n- $\\texttt{D743}$ — $\\texttt{SCHKBITREFS}$ ($s$ $l$ $r$ -- ), checks whether there are at least $l$ data bits and $r$ references in *Slice* $s$.\n- $\\texttt{D745}$ — $\\texttt{SCHKBITSQ}$ ($s$ $l$ -- $?$), checks whether there are at least $l$ data bits in *Slice* $s$.\n- $\\texttt{D746}$ — $\\texttt{SCHKREFSQ}$ ($s$ $r$ -- $?$), checks whether there are at least $r$ references in *Slice* $s$.\n- $\\texttt{D747}$ — $\\texttt{SCHKBITREFSQ}$ ($s$ $l$ $r$ -- $?$), checks whether there are at least $l$ data bits and $r$ references in *Slice* $s$.\n- $\\texttt{D748}$ — $\\texttt{PLDREFVAR}$ ($s$ $n$ -- $c$), returns the $n$-th cell reference of *Slice* $s$ for $0\\leq n\\leq 3$.\n- $\\texttt{D749}$ — $\\texttt{SBITS}$ ($s$ -- $l$), returns the number of data bits in *Slice* $s$.\n- $\\texttt{D74A}$ — $\\texttt{SREFS}$ ($s$ -- $r$), returns the number of references in *Slice* $s$.\n- $\\texttt{D74B}$ — $\\texttt{SBITREFS}$ ($s$ -- $l$ $r$), returns both the number of data bits and the number of references in $s$.\n- $\\texttt{D74E\\_}n$ — $\\texttt{PLDREFIDX}$ $n$ ($s$ -- $c$), returns the $n$-th cell reference of *Slice* $s$, where $0\\leq n\\leq 3$.\n- $\\texttt{D74C}$ — $\\texttt{PLDREF}$ ($s$ -- $c$), preloads the first cell reference of a *Slice*.\n- $\\texttt{D750}$ — $\\texttt{LDILE4}$ ($s$ -- $x$ $s'$), loads a little-endian signed 32-bit integer.\n- $\\texttt{D751}$ — $\\texttt{LDULE4}$ ($s$ -- $x$ $s'$), loads a little-endian unsigned 32-bit integer.\n- $\\texttt{D752}$ — $\\texttt{LDILE8}$ ($s$ -- $x$ $s'$), loads a little-endian signed 64-bit integer.\n- $\\texttt{D753}$ — $\\texttt{LDULE8}$ ($s$ -- $x$ $s'$), loads a little-endian unsigned 64-bit integer.\n- $\\texttt{D754}$ — $\\texttt{PLDILE4}$ ($s$ -- $x$), preloads a little-endian signed 32-bit integer.\n- $\\texttt{D755}$ — $\\texttt{PLDULE4}$ ($s$ -- $x$), preloads a little-endian unsigned 32-bit integer.\n- $\\texttt{D756}$ — $\\texttt{PLDILE8}$ ($s$ -- $x$), preloads a little-endian signed 64-bit integer.\n- $\\texttt{D757}$ — $\\texttt{PLDULE8}$ ($s$ -- $x$), preloads a little-endian unsigned 64-bit integer.\n- $\\texttt{D758}$ — $\\texttt{LDILE4Q}$ ($s$ -- $x$ $s'$ $-1$ or $s$ $0$), quietly loads a little-endian signed 32-bit integer.\n- $\\texttt{D759}$ — $\\texttt{LDULE4Q}$ ($s$ -- $x$ $s'$ $-1$ or $s$ $0$), quietly loads a little-endian unsigned 32-bit integer.\n- $\\texttt{D75A}$ — $\\texttt{LDILE8Q}$ ($s$ -- $x$ $s'$ $-1$ or $s$ $0$), quietly loads a little-endian signed 64-bit integer.\n- $\\texttt{D75B}$ — $\\texttt{LDULE8Q}$ ($s$ -- $x$ $s'$ $-1$ or $s$ $0$), quietly loads a little-endian unsigned 64-bit integer.\n- $\\texttt{D75C}$ — $\\texttt{PLDILE4Q}$ ($s$ -- $x$ $-1$ or $0$), quietly preloads a little-endian signed 32-bit integer.\n- $\\texttt{D75D}$ — $\\texttt{PLDULE4Q}$ ($s$ -- $x$ $-1$ or $0$), quietly preloads a little-endian unsigned 32-bit integer.\n- $\\texttt{D75E}$ — $\\texttt{PLDILE8Q}$ ($s$ -- $x$ $-1$ or $0$), quietly preloads a little-endian signed 64-bit integer.\n- $\\texttt{D75F}$ — $\\texttt{PLDULE8Q}$ ($s$ -- $x$ $-1$ or $0$), quietly preloads a little-endian unsigned 64-bit integer.\n- $\\texttt{D760}$ — $\\texttt{LDZEROES}$ ($s$ -- $n$ $s'$), returns the count $n$ of leading zero bits in $s$, and removes these bits from $s$.\n- $\\texttt{D761}$ — $\\texttt{LDONES}$ ($s$ -- $n$ $s'$), returns the count $n$ of leading one bits in $s$, and removes these bits from $s$.\n- $\\texttt{D762}$ — $\\texttt{LDSAME}$ ($s$ $x$ -- $n$ $s'$), returns the count $n$ of leading bits equal to $0\\leq x\\leq 1$ in $s$, and removes these bits from $s$.\n- $\\texttt{D764}$ — $\\texttt{SDEPTH}$ ($s$ -- $x$), returns the depth of *Slice* $s$. If $s$ has no references, then $x=0$; otherwise $x$ is one plus the maximum of depths of cells referred to from $s$.\n- $\\texttt{D765}$ — $\\texttt{CDEPTH}$ ($c$ -- $x$), returns the depth of *Cell* $c$. If $c$ has no references, then $x=0$; otherwise $x$ is one plus the maximum of depths of cells referred to from $c$. If $c$ is a *Null* instead of a *Cell*, returns zero.\n\n## A.8  Continuation and control flow primitives\n\n### A.8.1. Unconditional control flow primitives\n\n- $\\texttt{D8}$ — $\\texttt{EXECUTE}$ or $\\texttt{CALLX}$ ($c$ - ), *calls* or *executes* continuation $c$ (i.e., $\\texttt{cc}\\leftarrow c\\circ_0\\texttt{cc}$).\n- $\\texttt{D9}$ — $\\texttt{JMPX}$ ($c$ - ), *jumps*, or transfers control, to continuation $c$ (i.e., $\\texttt{cc}\\leftarrow c\\circ_0\\texttt{c0}$, or rather $\\texttt{cc}\\leftarrow(c\\circ_0\\texttt{c0})\\circ_1\\texttt{c1}$). The remainder of the previous current continuation $\\texttt{cc}$ is discarded.\n- $\\texttt{DA}pr$ — $\\texttt{CALLXARGS}$ $p$,$r$ ($c$ - ), *calls* continuation $c$ with $p$ parameters and expecting $r$ return values, $0\\leq p\\leq15$, $0\\leq r\\leq 15$.\n- $\\texttt{DB0}p$ — $\\texttt{CALLXARGS}$ $p$,$-1$ ($c$ - ), *calls* continuation $c$ with $0\\leq p\\leq15$ parameters, expecting an arbitrary number of return values.\n- $\\texttt{DB1}p$ — $\\texttt{JMPXARGS}$ $p$ ($c$ - ), *jumps* to continuation $c$, passing only the top $0\\leq p\\leq 15$ values from the current stack to it (the remainder of the current stack is discarded).\n- $\\texttt{DB2}r$ — $\\texttt{RETARGS}$ $r$, *returns* to $\\texttt{c0}$, with $0\\leq r\\leq 15$ return values taken from the current stack.\n- $\\texttt{DB30}$ — $\\texttt{RET}$ or $\\texttt{RETTRUE}$, *returns* to the continuation at $\\texttt{c0}$ (i.e., performs $\\texttt{cc}\\leftarrow\\texttt{c0}$). The remainder of the current continuation $\\texttt{cc}$ is discarded. Approximately equivalent to $\\texttt{PUSH c0}$; $\\texttt{JMPX}$.\n- $\\texttt{DB31}$ — $\\texttt{RETALT}$ or $\\texttt{RETFALSE}$, *returns* to the continuation at $\\texttt{c1}$ (i.e., $\\texttt{cc}\\leftarrow\\texttt{c1}$). Approximately equivalent to $\\texttt{PUSH c1}$; $\\texttt{JMPX}$.\n- $\\texttt{DB32}$ — $\\texttt{BRANCH}$ or $\\texttt{RETBOOL}$ ($f$ - ), performs $\\texttt{RETTRUE}$ if integer $f\\neq 0$, or $\\texttt{RETFALSE}$ if $f=0$.\n- $\\texttt{DB34}$ — $\\texttt{CALLCC}$ ($c$ - ), *call with current continuation*, transfers control to $c$, pushing the old value of $\\texttt{cc}$ into $c$'s stack (instead of discarding it or writing it into new $\\texttt{c0}$).\n- $\\texttt{DB35}$ — $\\texttt{JMPXDATA}$ ($c$ - ), similar to $\\texttt{CALLCC}$, but the remainder of the current continuation (the old value of $\\texttt{cc}$) is converted into a *Slice* before pushing it into the stack of $c$.\n- $\\texttt{DB36}pr$ — $\\texttt{CALLCCARGS}$ $p$,$r$ ($c$ - ), similar to $\\texttt{CALLXARGS}$, but pushes the old value of $\\texttt{cc}$ (along with the top $0\\leq p\\leq 15$ values from the original stack) into the stack of newly-invoked continuation $c$, setting $\\texttt{cc.nargs}$ to $-1\\leq r\\leq 14$.\n- $\\texttt{DB38}$ — $\\texttt{CALLXVARARGS}$ ($c$ $p$ $r$ - ), similar to $\\texttt{CALLXARGS}$, but takes $-1\\leq p,r\\leq254$ from the stack. The next three operations also take $p$ and $r$ from the stack, both in the range $-1\\ldots254$.\n- $\\texttt{DB39}$ — $\\texttt{RETVARARGS}$ ($p$ $r$ - ), similar to $\\texttt{RETARGS}$.\n- $\\texttt{DB3A}$ — $\\texttt{JMPXVARARGS}$ ($c$ $p$ $r$ - ), similar to $\\texttt{JMPXARGS}$.\n- $\\texttt{DB3B}$ — $\\texttt{CALLCCVARARGS}$ ($c$ $p$ $r$ - ), similar to $\\texttt{CALLCCARGS}$.\n- $\\texttt{DB3C}$ — $\\texttt{CALLREF}$, equivalent to $\\texttt{PUSHREFCONT}$; $\\texttt{CALLX}$.\n- $\\texttt{DB3D}$ — $\\texttt{JMPREF}$, equivalent to $\\texttt{PUSHREFCONT}$; $\\texttt{JMPX}$.\n- $\\texttt{DB3E}$ — $\\texttt{JMPREFDATA}$, equivalent to $\\texttt{PUSHREFCONT}$; $\\texttt{JMPXDATA}$.\n- $\\texttt{DB3F}$ — $\\texttt{RETDATA}$, equivalent to $\\texttt{PUSH c0}$; $\\texttt{JMPXDATA}$. In this way, the remainder of the current continuation is converted into a *Slice* and returned to the caller.\n\n### A.8.2. Conditional control flow primitives\n\n- $\\texttt{DC}$ — $\\texttt{IFRET}$ ($f$ - ), performs a $\\texttt{RET}$, but only if integer $f$ is non-zero. If $f$ is a $\\texttt{NaN}$, throws an integer overflow exception.\n- $\\texttt{DD}$ — $\\texttt{IFNOTRET}$ ($f$ - ), performs a $\\texttt{RET}$, but only if integer $f$ is zero.\n- $\\texttt{DE}$ — $\\texttt{IF}$ ($f$ $c$ - ), performs $\\texttt{EXECUTE}$ for $c$ (i.e., *executes* $c$), but only if integer $f$ is non-zero. Otherwise simply discards both values.\n- $\\texttt{DF}$ — $\\texttt{IFNOT}$ ($f$ $c$ - ), executes continuation $c$, but only if integer $f$ is zero. Otherwise simply discards both values.\n- $\\texttt{E0}$ — $\\texttt{IFJMP}$ ($f$ $c$ - ), jumps to $c$ (similarly to $\\texttt{JMPX}$), but only if $f$ is non-zero.\n- $\\texttt{E1}$ — $\\texttt{IFNOTJMP}$ ($f$ $c$ - ), jumps to $c$ (similarly to $\\texttt{JMPX}$), but only if $f$ is zero.\n- $\\texttt{E2}$ — $\\texttt{IFELSE}$ ($f$ $c$ $c'$ - ), if integer $f$ is non-zero, executes $c$, otherwise executes $c'$. Equivalent to $\\texttt{CONDSELCHK}$; $\\texttt{EXECUTE}$.\n- $\\texttt{E300}$ — $\\texttt{IFREF}$ ($f$ - ), equivalent to $\\texttt{PUSHREFCONT}$; $\\texttt{IF}$, with the optimization that the cell reference is not actually loaded into a *Slice* and then converted into an ordinary *Continuation* if $f=0$. Similar remarks apply to the next three primitives.\n- $\\texttt{E301}$ — $\\texttt{IFNOTREF}$ ($f$ - ), equivalent to $\\texttt{PUSHREFCONT}$; $\\texttt{IFNOT}$.\n- $\\texttt{E302}$ — $\\texttt{IFJMPREF}$ ($f$ - ), equivalent to $\\texttt{PUSHREFCONT}$; $\\texttt{IFJMP}$.\n- $\\texttt{E303}$ — $\\texttt{IFNOTJMPREF}$ ($f$ - ), equivalent to $\\texttt{PUSHREFCONT}$; $\\texttt{IFNOTJMP}$.\n- $\\texttt{E304}$ — $\\texttt{CONDSEL}$ ($f$ $x$ $y$ - $x$ or $y$), if integer $f$ is non-zero, returns $x$, otherwise returns $y$. Notice that no type checks are performed on $x$ and $y$; as such, it is more like a conditional stack operation. Roughly equivalent to $\\texttt{ROT}$; $\\texttt{ISZERO}$; $\\texttt{INC}$; $\\texttt{ROLLX}$; $\\texttt{NIP}$.\n- $\\texttt{E305}$ — $\\texttt{CONDSELCHK}$ ($f$ $x$ $y$ - $x$ or $y$), same as $\\texttt{CONDSEL}$, but first checks whether $x$ and $y$ have the same type.\n- $\\texttt{E308}$ — $\\texttt{IFRETALT}$ ($f$ -), performs $\\texttt{RETALT}$ if integer $f\\neq0$.\n- $\\texttt{E309}$ — $\\texttt{IFNOTRETALT}$ ($f$ -), performs $\\texttt{RETALT}$ if integer $f=0$.\n- $\\texttt{E30D}$ — $\\texttt{IFREFELSE}$ ($f$ $c$ -), equivalent to $\\texttt{PUSHREFCONT}$; $\\texttt{SWAP}$; $\\texttt{IFELSE}$, with the optimization that the cell reference is not actually loaded into a *Slice* and then converted into an ordinary *Continuation* if $f=0$. Similar remarks apply to the next two primitives: *Cell*s are converted into *Continuation*s only when necessary.\n- $\\texttt{E30E}$ — $\\texttt{IFELSEREF}$ ($f$ $c$ -), equivalent to $\\texttt{PUSHREFCONT}$; $\\texttt{IFELSE}$.\n- $\\texttt{E30F}$ — $\\texttt{IFREFELSEREF}$ ($f$ -), equivalent to $\\texttt{PUSHREFCONT}$; $\\texttt{PUSHREFCONT}$; $\\texttt{IFELSE}$.\n- $\\texttt{E310}$--$\\texttt{E31F}$ — reserved for loops with break operators, [A.8.4](#a-8-4-manipulating-the-stack-of-continuations) below.\n- $\\texttt{E39\\_}n$ — $\\texttt{IFBITJMP}$ $n$ ($x$ $c$ - $x$), checks whether bit $0\\leq n\\leq 31$ is set in integer $x$, and if so, performs $\\texttt{JMPX}$ to continuation $c$. Value $x$ is left in the stack.\n- $\\texttt{E3B\\_}n$ — $\\texttt{IFNBITJMP}$ $n$ ($x$ $c$ - $x$), jumps to $c$ if bit $0\\leq n\\leq 31$ is not set in integer $x$.\n- $\\texttt{E3D\\_}n$ — $\\texttt{IFBITJMPREF}$ $n$ ($x$ - $x$), performs a $\\texttt{JMPREF}$ if bit $0\\leq n\\leq 31$ is set in integer $x$.\n- $\\texttt{E3F\\_}n$ — $\\texttt{IFNBITJMPREF}$ $n$ ($x$ - $x$), performs a $\\texttt{JMPREF}$ if bit $0\\leq n\\leq 31$ is not set in integer $x$.\n\n### A.8.3. Control flow primitives: loops\n\nMost of the loop primitives listed below are implemented with the aid of [extraordinary continuations](#4-1-5-extraordinary-continuations), such as $\\texttt{ec\\_until}$, with the loop body and the original current continuation $\\texttt{cc}$ stored as the arguments to this extraordinary continuation. Typically a suitable extraordinary continuation is constructed, and then saved into the loop body continuation savelist as $\\texttt{c0}$; after that, the modified loop body continuation is loaded into $\\texttt{cc}$ and executed in the usual fashion. All of these loop primitives have $\\texttt{*BRK}$ versions, adapted for breaking out of a loop; they additionally set $\\texttt{c1}$ to the original current continuation (or original $\\texttt{c0}$ for $\\texttt{*ENDBRK}$ versions), and save the old $\\texttt{c1}$ into the savelist of the original current continuation (or of the original $\\texttt{c0}$ for $\\texttt{*ENDBRK}$ versions).\n\n- $\\texttt{E4}$ — $\\texttt{REPEAT}$ ($n$ $c$ - ), executes continuation $c$ $n$ times, if integer $n$ is non-negative. If $n\\geq2^{31}$ or $n<-2^{31}$, generates a range check exception. Notice that a $\\texttt{RET}$ inside the code of $c$ works as a $\\texttt{continue}$, not as a $\\texttt{break}$. One should use either alternative (experimental) loops or alternative $\\texttt{RETALT}$ (along with a $\\texttt{SETEXITALT}$ before the loop) to $\\texttt{break}$ out of a loop.\n- $\\texttt{E5}$ — $\\texttt{REPEATEND}$ ($n$ - ), similar to $\\texttt{REPEAT}$, but it is applied to the current continuation $\\texttt{cc}$.\n- $\\texttt{E6}$ — $\\texttt{UNTIL}$ ($c$ - ), executes continuation $c$, then pops an integer $x$ from the resulting stack. If $x$ is zero, performs another iteration of this loop. The actual implementation of this primitive involves an [extraordinary continuation](#4-1-5-extraordinary-continuations) $\\texttt{ec\\_until}$ with its arguments set to the body of the loop (continuation $c$) and the original current continuation $\\texttt{cc}$. This extraordinary continuation is then saved into the savelist of $c$ as $c$.$\\texttt{c0}$ and the modified $c$ is then executed. The other loop primitives are implemented similarly with the aid of suitable extraordinary continuations.\n- $\\texttt{E7}$ — $\\texttt{UNTILEND}$ ( - ), similar to $\\texttt{UNTIL}$, but executes the current continuation $\\texttt{cc}$ in a loop. When the loop exit condition is satisfied, performs a $\\texttt{RET}$.\n- $\\texttt{E8}$ — $\\texttt{WHILE}$ ($c'$ $c$ - ), executes $c'$ and pops an integer $x$ from the resulting stack. If $x$ is zero, exists the loop and transfers control to the original $\\texttt{cc}$. If $x$ is non-zero, executes $c$, and then begins a new iteration.\n- $\\texttt{E9}$ — $\\texttt{WHILEEND}$ ($c'$ - ), similar to $\\texttt{WHILE}$, but uses the current continuation $\\texttt{cc}$ as the loop body.\n- $\\texttt{EA}$ — $\\texttt{AGAIN}$ ($c$ - ), similar to $\\texttt{REPEAT}$, but executes $c$ infinitely many times. A $\\texttt{RET}$ only begins a new iteration of the infinite loop, which can be exited only by an exception, or a $\\texttt{RETALT}$ (or an explicit $\\texttt{JMPX}$).\n- $\\texttt{EB}$ — $\\texttt{AGAINEND}$ ( - ), similar to $\\texttt{AGAIN}$, but performed with respect to the current continuation $\\texttt{cc}$.\n- $\\texttt{E314}$ — $\\texttt{REPEATBRK}$ ($n$ $c$ - ), similar to $\\texttt{REPEAT}$, but also sets $\\texttt{c1}$ to the original $\\texttt{cc}$ after saving the old value of $\\texttt{c1}$ into the savelist of the original $\\texttt{cc}$. In this way $\\texttt{RETALT}$ could be used to break out of the loop body.\n- $\\texttt{E315}$ — $\\texttt{REPEATENDBRK}$ ($n$ - ), similar to $\\texttt{REPEATEND}$, but also sets $\\texttt{c1}$ to the original $\\texttt{c0}$ after saving the old value of $\\texttt{c1}$ into the savelist of the original $\\texttt{c0}$. Equivalent to $\\texttt{SAMEALTSAVE}$; $\\texttt{REPEATEND}$.\n- $\\texttt{E316}$ — $\\texttt{UNTILBRK}$ ($c$ - ), similar to $\\texttt{UNTIL}$, but also modifies $\\texttt{c1}$ in the same way as $\\texttt{REPEATBRK}$.\n- $\\texttt{E317}$ — $\\texttt{UNTILENDBRK}$ ( - ), equivalent to $\\texttt{SAMEALTSAVE}$; $\\texttt{UNTILEND}$.\n- $\\texttt{E318}$ — $\\texttt{WHILEBRK}$ ($c'$ $c$ - ), similar to $\\texttt{WHILE}$, but also modifies $\\texttt{c1}$ in the same way as $\\texttt{REPEATBRK}$.\n- $\\texttt{E319}$ — $\\texttt{WHILEENDBRK}$ ($c$ - ), equivalent to $\\texttt{SAMEALTSAVE}$; $\\texttt{WHILEEND}$.\n- $\\texttt{E31A}$ — $\\texttt{AGAINBRK}$ ($c$ - ), similar to $\\texttt{AGAIN}$, but also modifies $\\texttt{c1}$ in the same way as $\\texttt{REPEATBRK}$.\n- $\\texttt{E31B}$ — $\\texttt{AGAINENDBRK}$ ( - ), equivalent to $\\texttt{SAMEALTSAVE}$; $\\texttt{AGAINEND}$.\n\n### A.8.4. Manipulating the stack of continuations\n\n- $\\texttt{EC}rn$ — $\\texttt{SETCONTARGS}$ $r$,$n$ ($x_1$ $x_2\\ldots x_r$ $c$ - $c'$), similar to $\\texttt{SETCONTARGS}$ $r$, but sets $c$.$\\texttt{nargs}$ to the final size of the stack of $c'$ plus $n$. In other words, transforms $c$ into a *closure* or a *partially applied function*, with $0\\leq n\\leq 14$ arguments missing.\n- $\\texttt{EC0}n$ — $\\texttt{SETNUMARGS}$ $n$ or $\\texttt{SETCONTARGS}$ $0$,$n$ ($c$ - $c'$), sets $c$.$\\texttt{nargs}$ to $n$ plus the current depth of $c$'s stack, where $0\\leq n\\leq 14$. If $c$.$\\texttt{nargs}$ is already set to a non-negative value, does nothing.\n- $\\texttt{EC}r\\texttt{F}$ — $\\texttt{SETCONTARGS}$ $r$ or $\\texttt{SETCONTARGS}$ $r$,$-1$ ($x_1$ $x_2\\ldots x_r$ $c$ - $c'$), pushes $0\\leq r\\leq 15$ values $x_1\\ldots x_r$ into the stack of (a copy of) the continuation $c$, starting with $x_1$. If the final depth of $c$'s stack turns out to be greater than $c$.$\\texttt{nargs}$, a stack overflow exception is generated.\n- $\\texttt{ED0}p$ — $\\texttt{RETURNARGS}$ $p$ ( - ), leaves only the top $0\\leq p\\leq 15$ values in the current stack (somewhat similarly to $\\texttt{ONLYTOPX}$), with all the unused bottom values not discarded, but saved into continuation $\\texttt{c0}$ in the same way as $\\texttt{SETCONTARGS}$ does.\n- $\\texttt{ED10}$ — $\\texttt{RETURNVARARGS}$ ($p$ - ), similar to $\\texttt{RETURNARGS}$, but with Integer $0\\leq p\\leq 255$ taken from the stack.\n- $\\texttt{ED11}$ — $\\texttt{SETCONTVARARGS}$ ($x_1$ $x_2\\ldots x_r$ $c$ $r$ $n$ - $c'$), similar to $\\texttt{SETCONTARGS}$, but with $0\\leq r\\leq 255$ and $-1\\leq n\\leq 255$ taken from the stack.\n- $\\texttt{ED12}$ — $\\texttt{SETNUMVARARGS}$ ($c$ $n$ - $c'$), where $-1\\leq n\\leq 255$. If $n=-1$, this operation does nothing ($c'=c$). Otherwise its action is similar to $\\texttt{SETNUMARGS}$ $n$, but with $n$ taken from the stack.\n\n### A.8.5. Creating simple continuations and closures\n\n- $\\texttt{ED1E}$ — $\\texttt{BLESS}$ ($s$ - $c$), transforms a *Slice* $s$ into a simple ordinary continuation $c$, with $c$.$\\texttt{code}=s$ and an empty stack and savelist.\n- $\\texttt{ED1F}$ — $\\texttt{BLESSVARARGS}$ ($x_1\\ldots x_r$ $s$ $r$ $n$ - $c$), equivalent to $\\texttt{ROT}$; $\\texttt{BLESS}$; $\\texttt{ROTREV}$; $\\texttt{SETCONTVARARGS}$.\n- $\\texttt{EE}rn$ — $\\texttt{BLESSARGS}$ $r,n$ ($x_1\\ldots x_r$ $s$ - $c$), where $0\\leq r\\leq 15$, $-1\\leq n\\leq 14$, equivalent to $\\texttt{BLESS}$; $\\texttt{SETCONTARGS}$ $r,n$. The value of $n$ is represented inside the instruction by the 4-bit integer $n\\bmod16$.\n- $\\texttt{EE0}n$ — $\\texttt{BLESSNUMARGS}$ $n$ or $\\texttt{BLESSARGS 0}$,$n$ ($s$ - $c$), also transforms a *Slice* $s$ into a *Continuation* $c$, but sets $c$.$\\texttt{nargs}$ to $0\\leq n\\leq 14$.\n\n### A.8.6. Operations with continuation savelists and control registers\n\n- $\\texttt{ED4}i$ — $\\texttt{PUSH c}(i)$ or $\\texttt{PUSHCTR c}(i)$ ( - $x$), pushes the current value of control register $\\texttt{c}(i)$. If the control register is not supported in the current codepage, or if it does not have a value, an exception is triggered.\n- $\\texttt{ED44}$ — $\\texttt{PUSH c4}$ or $\\texttt{PUSHROOT}$, pushes the \"global data root\" cell reference, thus enabling access to persistent smart-contract data.\n- $\\texttt{ED5}i$ — $\\texttt{POP c}(i)$ or $\\texttt{POPCTR c}(i)$ ($x$ - ), pops a value $x$ from the stack and stores it into control register $\\texttt{c}(i)$, if supported in the current codepage. Notice that if a control register accepts only values of a specific type, a type-checking exception may occur.\n- $\\texttt{ED54}$ — $\\texttt{POP c4}$ or $\\texttt{POPROOT}$, sets the \"global data root\" cell reference, thus allowing modification of persistent smart-contract data.\n- $\\texttt{ED6}i$ — $\\texttt{SETCONT c}(i)$ or $\\texttt{SETCONTCTR c}(i)$ ($x$ $c$ - $c'$), stores $x$ into the savelist of continuation $c$ as $\\texttt{c}(i)$, and returns the resulting continuation $c'$. Almost all operations with continuations may be expressed in terms of $\\texttt{SETCONTCTR}$, $\\texttt{POPCTR}$, and $\\texttt{PUSHCTR}$.\n- $\\texttt{ED7}i$ — $\\texttt{SETRETCTR c}(i)$ ($x$ - ), equivalent to $\\texttt{PUSH c0}$; $\\texttt{SETCONTCTR c}(i)$; $\\texttt{POP c0}$.\n- $\\texttt{ED8}i$ — $\\texttt{SETALTCTR c}(i)$ ($x$ - ), equivalent to $\\texttt{PUSH c1}$; $\\texttt{SETCONTCTR c}(i)$; $\\texttt{POP c0}$.\n- $\\texttt{ED9}i$ — $\\texttt{POPSAVE c}(i)$ or $\\texttt{POPCTRSAVE c}(i)$ ($x$ -), similar to $\\texttt{POP c}(i)$, but also saves the old value of $\\texttt{c}(i)$ into continuation $\\texttt{c0}$. Equivalent (up to exceptions) to $\\texttt{SAVECTR c}(i)$; $\\texttt{POP c}(i)$.\n- $\\texttt{EDA}i$ — $\\texttt{SAVE c}(i)$ or $\\texttt{SAVECTR c}(i)$ ( - ), saves the current value of $\\texttt{c}(i)$ into the savelist of continuation $\\texttt{c0}$. If an entry for $\\texttt{c}(i)$ is already present in the savelist of $\\texttt{c0}$, nothing is done. Equivalent to $\\texttt{PUSH c}(i)$; $\\texttt{SETRETCTR c}(i)$.\n- $\\texttt{EDB}i$ — $\\texttt{SAVEALT c}(i)$ or $\\texttt{SAVEALTCTR c}(i)$ ( - ), similar to $\\texttt{SAVE c}(i)$, but saves the current value of $\\texttt{c}(i)$ into the savelist of $\\texttt{c1}$, not $\\texttt{c0}$.\n- $\\texttt{EDC}i$ — $\\texttt{SAVEBOTH c}(i)$ or $\\texttt{SAVEBOTHCTR c}(i)$ ( - ), equivalent to $\\texttt{DUP}$; $\\texttt{SAVE c}(i)$; $\\texttt{SAVEALT c}(i)$.\n- $\\texttt{EDE0}$ — $\\texttt{PUSHCTRX}$ ($i$ - $x$), similar to $\\texttt{PUSHCTR c}(i)$, but with $i$, $0\\leq i\\leq255$, taken from the stack. Notice that this primitive is one of the few \"exotic\" primitives, which are not polymorphic like stack manipulation primitives, and at the same time do not have well-defined types of parameters and return values, because the type of $x$ depends on $i$.\n- $\\texttt{EDE1}$ — $\\texttt{POPCTRX}$ ($x$ $i$ - ), similar to $\\texttt{POPCTR c}(i)$, but with $0\\leq i\\leq255$ from the stack.\n- $\\texttt{EDE2}$ — $\\texttt{SETCONTCTRX}$ ($x$ $c$ $i$ - $c'$), similar to $\\texttt{SETCONTCTR c}(i)$, but with $0\\leq i\\leq 255$ from the stack.\n- $\\texttt{EDF0}$ — $\\texttt{COMPOS}$ or $\\texttt{BOOLAND}$ ($c$ $c'$ - $c''$), computes the composition $c\\circ_0c'$, which has the meaning of \"perform $c$, and, if successful, perform $c'$\" (if $c$ is a boolean circuit) or simply \"perform $c$, then $c'$\". Equivalent to $\\texttt{SWAP}$; $\\texttt{SETCONT c0}$.\n- $\\texttt{EDF1}$ — $\\texttt{COMPOSALT}$ or $\\texttt{BOOLOR}$ ($c$ $c'$ - $c''$), computes the alternative composition $c\\circ_1 c'$, which has the meaning of \"perform $c$, and, if not successful, perform $c'$\" (if $c$ is a boolean circuit). Equivalent to $\\texttt{SWAP}$; $\\texttt{SETCONT c1}$.\n- $\\texttt{EDF2}$ — $\\texttt{COMPOSBOTH}$ ($c$ $c'$ - $c''$), computes $(c\\circ_0c')\\circ_1c'$, which has the meaning of \"compute boolean circuit $c$, then compute $c'$, regardless of the result of $c$\".\n- $\\texttt{EDF3}$ — $\\texttt{ATEXIT}$ ($c$ - ), sets $\\texttt{c0}\\leftarrow c\\circ_0\\texttt{c0}$. In other words, $c$ will be executed before exiting current subroutine.\n- $\\texttt{EDF4}$ — $\\texttt{ATEXITALT}$ ($c$ - ), sets $\\texttt{c1}\\leftarrow c\\circ_1\\texttt{c1}$. In other words, $c$ will be executed before exiting current subroutine by its alternative return path.\n- $\\texttt{EDF5}$ — $\\texttt{SETEXITALT}$ ($c$ - ), sets $\\texttt{c1}\\leftarrow (c\\circ_0\\texttt{c0})\\circ_1\\texttt{c1}$. In this way, a subsequent $\\texttt{RETALT}$ will first execute $c$, then transfer control to the original $\\texttt{c0}$. This can be used, for instance, to exit from nested loops.\n- $\\texttt{EDF6}$ — $\\texttt{THENRET}$ ($c$ - $c'$), computes $c':=c\\circ_0\\texttt{c0}$\n- $\\texttt{EDF7}$ — $\\texttt{THENRETALT}$ ($c$ - $c'$), computes $c':=c\\circ_0\\texttt{c1}$\n- $\\texttt{EDF8}$ — $\\texttt{INVERT}$ ( - ), interchanges $\\texttt{c0}$ and $\\texttt{c1}$.\n- $\\texttt{EDF9}$ — $\\texttt{BOOLEVAL}$ ($c$ - $?$), performs $\\texttt{cc}\\leftarrow \\bigl(c\\circ_0((\\texttt{PUSH}\\,-1)\\circ_0\\texttt{cc})\\bigr)\\circ_1((\\texttt{PUSH}\\,0)\\circ_0\\texttt{cc})$. If $c$ represents a boolean circuit, the net effect is to evaluate it and push either $-1$ or $0$ into the stack before continuing.\n- $\\texttt{EDFA}$ — $\\texttt{SAMEALT}$ ( - ), sets $c_1:=c_0$. Equivalent to $\\texttt{PUSH c0}$; $\\texttt{POP c1}$.\n- $\\texttt{EDFB}$ — $\\texttt{SAMEALTSAVE}$ ( - ), sets $c_1:=c_0$, but first saves the old value of $c_1$ into the savelist of $c_0$. Equivalent to $\\texttt{SAVE c1}$; $\\texttt{SAMEALT}$.\n- $\\texttt{EE}rn$ — $\\texttt{BLESSARGS}$ $r,n$ ($x_1\\ldots x_r$ $s$ -- $c$), described in [A.8.4](#a-8-4-manipulating-the-stack-of-continuations).\n\n\n### A.8.7. Dictionary subroutine calls and jumps\n\n- $\\texttt{F0}n$ — $\\texttt{CALL}$ $n$ or $\\texttt{CALLDICT}$ $n$ ( - $n$), calls the continuation in $\\texttt{c3}$, pushing integer $0\\leq n\\leq 255$ into its stack as an argument. Approximately equivalent to $\\texttt{PUSHINT}$ $n$; $\\texttt{PUSH c3}$; $\\texttt{EXECUTE}$.\n- $\\texttt{F12\\_}n$ — $\\texttt{CALL}$ $n$ for $0\\leq n<2^{14}$ ( - $n$), an encoding of $\\texttt{CALL}$ $n$ for larger values of $n$.\n- $\\texttt{F16\\_}n$ — $\\texttt{JMP}$ $n$ or $\\texttt{JMPDICT}$ $n$ ( - $n$), jumps to the continuation in $\\texttt{c3}$, pushing integer $0\\leq n<2^{14}$ as its argument. Approximately equivalent to $\\texttt{PUSHINT}$ $n$; $\\texttt{PUSH c3}$; $\\texttt{JMPX}$.\n- $\\texttt{F1A\\_}n$ — $\\texttt{PREPARE}$ $n$ or $\\texttt{PREPAREDICT}$ $n$ ( - $n$ $c$), equivalent to $\\texttt{PUSHINT}$ $n$; $\\texttt{PUSH c3}$, for $0\\leq n<2^{14}$. In this way, $\\texttt{CALL}$ $n$ is approximately equivalent to $\\texttt{PREPARE}$ $n$; $\\texttt{EXECUTE}$, and $\\texttt{JMP}$ $n$ is approximately equivalent to $\\texttt{PREPARE}$ $n$; $\\texttt{JMPX}$. One might use, for instance, $\\texttt{CALLARGS}$ or $\\texttt{CALLCC}$ instead of $\\texttt{EXECUTE}$ here.\n\n## A.9  Exception generating and handling primitives\n\n### A.9.1. Throwing exceptions\n\n- $\\texttt{F22\\_}nn$ — $\\texttt{THROW}$ $nn$ ( - $0$ $nn$), throws exception $0\\leq nn\\leq 63$ with parameter zero. In other words, it transfers control to the continuation in $\\texttt{c2}$, pushing $0$ and $nn$ into its stack, and discarding the old stack altogether.\n- $\\texttt{F26\\_}nn$ — $\\texttt{THROWIF}$ $nn$ ($f$ - ), throws exception $0\\leq nn\\leq 63$ with parameter zero only if integer $f\\neq0$.\n- $\\texttt{F2A\\_}nn$ — $\\texttt{THROWIFNOT}$ $nn$ ($f$ - ), throws exception $0\\leq nn\\leq 63$ with parameter zero only if integer $f=0$.\n- $\\texttt{F2C4\\_}nn$ — $\\texttt{THROW}$ $nn$ for $0\\leq nn<2^{11}$, an encoding of $\\texttt{THROW}$ $nn$ for larger values of $nn$.\n- $\\texttt{F2CC\\_}nn$ — $\\texttt{THROWARG}$ $nn$ ($x$ - $x$ $nn$), throws exception $0\\leq nn<2^{11}$ with parameter $x$, by copying $x$ and $nn$ into the stack of $\\texttt{c2}$ and transferring control to $\\texttt{c2}$.\n- $\\texttt{F2D4\\_}nn$ — $\\texttt{THROWIF}$ $nn$ ($f$ - ) for $0\\leq nn<2^{11}$.\n- $\\texttt{F2DC\\_}nn$ — $\\texttt{THROWARGIF}$ $nn$ ($x$ $f$ - ), throws exception $0\\leq nn<2^{11}$ with parameter $x$ only if integer $f\\neq0$.\n- $\\texttt{F2E4\\_}nn$ — $\\texttt{THROWIFNOT}$ $nn$ ($f$ - ) for $0\\leq nn<2^{11}$.\n- $\\texttt{F2EC\\_}nn$ — $\\texttt{THROWARGIFNOT}$ $nn$ ($x$ $f$ - ), throws exception $0\\leq nn<2^{11}$ with parameter $x$ only if integer $f=0$.\n- $\\texttt{F2F0}$ — $\\texttt{THROWANY}$ ($n$ - $0$ $n$), throws exception $0\\leq n<2^{16}$ with parameter zero. Approximately equivalent to $\\texttt{PUSHINT 0}$; $\\texttt{SWAP}$; $\\texttt{THROWARGANY}$.\n- $\\texttt{F2F1}$ — $\\texttt{THROWARGANY}$ ($x$ $n$ - $x$ $n$), throws exception $0\\leq n<2^{16}$ with parameter $x$, transferring control to the continuation in $\\texttt{c2}$. Approximately equivalent to $\\texttt{PUSH c2}$; $\\texttt{JMPXARGS 2}$.\n- $\\texttt{F2F2}$ — $\\texttt{THROWANYIF}$ ($n$ $f$ - ), throws exception $0\\leq n<2^{16}$ with parameter zero only if $f\\neq0$.\n- $\\texttt{F2F3}$ — $\\texttt{THROWARGANYIF}$ ($x$ $n$ $f$ - ), throws exception $0\\leq n<2^{16}$ with parameter $x$ only if $f\\neq0$.\n- $\\texttt{F2F4}$ — $\\texttt{THROWANYIFNOT}$ ($n$ $f$ - ), throws exception $0\\leq n<2^{16}$ with parameter zero only if $f=0$.\n- $\\texttt{F2F5}$ — $\\texttt{THROWARGANYIFNOT}$ ($x$ $n$ $f$ - ), throws exception $0\\leq n<2^{16}$ with parameter $x$ only if $f=0$.\n\n### A.9.2. Catching and handling exceptions\n\n- $\\texttt{F2FF}$ — $\\texttt{TRY}$ ($c$ $c'$ - ), sets $\\texttt{c2}$ to $c'$, first saving the old value of $\\texttt{c2}$ both into the savelist of $c'$ and into the savelist of the current continuation, which is stored into $c$.$\\texttt{c0}$ and $c'$.$\\texttt{c0}$. Then runs $c$ similarly to $\\texttt{EXECUTE}$. If $c$ does not throw any exceptions, the original value of $\\texttt{c2}$ is automatically restored on return from $c$. If an exception occurs, the execution is transferred to $c'$, but the original value of $\\texttt{c2}$ is restored in the process, so that $c'$ can re-throw the exception by $\\texttt{THROWANY}$ if it cannot handle it by itself.\n- $\\texttt{F3}pr$ — $\\texttt{TRYARGS}$ $p$,$r$ ($c$ $c'$ - ), similar to $\\texttt{TRY}$, but with $\\texttt{CALLARGS}$ $p$,$r$ internally used instead of $\\texttt{EXECUTE}$. In this way, all but the top $0\\leq p\\leq 15$ stack elements will be saved into current continuation's stack, and then restored upon return from either $c$ or $c'$, with the top $0\\leq r\\leq 15$ values of the resulting stack of $c$ or $c'$ copied as return values.\n\n## A.10  Dictionary manipulation primitives\n\nTVM's dictionary support is discussed at length in [3.3](#3-3-hashmaps%2C-or-dictionaries). The basic operations with [dictionaries](#3-3-10-basic-dictionary-operations), while the taxonomy of dictionary manipulation [primitives](#3-3-11-taxonomy-of-dictionary-primitives). Here we use the concepts and notation introduced in those sections.\n\nDictionaries admit two different representations as TVM stack values:\n\n- A *Slice* $s$ with a serialization of a TL-B value of type $\\mathit{HashmapE}(n,X)$. In other words, $s$ consists either of one bit equal to zero (if the dictionary is empty), or of one bit equal to one and a reference to a *Cell* containing the root of the binary tree, i.e., a serialized value of type $\\mathit{Hashmap}(n,X)$.\n\n- A \"maybe *Cell*\" $c^?$, i.e., a value that is either a *Cell* (containing a serialized value of type $\\mathit{Hashmap}(n,X)$ as before) or a *Null* (corresponding to an empty dictionary). When a \"maybe *Cell*\" $c^?$ is used to represent a dictionary, we usually denote it by $D$ in the stack notation.\n\nMost of the dictionary primitives listed below accept and return dictionaries in the second form, which is more convenient for stack manipulation. However, serialized dictionaries inside larger TL-B objects use the first representation.\n\nOpcodes starting with $\\texttt{F4}$ and $\\texttt{F5}$ are reserved for dictionary operations.\n\n### A.10.1. Dictionary creation\n\n- $\\texttt{6D}$ — $\\texttt{NEWDICT}$ ( - $D$), returns a new empty dictionary. It is an alternative mnemonics for $\\texttt{PUSHNULL}$, [A.3.1](#a-3-1-null-primitives).\n- $\\texttt{6E}$ — $\\texttt{DICTEMPTY}$ ($D$ - $?$), checks whether dictionary $D$ is empty, and returns $-1$ or $0$ accordingly. It is an alternative mnemonics for $\\texttt{ISNULL}$, [A.3.1](#a-3-1-null-primitives).\n\n### A.10.2. Dictionary serialization and deserialization\n\n- $\\texttt{CE}$ — $\\texttt{STDICTS}$ ($s$ $b$ - $b'$), stores a *Slice*-represented dictionary $s$ into *Builder* $b$. It is actually a synonym for $\\texttt{STSLICE}$.\n- $\\texttt{F400}$ — $\\texttt{STDICT}$ or $\\texttt{STOPTREF}$ ($D$ $b$ - $b'$), stores dictionary $D$ into *Builder* $b$, returning the resulting *Builder* $b'$. In other words, if $D$ is a cell, performs $\\texttt{STONE}$ and $\\texttt{STREF}$; if $D$ is *Null*, performs $\\texttt{NIP}$ and $\\texttt{STZERO}$; otherwise throws a type checking exception.\n- $\\texttt{F401}$ — $\\texttt{SKIPDICT}$ or $\\texttt{SKIPOPTREF}$ ($s$ - $s'$), equivalent to $\\texttt{LDDICT}$; $\\texttt{NIP}$.\n- $\\texttt{F402}$ — $\\texttt{LDDICTS}$ ($s$ - $s'$ $s''$), loads (parses) a (*Slice*-represented) dictionary $s'$ from *Slice* $s$, and returns the remainder of $s$ as $s''$. This is a \"split function\" for all $\\mathit{HashmapE}(n,X)$ dictionary types.\n- $\\texttt{F403}$ — $\\texttt{PLDDICTS}$ ($s$ - $s'$), preloads a (*Slice*-represented) dictionary $s'$ from *Slice* $s$. Approximately equivalent to $\\texttt{LDDICTS}$; $\\texttt{DROP}$.\n- $\\texttt{F404}$ — $\\texttt{LDDICT}$ or $\\texttt{LDOPTREF}$ ($s$ - $D$ $s'$), loads (parses) a dictionary $D$ from *Slice* $s$, and returns the remainder of $s$ as $s'$. May be applied to dictionaries or to values of arbitrary $(\\text{\\textasciicircum}Y$) types.\n- $\\texttt{F405}$ — $\\texttt{PLDDICT}$ or $\\texttt{PLDOPTREF}$ ($s$ - $D$), preloads a dictionary $D$ from *Slice* $s$. Approximately equivalent to $\\texttt{LDDICT}$; $\\texttt{DROP}$.\n- $\\texttt{F406}$ — $\\texttt{LDDICTQ}$ ($s$ - $D$ $s'$ $-1$ or $s$ $0$), a quiet version of $\\texttt{LDDICT}$.\n- $\\texttt{F407}$ — $\\texttt{PLDDICTQ}$ ($s$ - $D$ $-1$ or $0$), a quiet version of $\\texttt{PLDDICT}$.\n\n### A.10.3. $\\texttt{Get}$ dictionary operations\n\n- $\\texttt{F40A}$ — $\\texttt{DICTGET}$ ($k$ $D$ $n$ - $x$ $-1$ or $0$), looks up key $k$ (represented by a *Slice*, the first $0\\leq n\\leq 1023$ data bits of which are used as a key) in dictionary $D$ of type $\\mathit{HashmapE}(n,X)$ with $n$-bit keys. On success, returns the value found as a *Slice* $x$.\n- $\\texttt{F40B}$ — $\\texttt{DICTGETREF}$ ($k$ $D$ $n$ - $c$ $-1$ or $0$), similar to $\\texttt{DICTGET}$, but with a $\\texttt{LDREF}$; $\\texttt{ENDS}$ applied to $x$ on success. This operation is useful for dictionaries of type $\\mathit{HashmapE}(n, \\text{\\textasciicircum}Y$).\n- $\\texttt{F40C}$ — $\\texttt{DICTIGET}$ ($i$ $D$ $n$ - $x$ $-1$ or $0$), similar to $\\texttt{DICTGET}$, but with a signed (big-endian) $n$-bit *Integer* $i$ as a key. If $i$ does not fit into $n$ bits, returns $0$. If $i$ is a $\\texttt{NaN}$, throws an integer overflow exception.\n- $\\texttt{F40D}$ — $\\texttt{DICTIGETREF}$ ($i$ $D$ $n$ - $c$ $-1$ or $0$), combines $\\texttt{DICTIGET}$ with $\\texttt{DICTGETREF}$: it uses signed $n$-bit *Integer* $i$ as a key and returns a *Cell* instead of a *Slice* on success.\n- $\\texttt{F40E}$ — $\\texttt{DICTUGET}$ ($i$ $D$ $n$ - $x$ $-1$ or $0$), similar to $\\texttt{DICTIGET}$, but with unsigned (big-endian) $n$-bit *Integer* $i$ used as a key.\n- $\\texttt{F40F}$ — $\\texttt{DICTUGETREF}$ ($i$ $D$ $n$ - $c$ $-1$ or $0$), similar to $\\texttt{DICTIGETREF}$, but with an unsigned $n$-bit *Integer* key $i$.\n\n### A.10.4. $\\texttt{Set}$/$\\texttt{Replace}$/$\\texttt{Add}$ dictionary operations\n\nThe mnemonics of the following dictionary primitives are constructed in a systematic fashion according to the regular expression $\\texttt{DICT}[,\\texttt{I},\\texttt{U}](\\texttt{SET},\\texttt{REPLACE},\\texttt{ADD})[\\texttt{GET}][\\texttt{REF}]$ depending on the type of the key used (a *Slice* or a signed or unsigned *Integer*), the dictionary operation to be performed, and the way the values are accepted and returned (as *Cells* or as *Slices*). Therefore, we provide a detailed description only for some primitives, assuming that this information is sufficient for the reader to understand the precise action of the remaining primitives.\n\n- $\\texttt{F412}$ — $\\texttt{DICTSET}$ ($x$ $k$ $D$ $n$ - $D'$), sets the value associated with $n$-bit key $k$ (represented by a *Slice* as in $\\texttt{DICTGET}$) in dictionary $D$ (also represented by a *Slice*) to value $x$ (again a *Slice*), and returns the resulting dictionary as $D'$.\n- $\\texttt{F413}$ — $\\texttt{DICTSETREF}$ ($c$ $k$ $D$ $n$ - $D'$), similar to $\\texttt{DICTSET}$, but with the value set to a reference to *Cell* $c$.\n- $\\texttt{F414}$ — $\\texttt{DICTISET}$ ($x$ $i$ $D$ $n$ - $D'$), similar to $\\texttt{DICTSET}$, but with the key represented by a (big-endian) signed $n$-bit integer $i$. If $i$ does not fit into $n$ bits, a range check exception is generated.\n- $\\texttt{F415}$ — $\\texttt{DICTISETREF}$ ($c$ $i$ $D$ $n$ - $D'$), similar to $\\texttt{DICTSETREF}$, but with the key a signed $n$-bit integer as in $\\texttt{DICTISET}$.\n- $\\texttt{F416}$ — $\\texttt{DICTUSET}$ ($x$ $i$ $D$ $n$ - $D'$), similar to $\\texttt{DICTISET}$, but with $i$ an unsigned $n$-bit integer.\n- $\\texttt{F417}$ — $\\texttt{DICTUSETREF}$ ($c$ $i$ $D$ $n$ - $D'$), similar to $\\texttt{DICTISETREF}$, but with $i$ unsigned.\n- $\\texttt{F41A}$ — $\\texttt{DICTSETGET}$ ($x$ $k$ $D$ $n$ - $D'$ $y$ $-1$ or $D'$ $0$), combines $\\texttt{DICTSET}$ with $\\texttt{DICTGET}$: it sets the value corresponding to key $k$ to $x$, but also returns the old value $y$ associated with the key in question, if present.\n- $\\texttt{F41B}$ — $\\texttt{DICTSETGETREF}$ ($c$ $k$ $D$ $n$ - $D'$ $c'$ $-1$ or $D'$ $0$), combines $\\texttt{DICTSETREF}$ with $\\texttt{DICTGETREF}$ similarly to $\\texttt{DICTSETGET}$.\n- $\\texttt{F41C}$ — $\\texttt{DICTISETGET}$ ($x$ $i$ $D$ $n$ - $D'$ $y$ $-1$ or $D'$ $0$), similar to $\\texttt{DICTSETGET}$, but with the key represented by a big-endian signed $n$-bit *Integer* $i$.\n- $\\texttt{F41D}$ — $\\texttt{DICTISETGETREF}$ ($c$ $i$ $D$ $n$ - $D'$ $c'$ $-1$ or $D'$ $0$), a version of $\\texttt{DICTSETGETREF}$ with signed *Integer* $i$ as a key.\n- $\\texttt{F41E}$ — $\\texttt{DICTUSETGET}$ ($x$ $i$ $D$ $n$ - $D'$ $y$ $-1$ or $D'$ $0$), similar to $\\texttt{DICTISETGET}$, but with $i$ an unsigned $n$-bit integer.\n- $\\texttt{F41F}$ — $\\texttt{DICTUSETGETREF}$ ($c$ $i$ $D$ $n$ - $D'$ $c'$ $-1$ or $D'$ $0$).\n- $\\texttt{F422}$ — $\\texttt{DICTREPLACE}$ ($x$ $k$ $D$ $n$ - $D'$ $-1$ or $D$ $0$), a $\\texttt{Replace}$ operation, which is similar to $\\texttt{DICTSET}$, but sets the value of key $k$ in dictionary $D$ to $x$ only if the key $k$ was already present in $D$.\n- $\\texttt{F423}$ — $\\texttt{DICTREPLACEREF}$ ($c$ $k$ $D$ $n$ - $D'$ $-1$ or $D$ $0$), a $\\texttt{Replace}$ counterpart of $\\texttt{DICTSETREF}$.\n- $\\texttt{F424}$ — $\\texttt{DICTIREPLACE}$ ($x$ $i$ $D$ $n$ - $D'$ $-1$ or $D$ $0$), a version of $\\texttt{DICTREPLACE}$ with signed $n$-bit *Integer* $i$ used as a key.\n- $\\texttt{F425}$ — $\\texttt{DICTIREPLACEREF}$ ($c$ $i$ $D$ $n$ - $D'$ $-1$ or $D$ $0$).\n- $\\texttt{F426}$ — $\\texttt{DICTUREPLACE}$ ($x$ $i$ $D$ $n$ - $D'$ $-1$ or $D$ $0$).\n- $\\texttt{F427}$ — $\\texttt{DICTUREPLACEREF}$ ($c$ $i$ $D$ $n$ - $D'$ $-1$ or $D$ $0$).\n- $\\texttt{F42A}$ — $\\texttt{DICTREPLACEGET}$ ($x$ $k$ $D$ $n$ - $D'$ $y$ $-1$ or $D$ $0$), a $\\texttt{Replace}$ counterpart of $\\texttt{DICTSETGET}$: on success, also returns the old value associated with the key in question.\n- $\\texttt{F42B}$ — $\\texttt{DICTREPLACEGETREF}$ ($c$ $k$ $D$ $n$ - $D'$ $c'$ $-1$ or $D$ $0$).\n- $\\texttt{F42C}$ — $\\texttt{DICTIREPLACEGET}$ ($x$ $i$ $D$ $n$ - $D'$ $y$ $-1$ or $D$ $0$).\n- $\\texttt{F42D}$ — $\\texttt{DICTIREPLACEGETREF}$ ($c$ $i$ $D$ $n$ - $D'$ $c'$ $-1$ or $D$ $0$).\n- $\\texttt{F42E}$ — $\\texttt{DICTUREPLACEGET}$ ($x$ $i$ $D$ $n$ - $D'$ $y$ $-1$ or $D$ $0$).\n- $\\texttt{F42F}$ — $\\texttt{DICTUREPLACEGETREF}$ ($c$ $i$ $D$ $n$ - $D'$ $c'$ $-1$ or $D$ $0$).\n- $\\texttt{F432}$ — $\\texttt{DICTADD}$ ($x$ $k$ $D$ $n$ - $D'$ $-1$ or $D$ $0$), an Add counterpart of $\\texttt{DICTSET}$: sets the value associated with key $k$ in dictionary $D$ to $x$, but only if it is not already present in $D$.\n- $\\texttt{F433}$ — $\\texttt{DICTADDREF}$ ($c$ $k$ $D$ $n$ - $D'$ $-1$ or $D$ $0$).\n- $\\texttt{F434}$ — $\\texttt{DICTIADD}$ ($x$ $i$ $D$ $n$ - $D'$ $-1$ or $D$ $0$).\n- $\\texttt{F435}$ — $\\texttt{DICTIADDREF}$ ($c$ $i$ $D$ $n$ - $D'$ $-1$ or $D$ $0$).\n- $\\texttt{F436}$ — $\\texttt{DICTUADD}$ ($x$ $i$ $D$ $n$ - $D'$ $-1$ or $D$ $0$).\n- $\\texttt{F437}$ — $\\texttt{DICTUADDREF}$ ($c$ $i$ $D$ $n$ - $D'$ $-1$ or $D$ $0$).\n- $\\texttt{F43A}$ — $\\texttt{DICTADDGET}$ ($x$ $k$ $D$ $n$ - $D'$ $-1$ or $D$ $y$ $0$), an Add counterpart of $\\texttt{DICTSETGET}$: sets the value associated with key $k$ in dictionary $D$ to $x$, but only if key $k$ is not already present in $D$. Otherwise, just returns the old value $y$ without changing the dictionary.\n- $\\texttt{F43B}$ — $\\texttt{DICTADDGETREF}$ ($c$ $k$ $D$ $n$ - $D'$ $-1$ or $D$ $c'$ $0$), an Add counterpart of $\\texttt{DICTSETGETREF}$.\n- $\\texttt{F43C}$ — $\\texttt{DICTIADDGET}$ ($x$ $i$ $D$ $n$ - $D'$ $-1$ or $D$ $y$ $0$).\n- $\\texttt{F43D}$ — $\\texttt{DICTIADDGETREF}$ ($c$ $i$ $D$ $n$ - $D'$ $-1$ or $D$ $c'$ $0$).\n- $\\texttt{F43E}$ — $\\texttt{DICTUADDGET}$ ($x$ $i$ $D$ $n$ - $D'$ $-1$ or $D$ $y$ $0$).\n- $\\texttt{F43F}$ — $\\texttt{DICTUADDGETREF}$ ($c$ $i$ $D$ $n$ - $D'$ $-1$ or $D$ $c'$ $0$).\n\n### A.10.5. Builder-accepting variants of $\\texttt{Set}$ dictionary operations\n\nThe following primitives accept the new value as a *Builder* $b$ instead of a *Slice* $x$, which often is more convenient if the value needs to be serialized from several components computed in the stack. (This is reflected by appending a $\\texttt{B}$ to the mnemonics of the corresponding $\\texttt{Set}$ primitives that work with *Slice*s.) The net effect is roughly equivalent to converting $b$ into a *Slice* by $\\texttt{ENDC}$; $\\texttt{CTOS}$ and executing the [corresponding primitive](#a-10-4-%2F%2F-dictionary-operations).\n\n- $\\texttt{F441}$ — $\\texttt{DICTSETB}$ ($b$ $k$ $D$ $n$ - $D'$).\n- $\\texttt{F442}$ — $\\texttt{DICTISETB}$ ($b$ $i$ $D$ $n$ - $D'$).\n- $\\texttt{F443}$ — $\\texttt{DICTUSETB}$ ($b$ $i$ $D$ $n$ - $D'$).\n- $\\texttt{F445}$ — $\\texttt{DICTSETGETB}$ ($b$ $k$ $D$ $n$ - $D'$ $y$ $-1$ or $D'$ $0$).\n- $\\texttt{F446}$ — $\\texttt{DICTISETGETB}$ ($b$ $i$ $D$ $n$ - $D'$ $y$ $-1$ or $D'$ $0$).\n- $\\texttt{F447}$ — $\\texttt{DICTUSETGETB}$ ($b$ $i$ $D$ $n$ - $D'$ $y$ $-1$ or $D'$ $0$).\n- $\\texttt{F449}$ — $\\texttt{DICTREPLACEB}$ ($b$ $k$ $D$ $n$ - $D'$ $-1$ or $D$ $0$).\n- $\\texttt{F44A}$ — $\\texttt{DICTIREPLACEB}$ ($b$ $i$ $D$ $n$ - $D'$ $-1$ or $D$ $0$).\n- $\\texttt{F44B}$ — $\\texttt{DICTUREPLACEB}$ ($b$ $i$ $D$ $n$ - $D'$ $-1$ or $D$ $0$).\n- $\\texttt{F44D}$ — $\\texttt{DICTREPLACEGETB}$ ($b$ $k$ $D$ $n$ - $D'$ $y$ $-1$ or $D$ $0$).\n- $\\texttt{F44E}$ — $\\texttt{DICTIREPLACEGETB}$ ($b$ $i$ $D$ $n$ - $D'$ $y$ $-1$ or $D$ $0$).\n- $\\texttt{F44F}$ — $\\texttt{DICTUREPLACEGETB}$ ($b$ $i$ $D$ $n$ - $D'$ $y$ $-1$ or $D$ $0$).\n- $\\texttt{F451}$ — $\\texttt{DICTADDB}$ ($b$ $k$ $D$ $n$ - $D'$ $-1$ or $D$ $0$).\n- $\\texttt{F452}$ — $\\texttt{DICTIADDB}$ ($b$ $i$ $D$ $n$ - $D'$ $-1$ or $D$ $0$).\n- $\\texttt{F453}$ — $\\texttt{DICTUADDB}$ ($b$ $i$ $D$ $n$ - $D'$ $-1$ or $D$ $0$).\n- $\\texttt{F455}$ — $\\texttt{DICTADDGETB}$ ($b$ $k$ $D$ $n$ - $D'$ $-1$ or $D$ $y$ $0$).\n- $\\texttt{F456}$ — $\\texttt{DICTIADDGETB}$ ($b$ $i$ $D$ $n$ - $D'$ $-1$ or $D$ $y$ $0$).\n- $\\texttt{F457}$ — $\\texttt{DICTUADDGETB}$ ($b$ $i$ $D$ $n$ - $D'$ $-1$ or $D$ $y$ $0$).\n\n### A.10.6. $\\texttt{Delete}$ dictionary operations\n\n- $\\texttt{F459}$ — $\\texttt{DICTDEL}$ ($k$ $D$ $n$ - $D'$ $-1$ or $D$ $0$), deletes $n$-bit key, represented by a *Slice* $k$, from dictionary $D$. If the key is present, returns the modified dictionary $D'$ and the success flag $-1$. Otherwise, returns the original dictionary $D$ and $0$.\n- $\\texttt{F45A}$ — $\\texttt{DICTIDEL}$ ($i$ $D$ $n$ - $D'$ $?$), a version of $\\texttt{DICTDEL}$ with the key represented by a signed $n$-bit *Integer* $i$. If $i$ does not fit into $n$ bits, simply returns $D$ $0$ (\"key not found, dictionary unmodified\").\n- $\\texttt{F45B}$ — $\\texttt{DICTUDEL}$ ($i$ $D$ $n$ - $D'$ $?$), similar to $\\texttt{DICTIDEL}$, but with $i$ an unsigned $n$-bit integer.\n- $\\texttt{F462}$ — $\\texttt{DICTDELGET}$ ($k$ $D$ $n$ - $D'$ $x$ $-1$ or $D$ $0$), deletes $n$-bit key, represented by a *Slice* $k$, from dictionary $D$. If the key is present, returns the modified dictionary $D'$, the original value $x$ associated with the key $k$ (represented by a *Slice*), and the success flag $-1$. Otherwise, returns the original dictionary $D$ and $0$.\n- $\\texttt{F463}$ — $\\texttt{DICTDELGETREF}$ ($k$ $D$ $n$ - $D'$ $c$ $-1$ or $D$ $0$), similar to $\\texttt{DICTDELGET}$, but with $\\texttt{LDREF}$; $\\texttt{ENDS}$ applied to $x$ on success, so that the value returned $c$ is a *Cell*.\n- $\\texttt{F464}$ — $\\texttt{DICTIDELGET}$ ($i$ $D$ $n$ - $D'$ $x$ $-1$ or $D$ $0$), a variant of primitive $\\texttt{DICTDELGET}$ with signed $n$-bit integer $i$ as a key.\n- $\\texttt{F465}$ — $\\texttt{DICTIDELGETREF}$ ($i$ $D$ $n$ - $D'$ $c$ $-1$ or $D$ $0$), a variant of primitive $\\texttt{DICTIDELGET}$ returning a *Cell* instead of a *Slice*.\n- $\\texttt{F466}$ — $\\texttt{DICTUDELGET}$ ($i$ $D$ $n$ - $D'$ $x$ $-1$ or $D$ $0$), a variant of primitive $\\texttt{DICTDELGET}$ with unsigned $n$-bit integer $i$ as a key.\n- $\\texttt{F467}$ — $\\texttt{DICTUDELGETREF}$ ($i$ $D$ $n$ - $D'$ $c$ $-1$ or $D$ $0$), a variant of primitive $\\texttt{DICTUDELGET}$ returning a *Cell* instead of a *Slice*.\n\n### A.10.7. \"Maybe reference\" dictionary operations\n\nThe following operations assume that a dictionary is used to store values $c^?$ of type $\\mathit{Cell}^?$ (\"Maybe Cell\"), which can be used in particular to store dictionaries as values in other dictionaries. The representation is as follows: if $c^?$ is a *Cell*, it is stored as a value with no data bits and exactly one reference to this *Cell*. If $c^?$ is *Null*, then the corresponding key must be absent from the dictionary altogether.\n\n- $\\texttt{F469}$ — $\\texttt{DICTGETOPTREF}$ ($k$ $D$ $n$ - $c^?$), a variant of $\\texttt{DICTGETREF}$ that returns *Null* instead of the value $c^?$ if the key $k$ is absent from dictionary $D$.\n- $\\texttt{F46A}$ — $\\texttt{DICTIGETOPTREF}$ ($i$ $D$ $n$ - $c^?$), similar to $\\texttt{DICTGETOPTREF}$, but with the key given by signed $n$-bit *Integer* $i$. If the key $i$ is out of range, also returns *Null*.\n- $\\texttt{F46B}$ — $\\texttt{DICTUGETOPTREF}$ ($i$ $D$ $n$ - $c^?$), similar to $\\texttt{DICTGETOPTREF}$, but with the key given by unsigned $n$-bit *Integer* $i$.\n- $\\texttt{F46D}$ — $\\texttt{DICTSETGETOPTREF}$ ($c^?$ $k$ $D$ $n$ - $D'$ $\\tilde{c}^?$), a variant of both $\\texttt{DICTGETOPTREF}$ and $\\texttt{DICTSETGETREF}$ that sets the value corresponding to key $k$ in dictionary $D$ to $c^?$ (if $c^?$ is *Null*, then the key is deleted instead), and returns the old value $\\tilde{c}^?$ (if the key $k$ was absent before, returns *Null* instead).\n- $\\texttt{F46E}$ — $\\texttt{DICTISETGETOPTREF}$ ($c^?$ $i$ $D$ $n$ - $D'$ $\\tilde{c}^?$), similar to primitive $\\texttt{DICTSETGETOPTREF}$, but using signed $n$-bit *Integer* $i$ as a key. If $i$ does not fit into $n$ bits, throws a range checking exception.\n- $\\texttt{F46F}$ — $\\texttt{DICTUSETGETOPTREF}$ ($c^?$ $i$ $D$ $n$ - $D'$ $\\tilde{c}^?$), similar to primitive $\\texttt{DICTSETGETOPTREF}$, but using unsigned $n$-bit *Integer* $i$ as a key.\n\n### A.10.8. Prefix code dictionary operations\n\nThese are some basic operations for constructing [prefix code](#3-4-2-serialization-of-prefix-codes) dictionaries. The primary application for prefix code dictionaries is deserializing TL-B serialized data structures, or, more generally, parsing prefix codes. Therefore, most prefix code dictionaries will be constant and created at compile time, not by the following primitives.\n\nSome $\\texttt{Get}$ operations for prefix code dictionaries may be found in [A.10.11](#a-10-11-special-dictionary-and-prefix-code-dictionary-operations%2C-and-constant-dictionaries). Other prefix code dictionary operations include:\n\n- $\\texttt{F470}$ — $\\texttt{PFXDICTSET}$ ($x$ $k$ $D$ $n$ - $D'$ $-1$ or $D$ $0$).\n- $\\texttt{F471}$ — $\\texttt{PFXDICTREPLACE}$ ($x$ $k$ $D$ $n$ - $D'$ $-1$ or $D$ $0$).\n- $\\texttt{F472}$ — $\\texttt{PFXDICTADD}$ ($x$ $k$ $D$ $n$ - $D'$ $-1$ or $D$ $0$).\n- $\\texttt{F473}$ — $\\texttt{PFXDICTDEL}$ ($k$ $D$ $n$ - $D'$ $-1$ or $D$ $0$).\n\nThese primitives are completely similar to their [non-prefix code](#a-10-4-%2F%2F-dictionary-operations) counterparts $\\texttt{DICTSET}$ etc, with the obvious difference that even a $\\texttt{Set}$ may fail in a prefix code dictionary, so a success flag must be returned by $\\texttt{PFXDICTSET}$ as well.\n\n### A.10.9. Variants of $\\texttt{GetNext}$ and $\\texttt{GetPrev}$ operations\n\n- $\\texttt{F474}$ — $\\texttt{DICTGETNEXT}$ ($k$ $D$ $n$ - $x'$ $k'$ $-1$ or $0$), computes the minimal key $k'$ in dictionary $D$ that is lexicographically greater than $k$, and returns $k'$ (represented by a *Slice*) along with associated value $x'$ (also represented by a *Slice*).\n- $\\texttt{F475}$ — $\\texttt{DICTGETNEXTEQ}$ ($k$ $D$ $n$ - $x'$ $k'$ $-1$ or $0$), similar to $\\texttt{DICTGETNEXT}$, but computes the minimal key $k'$ that is lexicographically greater than or equal to $k$.\n- $\\texttt{F476}$ — $\\texttt{DICTGETPREV}$ ($k$ $D$ $n$ - $x'$ $k'$ $-1$ or $0$), similar to $\\texttt{DICTGETNEXT}$, but computes the maximal key $k'$ lexicographically smaller than $k$.\n- $\\texttt{F477}$ — $\\texttt{DICTGETPREVEQ}$ ($k$ $D$ $n$ - $x'$ $k'$ $-1$ or $0$), similar to $\\texttt{DICTGETPREV}$, but computes the maximal key $k'$ lexicographically smaller than or equal to $k$.\n- $\\texttt{F478}$ — $\\texttt{DICTIGETNEXT}$ ($i$ $D$ $n$ - $x'$ $i'$ $-1$ or $0$), similar to $\\texttt{DICTGETNEXT}$, but interprets all keys in dictionary $D$ as big-endian signed $n$-bit integers, and computes the minimal key $i'$ that is larger than *Integer* $i$ (which does not necessarily fit into $n$ bits).\n- $\\texttt{F479}$ — $\\texttt{DICTIGETNEXTEQ}$ ($i$ $D$ $n$ - $x'$ $i'$ $-1$ or $0$).\n- $\\texttt{F47A}$ — $\\texttt{DICTIGETPREV}$ ($i$ $D$ $n$ - $x'$ $i'$ $-1$ or $0$).\n- $\\texttt{F47B}$ — $\\texttt{DICTIGETPREVEQ}$ ($i$ $D$ $n$ - $x'$ $i'$ $-1$ or $0$).\n- $\\texttt{F47C}$ — $\\texttt{DICTUGETNEXT}$ ($i$ $D$ $n$ - $x'$ $i'$ $-1$ or $0$), similar to $\\texttt{DICTGETNEXT}$, but interprets all keys in dictionary $D$ as big-endian unsigned $n$-bit integers, and computes the minimal key $i'$ that is larger than *Integer* $i$ (which does not necessarily fit into $n$ bits, and is not necessarily non-negative).\n- $\\texttt{F47D}$ — $\\texttt{DICTUGETNEXTEQ}$ ($i$ $D$ $n$ - $x'$ $i'$ $-1$ or $0$).\n- $\\texttt{F47E}$ — $\\texttt{DICTUGETPREV}$ ($i$ $D$ $n$ - $x'$ $i'$ $-1$ or $0$).\n- $\\texttt{F47F}$ — $\\texttt{DICTUGETPREVEQ}$ ($i$ $D$ $n$ - $x'$ $i'$ $-1$ or $0$).\n\n### A.10.10. $\\texttt{GetMin}$, $\\texttt{GetMax}$, $\\texttt{RemoveMin}$, $\\texttt{RemoveMax}$ operations\n\n- $\\texttt{F482}$ — $\\texttt{DICTMIN}$ ($D$ $n$ - $x$ $k$ $-1$ or $0$), computes the minimal key $k$ (represented by a *Slice* with $n$ data bits) in dictionary $D$, and returns $k$ along with the associated value $x$.\n- $\\texttt{F483}$ — $\\texttt{DICTMINREF}$ ($D$ $n$ - $c$ $k$ $-1$ or $0$), similar to $\\texttt{DICTMIN}$, but returns the only reference in the value as a *Cell* $c$.\n- $\\texttt{F484}$ — $\\texttt{DICTIMIN}$ ($D$ $n$ - $x$ $i$ $-1$ or $0$), somewhat similar to $\\texttt{DICTMIN}$, but computes the minimal key $i$ under the assumption that all keys are big-endian signed $n$-bit integers. Notice that the key and value returned may differ from those computed by $\\texttt{DICTMIN}$ and $\\texttt{DICTUMIN}$.\n- $\\texttt{F485}$ — $\\texttt{DICTIMINREF}$ ($D$ $n$ - $c$ $i$ $-1$ or $0$).\n- $\\texttt{F486}$ — $\\texttt{DICTUMIN}$ ($D$ $n$ - $x$ $i$ $-1$ or $0$), similar to $\\texttt{DICTMIN}$, but returns the key as an unsigned $n$-bit *Integer* $i$.\n- $\\texttt{F487}$ — $\\texttt{DICTUMINREF}$ ($D$ $n$ - $c$ $i$ $-1$ or $0$).\n- $\\texttt{F48A}$ — $\\texttt{DICTMAX}$ ($D$ $n$ - $x$ $k$ $-1$ or $0$), computes the maximal key $k$ (represented by a *Slice* with $n$ data bits) in dictionary $D$, and returns $k$ along with the associated value $x$.\n- $\\texttt{F48B}$ — $\\texttt{DICTMAXREF}$ ($D$ $n$ - $c$ $k$ $-1$ or $0$).\n- $\\texttt{F48C}$ — $\\texttt{DICTIMAX}$ ($D$ $n$ - $x$ $i$ $-1$ or $0$).\n- $\\texttt{F48D}$ — $\\texttt{DICTIMAXREF}$ ($D$ $n$ - $c$ $i$ $-1$ or $0$).\n- $\\texttt{F48E}$ — $\\texttt{DICTUMAX}$ ($D$ $n$ - $x$ $i$ $-1$ or $0$).\n- $\\texttt{F48F}$ — $\\texttt{DICTUMAXREF}$ ($D$ $n$ - $c$ $i$ $-1$ or $0$).\n- $\\texttt{F492}$ — $\\texttt{DICTREMMIN}$ ($D$ $n$ - $D'$ $x$ $k$ $-1$ or $D$ $0$), computes the minimal key $k$ (represented by a *Slice* with $n$ data bits) in dictionary $D$, removes $k$ from the dictionary, and returns $k$ along with the associated value $x$ and the modified dictionary $D'$.\n- $\\texttt{F493}$ — $\\texttt{DICTREMMINREF}$ ($D$ $n$ - $D'$ $c$ $k$ $-1$ or $D$ $0$), similar to $\\texttt{DICTREMMIN}$, but returns the only reference in the value as a *Cell* $c$.\n- $\\texttt{F494}$ — $\\texttt{DICTIREMMIN}$ ($D$ $n$ - $D'$ $x$ $i$ $-1$ or $D$ $0$), somewhat similar to $\\texttt{DICTREMMIN}$, but computes the minimal key $i$ under the assumption that all keys are big-endian signed $n$-bit integers. Notice that the key and value returned may differ from those computed by $\\texttt{DICTREMMIN}$ and $\\texttt{DICTUREMMIN}$.\n- $\\texttt{F495}$ — $\\texttt{DICTIREMMINREF}$ ($D$ $n$ - $D'$ $c$ $i$ $-1$ or $D$ $0$).\n- $\\texttt{F496}$ — $\\texttt{DICTUREMMIN}$ ($D$ $n$ - $D'$ $x$ $i$ $-1$ or $D$ $0$), similar to $\\texttt{DICTREMMIN}$, but returns the key as an unsigned $n$-bit *Integer* $i$.\n- $\\texttt{F497}$ — $\\texttt{DICTUREMMINREF}$ ($D$ $n$ - $D'$ $c$ $i$ $-1$ or $D$ $0$).\n- $\\texttt{F49A}$ — $\\texttt{DICTREMMAX}$ ($D$ $n$ - $D'$ $x$ $k$ $-1$ or $D$ $0$), computes the maximal key $k$ (represented by a *Slice* with $n$ data bits) in dictionary $D$, removes $k$ from the dictionary, and returns $k$ along with the associated value $x$ and the modified dictionary $D'$.\n- $\\texttt{F49B}$ — $\\texttt{DICTREMMAXREF}$ ($D$ $n$ - $D'$ $c$ $k$ $-1$ or $D$ $0$).\n- $\\texttt{F49C}$ — $\\texttt{DICTIREMMAX}$ ($D$ $n$ - $D'$ $x$ $i$ $-1$ or $D$ $0$).\n- $\\texttt{F49D}$ — $\\texttt{DICTIREMMAXREF}$ ($D$ $n$ - $D'$ $c$ $i$ $-1$ or $D$ $0$).\n- $\\texttt{F49E}$ — $\\texttt{DICTUREMMAX}$ ($D$ $n$ - $D'$ $x$ $i$ $-1$ or $D$ $0$).\n- $\\texttt{F49F}$ — $\\texttt{DICTUREMMAXREF}$ ($D$ $n$ - $D'$ $c$ $i$ $-1$ or $D$ $0$).\n\n### A.10.11. Special $\\texttt{Get}$ dictionary and prefix code dictionary operations, and constant dictionaries\n\n- $\\texttt{F4A0}$ — $\\texttt{DICTIGETJMP}$ ($i$ $D$ $n$ - ), similar to $\\texttt{DICTIGET}$ ([A.10.12](#a-10-12-dictionary-operations)), but with $x$ $\\texttt{BLESS}$ed into a continuation with a subsequent $\\texttt{JMPX}$ to it on success. On failure, does nothing. This is useful for implementing $\\texttt{switch}$/$\\texttt{case}$ constructions.\n- $\\texttt{F4A1}$ — $\\texttt{DICTUGETJMP}$ ($i$ $D$ $n$ - ), similar to $\\texttt{DICTIGETJMP}$, but performs $\\texttt{DICTUGET}$ instead of $\\texttt{DICTIGET}$.\n- $\\texttt{F4A2}$ — $\\texttt{DICTIGETEXEC}$ ($i$ $D$ $n$ - ), similar to $\\texttt{DICTIGETJMP}$, but with $\\texttt{EXECUTE}$ instead of $\\texttt{JMPX}$.\n- $\\texttt{F4A3}$ — $\\texttt{DICTUGETEXEC}$ ($i$ $D$ $n$ - ), similar to $\\texttt{DICTUGETJMP}$, but with $\\texttt{EXECUTE}$ instead of $\\texttt{JMPX}$.\n- $\\texttt{F4A6\\_}n$ — $\\texttt{DICTPUSHCONST}$ $n$ ( - $D$ $n$), pushes a non-empty constant dictionary $D$ (as a $\\mathit{Cell}^?$) along with its key length $0\\leq n\\leq 1023$, stored as a part of the instruction. The dictionary itself is created from the first of remaining references of the current continuation. In this way, the complete $\\texttt{DICTPUSHCONST}$ instruction can be obtained by first serializing $\\texttt{xF4A8\\_}$, then the non-empty dictionary itself (one $\\texttt{1}$ bit and a cell reference), and then the unsigned 10-bit integer $n$ (as if by a $\\texttt{STU 10}$ instruction). An empty dictionary can be pushed by a $\\texttt{NEWDICT}$ primitive ([A.10.1](#a-10-1-dictionary-creation)) instead.\n- $\\texttt{F4A8}$ — $\\texttt{PFXDICTGETQ}$ ($s$ $D$ $n$ - $s'$ $x$ $s''$ $-1$ or $s$ $0$), looks up the unique prefix of *Slice* $s$ present in the prefix code dictionary represented by $\\mathit{Cell}^?$ $D$ and $0\\leq n\\leq 1023$. If found, the prefix of $s$ is returned as $s'$, and the corresponding value (also a *Slice*) as $x$. The remainder of $s$ is returned as a *Slice* $s''$. If no prefix of $s$ is a key in prefix code dictionary $D$, returns the unchanged $s$ and a zero flag to indicate failure.\n- $\\texttt{F4A9}$ — $\\texttt{PFXDICTGET}$ ($s$ $D$ $n$ - $s'$ $x$ $s''$), similar to $\\texttt{PFXDICTGETQ}$, but throws a cell deserialization failure exception on failure.\n- $\\texttt{F4AA}$ — $\\texttt{PFXDICTGETJMP}$ ($s$ $D$ $n$ - $s'$ $s''$ or $s$), similar to $\\texttt{PFXDICTGETQ}$, but on success $\\texttt{BLESS}$es the value $x$ into a *Continuation* and transfers control to it as if by a $\\texttt{JMPX}$. On failure, returns $s$ unchanged and continues execution.\n- $\\texttt{F4AB}$ — $\\texttt{PFXDICTGETEXEC}$ ($s$ $D$ $n$ - $s'$ $s''$), similar to $\\texttt{PFXDICTGETJMP}$, but $\\texttt{EXEC}$utes the continuation found instead of jumping to it. On failure, throws a cell deserialization exception.\n- $\\texttt{F4AE\\_}n$ — $\\texttt{PFXDICTCONSTGETJMP}$ $n$ or $\\texttt{PFXDICTSWITCH}$ $n$ ($s$ - $s'$ $s''$ or $s$), combines $\\texttt{DICTPUSHCONST}$ $n$ for $0\\leq n\\leq 1023$ with $\\texttt{PFXDICTGETJMP}$.\n- $\\texttt{F4BC}$ — $\\texttt{DICTIGETJMPZ}$ ($i$ $D$ $n$ - $i$ or nothing), a variant of $\\texttt{DICTIGETJMP}$ that returns index $i$ on failure.\n- $\\texttt{F4BD}$ — $\\texttt{DICTUGETJMPZ}$ ($i$ $D$ $n$ - $i$ or nothing), a variant of $\\texttt{DICTUGETJMP}$ that returns index $i$ on failure.\n- $\\texttt{F4BE}$ — $\\texttt{DICTIGETEXECZ}$ ($i$ $D$ $n$ - $i$ or nothing), a variant of $\\texttt{DICTIGETEXEC}$ that returns index $i$ on failure.\n- $\\texttt{F4BF}$ — $\\texttt{DICTUGETEXECZ}$ ($i$ $D$ $n$ - $i$ or nothing), a variant of $\\texttt{DICTUGETEXEC}$ that returns index $i$ on failure.\n\n### A.10.12. $\\texttt{SubDict}$ dictionary operations\n\n- $\\texttt{F4B1}$ — $\\texttt{SUBDICTGET}$ ($k$ $l$ $D$ $n$ - $D'$), constructs a subdictionary consisting of all keys beginning with prefix $k$ (represented by a *Slice*, the first $0\\leq l\\leq n\\leq 1023$ data bits of which are used as a key) of length $l$ in dictionary $D$ of type $\\mathit{HashmapE}(n,X)$ with $n$-bit keys. On success, returns the new subdictionary of the same type $\\mathit{HashmapE}(n,X)$ as a *Slice* $D'$.\n- $\\texttt{F4B2}$ — $\\texttt{SUBDICTIGET}$ ($x$ $l$ $D$ $n$ - $D'$), variant of $\\texttt{SUBDICTGET}$ with the prefix represented by a signed big-endian $l$-bit *Integer* $x$, where necessarily $l\\leq257$.\n- $\\texttt{F4B3}$ — $\\texttt{SUBDICTUGET}$ ($x$ $l$ $D$ $n$ - $D'$), variant of $\\texttt{SUBDICTGET}$ with the prefix represented by an unsigned big-endian $l$-bit *Integer* $x$, where necessarily $l\\leq256$.\n- $\\texttt{F4B5}$ — $\\texttt{SUBDICTRPGET}$ ($k$ $l$ $D$ $n$ - $D'$), similar to $\\texttt{SUBDICTGET}$, but removes the common prefix $k$ from all keys of the new dictionary $D'$, which becomes of type $\\mathit{HashmapE}(n-l,X)$.\n- $\\texttt{F4B6}$ — $\\texttt{SUBDICTIRPGET}$ ($x$ $l$ $D$ $n$ - $D'$), variant of $\\texttt{SUBDICTRPGET}$ with the prefix represented by a signed big-endian $l$-bit *Integer* $x$, where necessarily $l\\leq257$.\n- $\\texttt{F4B7}$ — $\\texttt{SUBDICTURPGET}$ ($x$ $l$ $D$ $n$ - $D'$), variant of $\\texttt{SUBDICTRPGET}$ with the prefix represented by an unsigned big-endian $l$-bit *Integer* $x$, where necessarily $l\\leq256$.\n- $\\texttt{F4BC}$–$\\texttt{F4BF}$ — used by $\\texttt{DICT\\ldots Z}$ primitives in [A.10.11](#a-10-11-special-dictionary-and-prefix-code-dictionary-operations%2C-and-constant-dictionaries).\n\n## A.11  Application-specific primitives\n\nOpcode range $\\texttt{F8}$...$\\texttt{FB}$ is reserved for the *application-specific primitives*. When TVM is used to execute TON Blockchain smart contracts, these application-specific primitives are in fact TON Blockchain-specific.\n\n### A.11.1. External actions and access to blockchain configuration data\n\nSome of the primitives listed below pretend to produce some externally visible actions, such as sending a message to another smart contract. In fact, the execution of a smart contract in TVM never has any effect apart from a modification of the TVM state. All external actions are collected into a linked list stored in special register $\\texttt{c5}$ (\"output actions\"). Additionally, some primitives use the data kept in the first component of the [Tuple](#1-3-2-list-of-control-registers) stored in $\\texttt{c7}$. Smart contracts are free to modify any other data kept in the cell $\\texttt{c7}$, provided the first reference remains intact (otherwise some application-specific primitives would be likely to throw exceptions when invoked).\n\nMost of the primitives listed below use 16-bit opcodes.\n\n### A.11.2. Gas-related primitives\n\nOf the following primitives, only the first two are \"pure\" in the sense that they do not use $\\texttt{c5}$ or $\\texttt{c7}$.\n\n- $\\texttt{F800}$ — $\\texttt{ACCEPT}$, sets current gas limit $g_l$ to its maximal allowed value $g_m$, and resets the gas credit $g_c$ to zero ([1.4](#1-4-total-state-of-tvm-scccg)), decreasing the value of $g_r$ by $g_c$ in the process. In other words, the current smart contract agrees to buy some gas to finish the current transaction. This action is required to process external messages, which bring no value (hence no gas) with themselves.\n- $\\texttt{F801}$ — $\\texttt{SETGASLIMIT}$ ($g$ - ), sets current gas limit $g_l$ to the minimum of $g$ and $g_m$, and resets the gas credit $g_c$ to zero. If the gas consumed so far (including the present instruction) exceeds the resulting value of $g_l$, an (unhandled) out of gas exception is thrown before setting new gas limits. Notice that $\\texttt{SETGASLIMIT}$ with an argument $g\\geq 2^{63}-1$ is equivalent to $\\texttt{ACCEPT}$.\n- $\\texttt{F802}$ — $\\texttt{BUYGAS}$ ($x$ - ), computes the amount of gas that can be bought for $x$ nanograms, and sets $g_l$ accordingly in the same way as $\\texttt{SETGASLIMIT}$.\n- $\\texttt{F804}$ — $\\texttt{GRAMTOGAS}$ ($x$ - $g$), computes the amount of gas that can be bought for $x$ nanograms. If $x$ is negative, returns 0. If $g$ exceeds $2^{63}-1$, it is replaced with this value.\n- $\\texttt{F805}$ — $\\texttt{GASTOGRAM}$ ($g$ - $x$), computes the price of $g$ gas in nanograms.\n- $\\texttt{F806}$–$\\texttt{F80E}$ — Reserved for gas-related primitives.\n- $\\texttt{F80F}$ — $\\texttt{COMMIT}$ ( - ), commits the current state of registers $\\texttt{c4}$ (\"persistent data\") and $\\texttt{c5}$ (\"actions\") so that the current execution is considered \"successful\" with the saved values even if an exception is thrown later.\n\n### A.11.3. Pseudo-random number generator primitives\n\nThe pseudo-random number generator uses the [random seed](#a-11-4-configuration-primitives) (parameter #6), an unsigned 256-bit *Integer*, and (sometimes) other data kept in $\\texttt{c7}$. The initial value of the random seed before a smart contract is executed in TON Blockchain is a hash of the smart contract address and the global block random seed. If there are several runs of the same smart contract inside a block, then all of these runs will have the same random seed. This can be fixed, for example, by running $\\texttt{LTIME}$; $\\texttt{ADDRAND}$ before using the pseudo-random number generator for the first time.\n\n- $\\texttt{F810}$ — $\\texttt{RANDU256}$ ( - $x$), generates a new pseudo-random unsigned 256-bit Integer $x$. The algorithm is as follows: if $r$ is the old value of the random seed, considered as a 32-byte array (by constructing the big-endian representation of an unsigned 256-bit integer), then its $\\text{Sha512}(r)$ is computed; the first 32 bytes of this hash are stored as the new value $r'$ of the random seed, and the remaining 32 bytes are returned as the next random value $x$.\n- $\\texttt{F811}$ — $\\texttt{RAND}$ ($y$ - $z$), generates a new pseudo-random integer $z$ in the range $0\\ldots y-1$ (or $y\\ldots-1$, if $y<0$). More precisely, an unsigned random value $x$ is generated as in $\\texttt{RAND256U}$; then $z:=\\lfloor xy/2^{256}\\rfloor$ is computed. Equivalent to $\\texttt{RANDU256}$; $\\texttt{MULRSHIFT 256}$.\n- $\\texttt{F814}$ — $\\texttt{SETRAND}$ ($x$ - ), sets the random seed to unsigned 256-bit *Integer* $x$.\n- $\\texttt{F815}$ — $\\texttt{ADDRAND}$ ($x$ - ), mixes unsigned 256-bit *Integer* $x$ into the random seed $r$ by setting the random seed to SHA-256 of the concatenation of two 32-byte strings: the first with the big-endian representation of the old seed $r$, and the second with the big-endian representation of $x$.\n- $\\texttt{F810}$–$\\texttt{F81F}$ — Reserved for pseudo-random number generator primitives.\n\n### A.11.4. Configuration primitives\n\nThe following primitives read configuration data provided in the *Tuple* stored in the first component of the Tuple at $\\texttt{c7}$. Whenever TVM is invoked for executing TON Blockchain smart contracts, this *Tuple* is initialized by a *SmartContractInfo* structure; configuration primitives assume that it has remained intact.\n\n- $\\texttt{F82}i$ — $\\texttt{GETPARAM}$ $i$ ( - $x$), returns the $i$-th parameter from the *Tuple* provided at $\\texttt{c7}$ for $0\\leq i<16$. Equivalent to $\\texttt{PUSH c7}$; $\\texttt{FIRST}$; $\\texttt{INDEX}$ $i$. If one of these internal operations fails, throws an appropriate type checking or range checking exception.\n- $\\texttt{F823}$ — $\\texttt{NOW}$ ( - $x$), returns the current Unix time as an *Integer*. If it is impossible to recover the requested value starting from $\\texttt{c7}$, throws a type checking or range checking exception as appropriate. Equivalent to $\\texttt{GETPARAM 3}$.\n- $\\texttt{F824}$ — $\\texttt{BLOCKLT}$ ( - $x$), returns the starting logical time of the current block. Equivalent to $\\texttt{GETPARAM 4}$.\n- $\\texttt{F825}$ — $\\texttt{LTIME}$ ( - $x$), returns the logical time of the current transaction. Equivalent to $\\texttt{GETPARAM 5}$.\n- $\\texttt{F826}$ — $\\texttt{RANDSEED}$ ( - $x$), returns the current random seed as an unsigned 256-bit *Integer*. Equivalent to $\\texttt{GETPARAM 6}$.\n- $\\texttt{F827}$ — $\\texttt{BALANCE}$ ( - $t$), returns the remaining balance of the smart contract as a *Tuple* consisting of an *Integer* (the remaining Gram balance in nanograms) and a *Maybe Cell* (a dictionary with 32-bit keys representing the balance of \"extra currencies\"). Equivalent to $\\texttt{GETPARAM 7}$. Note that $\\texttt{RAW}$ primitives such as $\\texttt{SENDRAWMSG}$ do not update this field.\n- $\\texttt{F828}$ — $\\texttt{MYADDR}$ ( - $s$), returns the internal address of the current smart contract as a *Slice* with a $\\texttt{MsgAddressInt}$. If necessary, it can be parsed further using primitives such as $\\texttt{PARSESTDADDR}$ or $\\texttt{REWRITESTDADDR}$. Equivalent to $\\texttt{GETPARAM 8}$.\n- $\\texttt{F829}$ — $\\texttt{CONFIGROOT}$ ( - $D$), returns the *Maybe Cell* $D$ with the current global configuration dictionary. Equivalent to $\\texttt{GETPARAM 9}$.\n- $\\texttt{F830}$ — $\\texttt{CONFIGDICT}$ ( - $D$ $32$), returns the global configuration dictionary along with its key length (32). Equivalent to $\\texttt{CONFIGROOT}$; $\\texttt{PUSHINT 32}$.\n- $\\texttt{F832}$ — $\\texttt{CONFIGPARAM}$ ($i$ - $c$ $-1$ or $0$), returns the value of the global configuration parameter with integer index $i$ as a *Cell* $c$, and a flag to indicate success. Equivalent to $\\texttt{CONFIGDICT}$; $\\texttt{DICTIGETREF}$.\n- $\\texttt{F833}$ — $\\texttt{CONFIGOPTPARAM}$ ($i$ - $c^?$), returns the value of the global configuration parameter with integer index $i$ as a *Maybe Cell* $c^?$. Equivalent to $\\texttt{CONFIGDICT}$; $\\texttt{DICTIGETOPTREF}$.\n- $\\texttt{F820}$-$\\texttt{F83F}$ — Reserved for configuration primitives.\n\n### A.11.5. Global variable primitives\n\nThe \"global variables\" may be helpful in implementing some high-level smart-contract languages. They are in fact stored as components of the *Tuple* at $\\texttt{c7}$: the $k$-th global variable simply is the $k$-th component of this *Tuple*, for $1\\leq k\\leq 254$. By convention, the $0$-th component is used for the [configuration parameters](#a-11-4-configuration-primitives), so it is not available as a global variable.\n\n- $\\texttt{F840}$ — $\\texttt{GETGLOBVAR}$ ($k$ - $x$), returns the $k$-th global variable for $0\\leq k<255$. Equivalent to $\\texttt{PUSH c7}$; $\\texttt{SWAP}$; $\\texttt{INDEXVARQ}$ ([A.3.2](#a-3-2-tuple-primitives)).\n- $\\texttt{F85\\_}k$ — $\\texttt{GETGLOB}$ $k$ ( - $x$), returns the $k$-th global variable for $1\\leq k\\leq 31$. Equivalent to $\\texttt{PUSH c7}$; $\\texttt{INDEXQ}$ $k$.\n- $\\texttt{F860}$ — $\\texttt{SETGLOBVAR}$ ($x$ $k$ - ), assigns $x$ to the $k$-th global variable for $0\\leq k<255$. Equivalent to $\\texttt{PUSH c7}$; $\\texttt{ROTREV}$; $\\texttt{SETINDEXVARQ}$; $\\texttt{POP c7}$.\n- $\\texttt{F87\\_}k$ — $\\texttt{SETGLOB}$ $k$ ($x$ - ), assigns $x$ to the $k$-th global variable for $1\\leq k\\leq 31$. Equivalent to $\\texttt{PUSH c7}$; $\\texttt{SWAP}$; $\\texttt{SETINDEXQ}$ $k$; $\\texttt{POP c7}$.\n\n### A.11.6. Hashing and cryptography primitives\n\n- $\\texttt{F900}$ — $\\texttt{HASHCU}$ ($c$ - $x$), computes the [representation hash](#3-1-5-the-representation-hash-of-a-cell) of a *Cell* $c$ and returns it as a 256-bit unsigned integer $x$. Useful for signing and checking signatures of arbitrary entities represented by a tree of cells.\n- $\\texttt{F901}$ — $\\texttt{HASHSU}$ ($s$ - $x$), computes the hash of a *Slice* $s$ and returns it as a 256-bit unsigned integer $x$. The result is the same as if an ordinary cell containing only data and references from $s$ had been created and its hash computed by $\\texttt{HASHCU}$.\n- $\\texttt{F902}$ — $\\texttt{SHA256U}$ ($s$ - $x$), computes SHA-256 of the data bits of *Slice* $s$. If the bit length of $s$ is not divisible by eight, throws a cell underflow exception. The hash value is returned as a 256-bit unsigned integer $x$.\n- $\\texttt{F910}$ — $\\texttt{CHKSIGNU}$ ($h$ $s$ $k$ - $?$), checks the Ed25519-signature $s$ of a hash $h$ (a 256-bit unsigned integer, usually computed as the hash of some data) using public key $k$ (also represented by a 256-bit unsigned integer). The signature $s$ must be a *Slice* containing at least 512 data bits; only the first 512 bits are used. The result is $-1$ if the signature is valid, $0$ otherwise. Notice that $\\texttt{CHKSIGNU}$ is equivalent to $\\texttt{ROT}$; $\\texttt{NEWB}$; $\\texttt{STU 256}$; $\\texttt{ENDB}$; $\\texttt{NEWC}$; $\\texttt{ROTREV}$; $\\texttt{CHKSIGNS}$, i.e., to $\\texttt{CHKSIGNS}$ with the first argument $d$ set to 256-bit *Slice* containing $h$. Therefore, if $h$ is computed as the hash of some data, these data are hashed *twice*, the second hashing occurring inside $\\texttt{CHKSIGNS}$.\n- $\\texttt{F911}$ — $\\texttt{CHKSIGNS}$ ($d$ $s$ $k$ - $?$), checks whether $s$ is a valid Ed25519-signature of the data portion of *Slice* $d$ using public key $k$, similarly to $\\texttt{CHKSIGNU}$. If the bit length of *Slice* $d$ is not divisible by eight, throws a cell underflow exception. The verification of Ed25519 signatures is the standard one, with SHA-256 used to reduce $d$ to the 256-bit number that is actually signed.\n- $\\texttt{F912}$-$\\texttt{F93F}$ — Reserved for hashing and cryptography primitives.\n\n### A.11.7. Miscellaneous primitives\n\n- $\\texttt{F940}$ — $\\texttt{CDATASIZEQ}$ ($c$ $n$ - $x$ $y$ $z$ $-1$ or $0$), recursively computes the count of distinct cells $x$, data bits $y$, and cell references $z$ in the dag rooted at *Cell* $c$, effectively returning the total storage used by this dag taking into account the identification of equal cells. The values of $x$, $y$, and $z$ are computed by a depth-first traversal of this dag, with a hash table of visited cell hashes used to prevent visits of already-visited cells. The total count of visited cells $x$ cannot exceed non-negative *Integer* $n$; otherwise the computation is aborted before visiting the $(n+1)$-st cell and a zero is returned to indicate failure. If $c$ is *Null*, returns $x=y=z=0$.\n- $\\texttt{F941}$ — $\\texttt{CDATASIZE}$ ($c$ $n$ - $x$ $y$ $z$), a non-quiet version of $\\texttt{CDATASIZEQ}$ that throws a cell overflow exception (8) on failure.\n- $\\texttt{F942}$ — $\\texttt{SDATASIZEQ}$ ($s$ $n$ - $x$ $y$ $z$ $-1$ or $0$), similar to $\\texttt{CDATASIZEQ}$, but accepting a *Slice* $s$ instead of a *Cell*. The returned value of $x$ does not take into account the cell that contains the slice $s$ itself; however, the data bits and the cell references of $s$ are accounted for in $y$ and $z$.\n- $\\texttt{F943}$ — $\\texttt{SDATASIZE}$ ($s$ $n$ - $x$ $y$ $z$), a non-quiet version of $\\texttt{SDATASIZEQ}$ that throws a cell overflow exception (8) on failure.\n- $\\texttt{F944}$-$\\texttt{F97F}$ — Reserved for miscellaneous TON-specific primitives that do not fall into any other specific category.\n\n### A.11.8. Currency manipulation primitives\n\n- $\\texttt{FA00}$ — $\\texttt{LDGRAMS}$ or $\\texttt{LDVARUINT16}$ ($s$ - $x$ $s'$), loads (deserializes) a $\\texttt{Gram}$ or $\\texttt{VarUInteger 16}$ amount from *CellSlice* $s$, and returns the amount as *Integer* $x$ along with the remainder $s'$ of $s$. The expected serialization of $x$ consists of a 4-bit unsigned big-endian integer $l$, followed by an $8l$-bit unsigned big-endian representation of $x$. The net effect is approximately equivalent to $\\texttt{LDU 4}$; $\\texttt{SWAP}$; $\\texttt{LSHIFT 3}$; $\\texttt{LDUX}$.\n- $\\texttt{FA01}$ — $\\texttt{LDVARINT16}$ ($s$ - $x$ $s'$), similar to $\\texttt{LDVARUINT16}$, but loads a *signed* *Integer* $x$. Approximately equivalent to $\\texttt{LDU 4}$; $\\texttt{SWAP}$; $\\texttt{LSHIFT 3}$; $\\texttt{LDIX}$.\n- $\\texttt{FA02}$ — $\\texttt{STGRAMS}$ or $\\texttt{STVARUINT16}$ ($b$ $x$ - $b'$), stores (serializes) an *Integer* $x$ in the range $0\\ldots2^{120}-1$ into *Builder* $b$, and returns the resulting *Builder* $b'$. The serialization of $x$ consists of a 4-bit unsigned big-endian integer $l$, which is the smallest integer $l\\geq0$, such that $x<2^{8l}$, followed by an $8l$-bit unsigned big-endian representation of $x$. If $x$ does not belong to the supported range, a range check exception is thrown.\n- $\\texttt{FA03}$ — $\\texttt{STVARINT16}$ ($b$ $x$ - $b'$), similar to $\\texttt{STVARUINT16}$, but serializes a *signed* *Integer* $x$ in the range $-2^{119}\\ldots2^{119}-1$.\n- $\\texttt{FA04}$ — $\\texttt{LDVARUINT32}$ ($s$ - $x$ $s'$), loads (deserializes) a $\\texttt{VarUInteger 32}$ from *CellSlice* $s$, and returns the deserialized value as an *Integer* $0\\leq x<2^{248}$. The expected serialization of $x$ consists of a 5-bit unsigned big-endian integer $l$, followed by an $8l$-bit unsigned big-endian representation of $x$. The net effect is approximately equivalent to $\\texttt{LDU 5}$; $\\texttt{SWAP}$; $\\texttt{SHIFT 3}$; $\\texttt{LDUX}$.\n- $\\texttt{FA05}$ — $\\texttt{LDVARINT32}$ ($s$ - $x$ $s'$), deserializes a $\\texttt{VarInteger 32}$ from *CellSlice* $s$, and returns the deserialized value as an *Integer* $-2^{247}\\leq x<2^{247}$.\n- $\\texttt{FA06}$ — $\\texttt{STVARUINT32}$ ($b$ $x$ - $b'$), serializes an *Integer* $0\\leq x<2^{248}$ as a $\\texttt{VarUInteger 32}$.\n- $\\texttt{FA07}$ — $\\texttt{STVARINT32}$ ($b$ $x$ - $b'$), serializes an *Integer* $-2^{247}\\leq x<2^{247}$ as a $\\texttt{VarInteger 32}$.\n- $\\texttt{FA08}$-$\\texttt{FA1F}$ — Reserved for currency manipulation primitives.\n\n### A.11.9. Message and address manipulation primitives\n\nThe message and address manipulation primitives listed below serialize and deserialize values according to the following [TL-B scheme](#3-3-4-brief-explanation-of-tl-b-schemes):\n```\naddr_none$00 = MsgAddressExt;\naddr_extern$01 len:(## 9) external_address:(bits len) \n             = MsgAddressExt;\nanycast_info$_ depth:(#<= 30) { depth >= 1 }\n   rewrite_pfx:(bits depth) = Anycast;\naddr_std$10 anycast:(Maybe Anycast) \n   workchain_id:int8 address:bits256  = MsgAddressInt;\naddr_var$11 anycast:(Maybe Anycast) addr_len:(## 9) \n   workchain_id:int32 address:(bits addr_len) = MsgAddressInt;\n_ _:MsgAddressInt = MsgAddress;\n_ _:MsgAddressExt = MsgAddress;\n\nint_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool\n  src:MsgAddress dest:MsgAddressInt \n  value:CurrencyCollection ihr_fee:Grams fwd_fee:Grams\n  created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed;\next_out_msg_info$11 src:MsgAddress dest:MsgAddressExt\n  created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed;\n```\n\nA deserialized $\\texttt{MsgAddress}$ is represented by a *Tuple* $t$ as follows:\n\n- $\\texttt{addr\\_none}$ is represented by $t=(0)$, i.e., a *Tuple* containing exactly one *Integer* equal to zero.\n- $\\texttt{addr\\_extern}$ is represented by $t=(1,s)$, where *Slice* $s$ contains the field $\\texttt{external\\_address}$. In other words, $t$ is a pair (a *Tuple* consisting of two entries), containing an *Integer* equal to one and *Slice* $s$.\n- $\\texttt{addr\\_std}$ is represented by $t=(2,u,x,s)$, where $u$ is either a *Null* (if $\\texttt{anycast}$ is absent) or a *Slice* $s'$ containing $\\texttt{rewrite\\_pfx}$ (if $\\texttt{anycast}$ is present). Next, *Integer* $x$ is the $\\texttt{workchain\\_id}$, and *Slice* $s$ contains the $\\texttt{address}$.\n- $\\texttt{addr\\_var}$ is represented by $t=(3,u,x,s)$, where $u$, $x$, and $s$ have the same meaning as for $\\texttt{addr\\_std}$.\n\nThe following primitives, which use the above conventions, are defined:\n\n- $\\texttt{FA40}$ — $\\texttt{LDMSGADDR}$ ($s$ - $s'$ $s''$), loads from *CellSlice* $s$ the only prefix that is a valid $\\texttt{MsgAddress}$, and returns both this prefix $s'$ and the remainder $s''$ of $s$ as *CellSlice*s.\n- $\\texttt{FA41}$ — $\\texttt{LDMSGADDRQ}$ ($s$ - $s'$ $s''$ $-1$ or $s$ $0$), a quiet version of $\\texttt{LDMSGADDR}$: on success, pushes an extra $-1$; on failure, pushes the original $s$ and a zero.\n- $\\texttt{FA42}$ — $\\texttt{PARSEMSGADDR}$ ($s$ - $t$), decomposes *CellSlice* $s$ containing a valid $\\texttt{MsgAddress}$ into a *Tuple* $t$ with separate fields of this $\\texttt{MsgAddress}$. If $s$ is not a valid $\\texttt{MsgAddress}$, a cell deserialization exception is thrown.\n- $\\texttt{FA43}$ — $\\texttt{PARSEMSGADDRQ}$ ($s$ - $t$ $-1$ or $0$), a quiet version of $\\texttt{PARSEMSGADDR}$: returns a zero on error instead of throwing an exception.\n- $\\texttt{FA44}$ — $\\texttt{REWRITESTDADDR}$ ($s$ - $x$ $y$), parses *CellSlice* $s$ containing a valid $\\texttt{MsgAddressInt}$ (usually a $\\texttt{msg\\_addr\\_std}$), applies rewriting from the $\\texttt{anycast}$ (if present) to the same-length prefix of the address, and returns both the workchain $x$ and the 256-bit address $y$ as *Integer*s. If the address is not 256-bit, or if $s$ is not a valid serialization of $\\texttt{MsgAddressInt}$, throws a cell deserialization exception.\n- $\\texttt{FA45}$ — $\\texttt{REWRITESTDADDRQ}$ ($s$ - $x$ $y$ $-1$ or $0$), a quiet version of primitive $\\texttt{REWRITESTDADDR}$.\n- $\\texttt{FA46}$ — $\\texttt{REWRITEVARADDR}$ ($s$ - $x$ $s'$), a variant of $\\texttt{REWRITESTDADDR}$ that returns the (rewritten) address as a *Slice* s, even if it is not exactly 256 bit long (represented by a $\\texttt{msg\\_addr\\_var}$).\n- $\\texttt{FA47}$ — $\\texttt{REWRITEVARADDRQ}$ ($s$ - $x$ $s'$ $-1$ or $0$), a quiet version of primitive $\\texttt{REWRITEVARADDR}$.\n- $\\texttt{FA48}$-$\\texttt{FA5F}$ — Reserved for message and address manipulation primitives.\n\n### A.11.10. Outbound message and output action primitives\n\n- $\\texttt{FB00}$ — $\\texttt{SENDRAWMSG}$ ($c$ $x$ - ), sends a raw message contained in *Cell* $c$, which should contain a correctly serialized object $\\texttt{Message}$ $X$, with the only exception that the source address is allowed to have dummy value $\\texttt{addr\\_none}$ (to be automatically replaced with the current smart-contract address), and $\\texttt{ihr\\_fee}$, $\\texttt{fwd\\_fee}$, $\\texttt{created\\_lt}$ and $\\texttt{created\\_at}$ fields can have arbitrary values (to be rewritten with correct values during the action phase of the current transaction). Integer parameter $x$ contains the flags. Currently $x=0$ is used for ordinary messages; $x=128$ is used for messages that are to carry all the remaining balance of the current smart contract (instead of the value originally indicated in the message); $x=64$ is used for messages that carry all the remaining value of the inbound message in addition to the value initially indicated in the new message (if bit 0 is not set, the gas fees are deducted from this amount); $x'=x+1$ means that the sender wants to pay transfer fees separately; $x'=x+2$ means that any errors arising while processing this message during the action phase should be ignored. Finally, $x'=x+32$ means that the current account must be destroyed if its resulting balance is zero. This flag is usually employed together with $+128$.\n- $\\texttt{FB02}$ — $\\texttt{RAWRESERVE}$ ($x$ $y$ - ), creates an output action which would reserve exactly $x$ nanograms (if $y=0$), at most $x$ nanograms (if $y=2$), or all but $x$ nanograms (if $y=1$ or $y=3$), from the remaining balance of the account. It is roughly equivalent to creating an outbound message carrying $x$ nanograms (or $b-x$ nanograms, where $b$ is the remaining balance) to oneself, so that the subsequent output actions would not be able to spend more money than the remainder. Bit $+2$ in $y$ means that the external action does not fail if the specified amount cannot be reserved; instead, all remaining balance is reserved. Bit $+8$ in $y$ means $x\\leftarrow -x$ before performing any further actions. Bit $+4$ in $y$ means that $x$ is increased by the original balance of the current account (before the compute phase), including all extra currencies, before performing any other checks and actions. Currently $x$ must be a non-negative integer, and $y$ must be in the range $0\\ldots 15$.\n- $\\texttt{FB03}$ — $\\texttt{RAWRESERVEX}$ ($x$ $D$ $y$ - ), similar to $\\texttt{RAWRESERVE}$, but also accepts a dictionary $D$ (represented by a *Cell* or *Null*) with extra currencies. In this way currencies other than Grams can be reserved.\n- $\\texttt{FB04}$ — $\\texttt{SETCODE}$ ($c$ - ), creates an output action that would change this smart contract code to that given by *Cell* $c$. Notice that this change will take effect only after the successful termination of the current run of the smart contract.\n- $\\texttt{FB06}$ — $\\texttt{SETLIBCODE}$ ($c$ $x$ - ), creates an output action that would modify the collection of this smart contract libraries by adding or removing library with code given in *Cell* $c$. If $x=0$, the library is actually removed if it was previously present in the collection (if not, this action does nothing). If $x=1$, the library is added as a private library, and if $x=2$, the library is added as a public library (and becomes available to all smart contracts if the current smart contract resides in the masterchain); if the library was present in the collection before, its public/private status is changed according to $x$. Values of $x$ other than $0\\ldots 2$ are invalid.\n- $\\texttt{FB07}$ — $\\texttt{CHANGELIB}$ ($h$ $x$ - ), creates an output action similarly to $\\texttt{SETLIBCODE}$, but instead of the library code accepts its hash as an unsigned 256-bit integer $h$. If $x\\neq0$ and the library with hash $h$ is absent from the library collection of this smart contract, this output action will fail.\n- $\\texttt{FB08}$-$\\texttt{FB3F}$ — Reserved for output action primitives.\n\n## A.12  Debug primitives\n\nOpcodes beginning with $\\texttt{FE}$ are reserved for the *debug primitives*. These primitives have known fixed operation length, and behave as (multibyte) NOP operations. In particular, they never change the stack contents, and never throw exceptions, unless there are not enough bits to completely decode the opcode. However, when invoked in a TVM instance with debug mode enabled, these primitives can produce specific output into the text debug log of the TVM instance, never affecting the TVM state (so that from the perspective of TVM the behavior of debug primitives in debug mode is exactly the same). For instance, a debug primitive might dump all or some of the values near the top of the stack, display the current state of TVM and so on.\n\n### A.12.1. Debug primitives as multibyte NOPs\n\n- $\\texttt{FE}nn$ — $\\texttt{DEBUG}$ $nn$, for $0\\leq nn<240$, is a two-byte NOP.\n- $\\texttt{FEF}nssss$ — $\\texttt{DEBUGSTR}$ $ssss$, for $0\\leq n<16$, is an $(n+3)$-byte NOP, with the $(n+1)$-byte \"contents string\" $ssss$ skipped as well.\n\n### A.12.2. Debug primitives as operations without side-effect\n\nNext we describe the debug primitives that might (and actually are) implemented in a version of TVM. Notice that another TVM implementation is free to use these codes for other debug purposes, or treat them as multibyte NOPs. Whenever these primitives need some arguments from the stack, they inspect these arguments, but leave them intact in the stack. If there are insufficient values in the stack, or they have incorrect types, debug primitives may output error messages into the debug log, or behave as NOPs, but they cannot throw exceptions.\n\n- $\\texttt{FE00}$ — $\\texttt{DUMPSTK}$, dumps the stack (at most the top 255 values) and shows the total stack depth.\n- $\\texttt{FE0}n$ — $\\texttt{DUMPSTKTOP}$ $n$, $1\\leq n<15$, dumps the top $n$ values from the stack, starting from the deepest of them. If there are $d<n$ values available, dumps only $d$ values.\n- $\\texttt{FE10}$ — $\\texttt{HEXDUMP}$, dumps $\\texttt{s0}$ in hexadecimal form, be it a *Slice* or an *Integer*.\n- $\\texttt{FE11}$ — $\\texttt{HEXPRINT}$, similar to $\\texttt{HEXDUMP}$, except the hexadecimal representation of $\\texttt{s0}$ is not immediately output, but rather concatenated to an output text buffer.\n- $\\texttt{FE12}$ — $\\texttt{BINDUMP}$, dumps $\\texttt{s0}$ in binary form, similarly to $\\texttt{HEXDUMP}$.\n- $\\texttt{FE13}$ — $\\texttt{BINPRINT}$, outputs the binary representation of $\\texttt{s0}$ to a text buffer.\n- $\\texttt{FE14}$ — $\\texttt{STRDUMP}$, dumps the *Slice* at $\\texttt{s0}$ as an UTF-8 string.\n- $\\texttt{FE15}$ — $\\texttt{STRPRINT}$, similar to $\\texttt{STRDUMP}$, but outputs the string into a text buffer (without carriage return).\n- $\\texttt{FE1E}$ — $\\texttt{DEBUGOFF}$, disables all debug output until it is re-enabled by a $\\texttt{DEBUGON}$. More precisely, this primitive increases an internal counter, which disables all debug operations (except $\\texttt{DEBUGOFF}$ and $\\texttt{DEBUGON}$) when strictly positive.\n- $\\texttt{FE1F}$ — $\\texttt{DEBUGON}$, enables debug output (in a debug version of TVM).\n- $\\texttt{FE2}n$ — $\\texttt{DUMP s}(n)$, $0\\leq n<15$, dumps $\\texttt{s}(n)$.\n- $\\texttt{FE3}n$ — $\\texttt{PRINT s}(n)$, $0\\leq n<15$, concatenates the text representation of $\\texttt{s}(n)$ (without any leading or trailing spaces or carriage returns) to a text buffer which will be output before the output of any other debug operation.\n- $\\texttt{FEC0}$-$\\texttt{FEEF}$ — Use these opcodes for custom/experimental debug operations.\n- $\\texttt{FEF}nssss$ — $\\texttt{DUMPTOSFMT}$ $ssss$, dumps $\\texttt{s0}$ formatted according to the $(n+1)$-byte string $ssss$. This string might contain (a prefix of) the name of a TL-B type supported by the debugger. If the string begins with a zero byte, simply outputs it (without the first byte) into the debug log. If the string begins with a byte equal to one, concatenates it to a buffer, which will be output before the output of any other debug operation (effectively outputs a string without a carriage return).\n- $\\texttt{FEF}n\\texttt{00}ssss$ — $\\texttt{LOGSTR}$ $ssss$, string $ssss$ is $n$ bytes long.\n- $\\texttt{FEF000}$ — $\\texttt{LOGFLUSH}$, flushes all pending debug output from the buffer into the debug log.\n- $\\texttt{FEF}n\\texttt{01}ssss$ — $\\texttt{PRINTSTR}$ $ssss$, string $ssss$ is $n$ bytes long.\n\n## A.13. Codepage primitives\n\nThe following primitives, which begin with byte $\\texttt{FF}$, typically are used at the very beginning of a smart contract's code or a library subroutine to select another TVM codepage. Notice that we expect all codepages to contain these primitives with the same codes, otherwise switching back to another [codepage](#5-1-8-setting-the-codepage-in-the-code-itself) might be impossible.\n\n- $\\texttt{FF}nn$ — $\\texttt{SETCP}$ $nn$, selects TVM codepage $0\\leq nn<240$. If the codepage is not supported, throws an invalid opcode exception.\n- $\\texttt{FF00}$ — $\\texttt{SETCP0}$, selects TVM (test) codepage zero as described in this document.\n- $\\texttt{FFF}z$ — $\\texttt{SETCP}$ $z-16$, selects TVM codepage $z-16$ for $1\\leq z\\leq 15$. Negative codepages $-13\\ldots-1$ are reserved for restricted versions of TVM needed to validate runs of TVM in other [codepages](#b-2-6-codepage). Negative codepage $-14$ is reserved for experimental codepages, not necessarily compatible between different TVM implementations, and should be disabled in the production versions of TVM.\n- $\\texttt{FFF0}$ — $\\texttt{SETCPX}$ ($c$ - ), selects codepage $c$ with $-2^{15}\\leq c<2^{15}$ passed in the top of the stack.\n\n# B   Formal properties and specifications of TVM\n\nThis appendix discusses certain formal properties of TVM that are necessary for executing smart contracts in the TON Blockchain and validating such executions afterwards.\n\n## B.1  Serialization of the TVM state\n\nRecall that a virtual machine used for executing smart contracts in a blockchain must be *deterministic*, otherwise the validation of each execution would require the inclusion of all intermediate steps of the execution into a block, or at least of the choices made when indeterministic operations have been performed.\n\nFurthermore, the *state* of such a virtual machine must be (uniquely) serializable, so that even if the state itself is not usually included in a block, its *hash* is still well-defined and can be included into a block for verification purposes.\n\n### B.1.1. TVM stack values\n\nTVM stack values can be serialized as follows:\n\n```\nvm_stk_tinyint#01 value:int64 = VmStackValue;\nvm_stk_int#0201_ value:int257 = VmStackValue;\nvm_stk_nan#02FF = VmStackValue;\nvm_stk_cell#03 cell:^Cell = VmStackValue;\n_ cell:^Cell st_bits:(## 10) end_bits:(## 10) \n  { st_bits <= end_bits } \n  st_ref:(#<= 4) end_ref:(#<= 4) \n  { st_ref <= end_ref } = VmCellSlice;\nvm_stk_slice#04 _:VmCellSlice  = VmStackValue;\nvm_stk_builder#05 cell:^Cell = VmStackValue;\nvm_stk_cont#06 cont:VmCont = VmStackValue;\n```\n\nOf these, $\\texttt{vm\\_stk\\_tinyint}$ is never used by TVM in codepage zero; it is used only in restricted modes.\n\n### B.1.2. TVM stack\n\nThe TVM stack can be serialized as follows:\n\n```\nvm_stack#_ depth:(## 24) stack:(VmStackList depth) = VmStack;\nvm_stk_cons#_ {n:#} head:VmStackValue tail:^(VmStackList n) \n  = VmStackList (n + 1);\nvm_stk_nil#_ = VmStackList 0;\n```\n\n### B.1.3. TVM control registers\n\nControl registers in TVM can be serialized as follows:\n\n```\n_ cregs:(HashmapE 4 VmStackValue) = VmSaveList;\n```\n\n### B.1.4. TVM gas limits\n\nGas limits in TVM can be serialized as follows:\n\n```\ngas_limits#_ remaining:int64 _:^[ \n  max_limit:int64 cur_limit:int64 credit:int64 ]\n  = VmGasLimits;\n```\n\n### B.1.5. TVM library environment\n\nThe TVM library environment can be serialized as follows:\n\n```\n_ libraries:(HashmapE 256 ^Cell) = VmLibraries;\n```\n\n### B.1.6. TVM continuations\n\nContinuations in TVM can be serialized as follows:\n\n```\nvmc_std$00 nargs:(## 22) stack:(Maybe VmStack) save:VmSaveList\n   cp:int16 code:VmCellSlice = VmCont;\nvmc_envelope$01 nargs:(## 22) stack:(Maybe VmStack) \n   save:VmSaveList next:^VmCont = VmCont;\nvmc_quit$1000 exit_code:int32 = VmCont;\nvmc_quit_exc$1001 = VmCont;\nvmc_until$1010 body:^VmCont after:^VmCont = VmCont;\nvmc_again$1011 body:^VmCont = VmCont;\nvmc_while_cond$1100 cond:^VmCont body:^VmCont \n   after:^VmCont = VmCont;\nvmc_while_body$1101 cond:^VmCont body:^VmCont\n   after:^VmCont = VmCont;\nvmc_pushint$1111 value:int32 next:^VmCont = VmCont;\n```\n\n ### B.1.7. TVM state\n\nThe total state of TVM can be serialized as follows:\n\n```\nvms_init$00 cp:int16 step:int32 gas:GasLimits \n  stack:(Maybe VmStack) save:VmSaveList code:VmCellSlice\n  lib:VmLibraries = VmState;\nvms_exception$01 cp:int16 step:int32 gas:GasLimits \n  exc_no:int32 exc_arg:VmStackValue \n  save:VmSaveList lib:VmLibraries = VmState;\nvms_running$10 cp:int16 step:int32 gas:GasLimits stack:VmStack\n  save:VmSaveList code:VmCellSlice lib:VmLibraries\n  = VmState;\nvms_finished$11 cp:int16 step:int32 gas:GasLimits \n  exit_code:int32 no_gas:Boolean stack:VmStack \n  save:VmSaveList lib:VmLibraries = VmState;\n```\n\nWhen TVM is initialized, its state is described by a $\\texttt{vms\\_init}$, usually with $\\texttt{step}$ set to zero. The step function of TVM does nothing to a $\\texttt{vms\\_finished}$ state, and transforms all other states into $\\texttt{vms\\_running}$, $\\texttt{vms\\_exception}$, or $\\texttt{vms\\_finished}$, with $\\texttt{step}$ increased by one.\n\n## B.2  Step function of TVM\n\nA formal specification of TVM would be completed by the definition of a *step function* $f:\\textit{VmState}\\to\\textit{VmState}$. This function deterministically transforms a valid VM state into a valid subsequent VM state, and is allowed to throw exceptions or return an invalid subsequent state if the original state was invalid.\n\n### B.2.1. A high-level definition of the step function\n\nWe might present a very long formal definition of the TVM step function in a high-level functional programming language. Such a specification, however, would mostly be useful as a reference for the (human) developers. We have chosen another approach, better adapted to automated formal verification by computers.\n\n### B.2.2. An operational definition of the step function\n\nNotice that the step function $f$ is a well-defined computable function from trees of cells into trees of cells. As such, it can be computed by a universal Turing machine. Then a program $P$ computing $f$ on such a machine would provide a machine-checkable specification of the step function $f$. This program $P$ effectively is an *emulator* of TVM on this Turing machine.\n\n### B.2.3. A reference implementation of the TVM emulator inside TVM\n\nWe see that the step function of TVM may be defined by a reference implementation of a TVM emulator on another machine. An obvious idea is to use TVM itself, since it is well-adapted to working with trees of cells. However, an emulator of TVM inside itself is not very useful if we have doubts about a particular implementation of TVM and want to check it. For instance, if such an emulator interpreted a $\\texttt{DICTISET}$ instruction simply by invoking this instruction itself, then a bug in the underlying implementation of TVM would remain unnoticed.\n\n### B.2.4. Reference implementation inside a minimal version of TVM\n\nWe see that using TVM itself as a host machine for a reference implementation of TVM emulator would yield little insight. A better idea is to define a *stripped-down version of TVM*, which supports only the bare minimum of primitives and 64-bit integer arithmetic, and provide a reference implementation $P$ of the TVM step function $f$ for this stripped-down version of TVM.\n\nIn that case, one must carefully implement and check only a handful of primitives to obtain a stripped-down version of TVM, and compare the reference implementation $P$ running on this stripped-down version to the full custom TVM implementation being verified. In particular, if there are any doubts about the validity of a specific run of a custom TVM implementation, they can now be easily resolved with the aid of the reference implementation.\n\n### B.2.5. Relevance for the TON Blockchain\n\nThe TON Blockchain adopts this approach to validate the runs of TVM (e.g., those used for processing inbound messages by smart contracts) when the validators' results do not match one another. In this case, a reference implementation of TVM, stored inside the masterchain as a configurable parameter (thus defining the current revision of TVM), is used to obtain the correct result.\n\n### B.2.6. Codepage $-1$\n\n*Codepage $-1$* of TVM is reserved for the stripped-down version of TVM. Its main purpose is to execute the reference implementation of the step function of the full TVM. This codepage contains only special versions of arithmetic primitives working with \"tiny integers\" (64-bit signed integers); therefore, TVM's 257-bit *Integer* arithmetic must be defined in terms of 64-bit arithmetic. Elliptic curve cryptography primitives are also implemented directly in codepage $-1$, without using any third-party libraries. Finally, a reference implementation of the $\\texttt{Sha}$ hash function is also provided in codepage $-1$.\n\n### B.2.7. Codepage $-2$\n\nThis bootstrapping process could be iterated even further, by providing an emulator of the stripped-down version of TVM written for an even simpler version of TVM that supports only boolean values (or integers 0 and 1)—a \"codepage $-2$\". All 64-bit arithmetic used in codepage $-1$ would then need to be defined by means of boolean operations, thus providing a reference implementation for the stripped-down version of TVM used in codepage $-1$. In this way, if some of the TON Blockchain validators did not agree on the results of their 64-bit arithmetic, they could regress to this reference implementation to find the correct answer.<a id=\"ref-fn30\"></a><sup>[30](#fn30)</sup>\n \n---\n\n\n# C   Code density of stack and register machines\n\nThis appendix extends the general consideration of [stack manipulation](#2-2-stack-manipulation-primitives) primitives, explaining the choice of such primitives for TVM, with a comparison of stack machines and register machines in terms of the quantity of primitives used and the code density. We do this by comparing the machine code that might be generated by an optimizing compiler for the same source files, for different (abstract) stack and register machines.\n\nIt turns out that the stack machines (at least those equipped with the [basic stack manipulation](#2-2-1-basic-stack-manipulation-primitives) primitives have far superior code density. Furthermore, the stack machines have excellent extendability with respect to additional arithmetic and arbitrary data processing operations, especially if one considers machine code automatically generated by optimizing compilers.\n\n## C.1   Sample leaf function\n\nWe start with a comparison of machine code generated by an (imaginary) optimizing compiler for several abstract register and stack machines, corresponding to the same high-level language source code that contains the definition of a leaf function (i.e., a function that does not call any other functions). For both the register machines and stack machines, we observe the notation and [conventions](#2-1-stack-calling-conventions).\n\n### C.1.1. Sample source file for a leaf function\n\nThe source file we consider contains one function $f$ that takes six integer arguments $a$, $b$, $c$, $d$, $e$, and $f$ and returns two integer values, $x$ and $y$, which are the solutions of the system of two linear equations:\n\n$$\n\\begin{cases}\nax + by = e \\\\\ncx + dy = f\n\\end{cases}\n\\tag{6}\n$$\n\nThe source code of the function, in a programming language similar to C, might look as follows:\n\n```\n(int, int) f(int a, int b, int c, int d, int e, int f) {\n  int D = a*d - b*c;\n  int Dx = e*d - b*f;\n  int Dy = a*f - e*c;\n  return (Dx / D, Dy / D);\n}\n```\n\nWe assume that the [register machines](#2-1-stack-calling-conventions) we consider accept the six parameters $a$ $\\ldots$ $f$ in registers $\\texttt{r0}$ $\\ldots$ $\\texttt{r5}$, and return the two values $x$ and $y$ in $\\texttt{r0}$ and $\\texttt{r1}$. We also assume that the register machines have 16 registers, and that the stack machine can directly access $\\texttt{s0}$ to $\\texttt{s15}$ by its stack manipulation primitives; the stack machine will accept the parameters in $\\texttt{s5}$ to $\\texttt{s0}$, and return the two values in $\\texttt{s0}$ and $\\texttt{s1}$, somewhat similarly to the register machine. Finally, we assume at first that the register machine is allowed to destroy values in all registers (which is slightly unfair towards the stack machine); this assumption will be revisited later.\n\n### C.1.2. Three-address register machine\n\nThe machine code (or rather the corresponding assembly code) for a three-address [register machine](#2-1-7-arguments-to-arithmetic-primitives-on-register-machines)) might look as follows:\n\n```\nIMUL r6,r0,r3  // r6 := r0 * r3 = ad\nIMUL r7,r1,r2  // r7 := bc\nSUB r6,r6,r7   // r6 := ad-bc = D\nIMUL r3,r4,r3  // r3 := ed\nIMUL r1,r1,r5  // r1 := bf\nSUB r3,r3,r1   // r3 := ed-bf = Dx\nIMUL r1,r0,r5  // r1 := af\nIMUL r7,r4,r2  // r7 := ec\nSUB r1,r1,r7   // r1 := af-ec = Dy\nIDIV r0,r3,r6  // x := Dx/D\nIDIV r1,r1,r6  // y := Dy/D\nRET\n```\n\nWe have used 12 operations and at least 23 bytes (each operation uses $3\\times 4=12$ bits to indicate the three registers involved, and at least 4 bits to indicate the operation performed; thus we need two or three bytes to encode each operation). A more realistic estimate would be 34 (three bytes for each arithmetic operation) or 31 bytes (two bytes for addition and subtraction, three bytes for multiplication and division).\n\n### C.1.3. Two-address register machine\n\nThe machine code for a two-address register machine might look as follows:\n\n```\nMOV r6,r0   // r6 := r0 = a\nMOV r7,r1   // r7 := b\nIMUL r6,r3  // r6 := r6*r3 = ad\nIMUL r7,r2  // r7 := bc\nIMUL r3,r4  // r3 := de\nIMUL r1,r5  // r1 := bf\nSUB r6,r7   // r6 := ad-bc = D\nIMUL r5,r0  // r5 := af\nSUB r3,r1   // r3 := de-bf = Dx\nIMUL r2,r4  // r2 := ce\nMOV r0,r3   // r0 := Dx\nSUB r5,r2   // r5 := af-ce = Dy\nIDIV r0,r6  // r0 := x = Dx/D\nMOV r1,r5   // r1 := Dy\nIDIV r1,r6  // r1 := Dy/D\nRET\n```\n\nWe have used 16 operations; optimistically assuming each of them (with the exception of $\\texttt{RET}$) can be encoded by two bytes, this code would require 31 bytes.<a id=\"ref-fn31\"></a><sup>[31](#fn31)</sup>\n\n### C.1.4. One-address register machine\n\nThe machine code for a one-address register machine might look as follows:\n\n```\nMOV r8,r0  // r8 := r0 = a\nXCHG r1    // r0 <-> r1; r0 := b, r1 := a\nMOV r6,r0  // r6 := b\nIMUL r2    // r0 := r0*r2; r0 := bc\nMOV r7,r0  // r7 := bc\nMOV r0,r8  // r0 := a\nIMUL r3    // r0 := ad\nSUB r7     // r0 := ad-bc = D\nXCHG r1    // r1 := D,  r0 := b\nIMUL r5    // r0 := bf\nXCHG r3    // r0 := d,  r3 := bf\nIMUL r4    // r0 := de\nSUB r3     // r0 := de-bf = Dx\nIDIV r1    // r0 := Dx/D = x\nXCHG r2    // r0 := c,  r2 := x\nIMUL r4    // r0 := ce\nXCHG r5    // r0 := f,  r5 := ce\nIMUL r8    // r0 := af\nSUB r5     // r0 := af-ce = Dy\nIDIV r1    // r0 := Dy/D = y\nMOV r1,r0  // r1 := y\nMOV r0,r2  // r0 := x\nRET\n```\n\nWe have used 23 operations; if we assume one-byte encoding for all arithmetic operations and $\\texttt{XCHG}$, and two-byte encodings for $\\texttt{MOV}$, the total size of the code will be 29 bytes. Notice, however, that to obtain the compact code shown above we had to choose a specific order of computation, and made heavy use of the commutativity of multiplication. (For example, we compute $bc$ before $af$, and $af-bc$ immediately after $af$.) It is not clear whether a compiler would be able to make all such optimizations by itself.\n\n### C.1.5. Stack machine with basic stack primitives\n\nThe machine code for a stack machine equipped with [basic stack manipulation](#2-2-1-basic-stack-manipulation-primitives) primitives might look as follows:\n\n\n```\nPUSH s5    // a b c d e f a\nPUSH s3    // a b c d e f a d\nIMUL       // a b c d e f ad\nPUSH s5    // a b c d e f ad b\nPUSH s5    // a b c d e f ad b c\nIMUL       // a b c d e f ad bc\nSUB        // a b c d e f ad-bc\nXCHG s3    // a b c ad-bc e f d\nPUSH s2    // a b c ad-bc e f d e\nIMUL       // a b c ad-bc e f de\nXCHG s5    // a de c ad-bc e f b\nPUSH s1    // a de c ad-bc e f b f\nIMUL       // a de c ad-bc e f bf\nXCHG s1,s5 // a f c ad-bc e de bf\nSUB        // a f c ad-bc e de-bf\nXCHG s3    // a f de-bf ad-bc e c\nIMUL       // a f de-bf ad-bc ec\nXCHG s3    // a ec de-bf ad-bc f\nXCHG s1,s4 // ad-bc ec de-bf a f\nIMUL       // D ec Dx af\nXCHG s1    // D ec af Dx\nXCHG s2    // D Dx af ec\nSUB        // D Dx Dy\nXCHG s1    // D Dy Dx\nPUSH s2    // D Dy Dx D\nIDIV       // D Dy x\nXCHG s2    // x Dy D\nIDIV       // x y\nRET\n```\n\nWe have used 29 operations; assuming one-byte encodings for all stack operations involved (including $\\texttt{XCHG s1,s}(i)$), we have used 29 code bytes as well. Notice that with one-byte encoding, the \"unsystematic\" operation $\\texttt{ROT}$ (equivalent to $\\texttt{XCHG s1}$; $\\texttt{XCHG s2}$) would reduce the operation and byte count to 28. This shows that such \"unsystematic\" operations, borrowed from Forth, may indeed reduce the code size on some occasions.\n\nNotice as well that we have implicitly used the commutativity of multiplication in this code, computing $de-bf$ instead of $ed-bf$ as specified in high-level language source code. If we were not allowed to do so, an extra $\\texttt{XCHG s1}$ would need to be inserted before the third $\\texttt{IMUL}$, increasing the total size of the code by one operation and one byte.\n\nThe code presented above might have been produced by a rather unsophisticated compiler that simply computed all expressions and subexpressions in the order they appear, then rearranged the arguments near the [top of the stack](#2-2-2-basic-stack-manipulation-primitives-suffice) before each operation. The only \"manual\" optimization done here involves computing $ec$ before $af$; one can check that the other order would lead to slightly shorter code of 28 operations and bytes (or 29, if we are not allowed to use the commutativity of multiplication), but the $\\texttt{ROT}$ optimization would not be applicable.\n \n### C.1.6. Stack machine with compound stack primitives\n\nA stack machine with [compound stack](#2-2-3-compound-stack-manipulation-primitives) primitives would not significantly improve code density of the code presented above, at least in terms of bytes used. The only difference is that, if we were not allowed to use commutativity of multiplication, the extra $\\texttt{XCHG s1}$ inserted before the third $\\texttt{IMUL}$ might be combined with two previous operations $\\texttt{XCHG s3}$, $\\texttt{PUSH s2}$ into one compound operation $\\texttt{PUXC s2,s3}$; we provide the resulting code below. To make this less redundant, we show a version of the code that computes subexpression $af$ before $ec$ as specified in the original source file. We see that this replaces six operations (starting from line 15) with five other operations, and disables the $\\texttt{ROT}$ optimization:\n\n```\nPUSH s5    // a b c d e f a\nPUSH s3    // a b c d e f a d\nIMUL       // a b c d e f ad\nPUSH s5    // a b c d e f ad b\nPUSH s5    // a b c d e f ad b c\nIMUL       // a b c d e f ad bc\nSUB        // a b c d e f ad-bc\nPUXC s2,s3 // a b c ad-bc e f e d\nIMUL       // a b c ad-bc e f ed\nXCHG s5    // a ed c ad-bc e f b\nPUSH s1    // a ed c ad-bc e f b f\nIMUL       // a ed c ad-bc e f bf\nXCHG s1,s5 // a f c ad-bc e ed bf\nSUB        // a f c ad-bc e ed-bf\nXCHG s4    // a ed-bf c ad-bc e f\nXCHG s1,s5 // e Dx c D a f\nIMUL       // e Dx c D af\nXCHG s2    // e Dx af D c\nXCHG s1,s4 // D Dx af e c\nIMUL       // D Dx af ec\nSUB        // D Dx Dy\nXCHG s1    // D Dy Dx\nPUSH s2    // D Dy Dx D\nIDIV       // D Dy x\nXCHG s2    // x Dy D\nIDIV       // x y\nRET\n```\n\nWe have used a total of 27 operations and 28 bytes, the same as the previous version (with the $\\texttt{ROT}$ optimization). However, we did not use the commutativity of multiplication here, so we can say that compound stack manipulation primitives enable us to reduce the code size from 29 to 28 bytes.\n\nYet again, notice that the above code might have been generated by an unsophisticated compiler. Manual optimizations might lead to more compact code; for instance, we could use compound operations such as $\\texttt{XCHG3}$ to prepare in advance not only the correct values of $\\texttt{s0}$ and $\\texttt{s1}$ for the next arithmetic operation, but also the value of $\\texttt{s2}$ for the arithmetic operation after that. The next section provides an example of such an optimization.\n\n### C.1.7. Stack machine with compound stack primitives and manually optimized code\n\nThe previous version of code for a stack machine with compound stack primitives can be manually optimized as follows.\n\nBy interchanging $\\texttt{XCHG}$ operations with preceding $\\texttt{XCHG}$, $\\texttt{PUSH}$, and arithmetic operations whenever possible, we obtain code fragment $\\texttt{XCHG s2,s6}$; $\\texttt{XCHG s1,s0}$; $\\texttt{XCHG s0,s5}$, which can then be replaced by compound operation $\\texttt{XCHG3 s6,s0,s5}$. This compound operation would admit a two-byte encoding, thus leading to 27-byte code using only 21 operations:\n\n```\nPUSH2 s5,s2    // a b c d e f a d\nIMUL           // a b c d e f ad\nPUSH2 s5,s4    // a b c d e f ad b c\nIMUL           // a b c d e f ad bc\nSUB            // a b c d e f ad-bc\nPUXC s2,s3     // a b c ad-bc e f e d\nIMUL           // a b c D e f ed\nXCHG3 s6,s0,s5 //  (same as XCHG s2,s6; XCHG s1,s0; XCHG s0,s5)\n               // e f c D a ed b\nPUSH s5        // e f c D a ed b f\nIMUL           // e f c D a ed bf\nSUB            // e f c D a ed-bf\nXCHG s4        // e Dx c D a f\nIMUL           // e Dx c D af\nXCHG2 s4,s2    // D Dx af e c\nIMUL           // D Dx af ec\nSUB            // D Dx Dy\nXCPU s1,s2     // D Dy Dx D\nIDIV           // D Dy x\nXCHG s2        // x Dy D\nIDIV           // x y\nRET\n```\n\nIt is interesting to note that this version of stack machine code contains only 9 stack manipulation primitives for 11 arithmetic operations. It is not clear, however, whether an optimizing compiler would be able to reorganize the code in such a manner by itself.\n\n## C.2   Comparison of machine code for sample leaf function\n\n[Table 1](#table-1) summarizes the properties of machine code corresponding to the [same source file](#c-1-1-sample-source-file-for-a-leaf-function), generated for a hypothetical [three-address register machine](#c-1-2-three-address-register-machine), with both \"optimistic\" and \"realistic\" instruction encodings; a [two-address machine](#c-1-3-two-address-register-machine); a [one-address machine](#c-1-4-one-address-register-machine); and a stack machine, similar to TVM, using either only the [basic stack manipulation](#c-1-5-stack-machine-with-basic-stack-primitives) primitives or both the basic and the [composite stack](#c-1-7-stack-machine-with-compound-stack-primitives-and-manually-optimized-code) primitives.\n\nThe meaning of the columns in [Table 1](#table-1) is as follows:\n\n- \"Operations\" — The quantity of instructions used, split into \"data\" (i.e., register move and exchange instructions for register machines, and stack manipulation instructions for stack machines) and \"arithmetic\" (instructions for adding, subtracting, multiplying and dividing integer numbers). The \"total\" is one more than the sum of these two, because there is also a one-byte $\\texttt{RET}$ instruction at the end of machine code.\n- \"Code bytes\" — The total amount of code bytes used.\n- \"Opcode space\" — The portion of \"opcode space\" (i.e., of possible choices for the first byte of the encoding of an instruction) used by data and arithmetic instructions in the assumed instruction encoding. For example, the \"optimistic\" encoding for the three-address machine assumes two-byte encodings for all arithmetic instructions *op* $\\texttt{r}(i)\\texttt{, r}(j)\\texttt{, r}(k)$. Each arithmetic instruction would then consume portion $16/256=1/16$ of the opcode space. Notice that for the stack machine we have assumed one-byte encodings for $\\texttt{XCHG s}(i)$, $\\texttt{PUSH s}(i)$ and $\\texttt{POP s}(i)$ in all cases, augmented by $\\texttt{XCHG s1,s}(i)$ for the basic stack instructions case only. As for the compound stack operations, we have assumed two-byte encodings for $\\texttt{PUSH3}$, $\\texttt{XCHG3}$, $\\texttt{XCHG2}$, $\\texttt{XCPU}$, $\\texttt{PUXC}$, $\\texttt{PUSH2}$, but not for $\\texttt{XCHG s1,s}(i)$.\n\n<a id=\"table-1\"></a>\n\n| Machine | Operations |  |  | Code bytes |  |  | Opcode space |  |  |\n|---------|------------|-------|-------|------------|-------|-------|--------------|-------|-------|\n|         | data | arith | total | data | arith | **total** | data | **arith** | total |\n| 3-addr. (opt.) | 0 | 11 | 12 | 0 | 22 | **23** | 0/256 | **64/256** | 65/256 |\n| 3-addr. (real.) | 0 | 11 | 12 | 0 | 30 | **31** | 0/256 | **34/256** | 35/256 |\n| 2-addr. | 4 | 11 | 16 | 8 | 22 | **31** | 1/256 | **4/256** | 6/256 |\n| 1-addr. | 11 | 11 | 23 | 17 | 11 | **29** | 17/256 | **64/256** | 82/256 |\n| stack (basic) | 16 | 11 | 28 | 16 | 11 | **28** | 64/256 | **4/256** | 69/256 |\n| stack (comp.) | 9 | 11 | 21 | 15 | 11 | **27** | 84/256 | **4/256** | 89/256 |\n\n**Table 1.** A summary of machine code properties for hypothetical 3-address, 2-address, 1-address, and stack machines, generated for a [sample leaf function](#c-1-1-sample-source-file-for-a-leaf-function). The two most important columns, reflecting code density and extendability to other operations, are marked by bold font. Smaller values are better in both of these columns.\n\n\nThe \"code bytes\" column reflects the density of the code for the specific sample source. However, \"opcode space\" is also important, because it reflects the extendability of the achieved density to other classes of operations (e.g., if one were to complement arithmetic operations with string manipulation operations and so on). Here the \"arithmetic\" subcolumn is more important than the \"data\" subcolumn, because no further data manipulation operations would be required for such extensions.\n\nWe see that the three-address register machine with the \"optimistic\" encoding, assuming two-byte encodings for all three-register arithmetic operations, achieves the best code density, requiring only 23 bytes. However, this comes at a price: each arithmetic operation consumes 1/16 of the opcode space, so the four operations already use a quarter of the opcode space. At most 11 other operations, arithmetic or not, might be added to this architecture while preserving such high code density. On the other hand, when we consider the \"realistic\" encoding for the three-address machine, using two-byte encodings only for the most frequently used addition/subtraction operations (and longer encodings for less frequently used multiplication/division operations, reflecting the fact that the possible extension operations would likely fall in this class), then the three-address machine ceases to offer such attractive code density.\n\nIn fact, the two-address machine becomes equally attractive at this point: it is capable of achieving the same code size of 31 bytes as the three-address machine with the \"realistic\" encoding, using only 6/256 of the opcode space for this! However, 31 bytes is the worst result in this table.\n\nThe one-address machine uses 29 bytes, slightly less than the two-address machine. However, it utilizes a quarter of the opcode space for its arithmetic operations, hampering its extendability. In this respect it is similar to the three-address machine with the \"optimistic\" encoding, but requires 29 bytes instead of 23! So there is no reason to use the one-address machine at all, in terms of extendability (reflected by opcode space used for arithmetic operations) compared to code density.\n\nFinally, the stack machine wins the competition in terms of code density (27 or 28 bytes), losing only to the three-address machine with the \"optimistic\" encoding (which, however, is terrible in terms of extendability).\n\nTo summarize: the two-address machine and stack machine achieve the best extendability with respect to additional arithmetic or data processing instructions (using only 1/256 of code space for each such instruction), while the stack machine additionally achieves the best code density by a small margin. The stack machine utilizes a significant part of its code space (more than a quarter) for data (i.e., stack) manipulation instructions; however, this does not seriously hamper extendability, because the stack manipulation instructions occupy a constant part of the opcode space, regardless of all other instructions and extensions.\n\nWhile one might still be tempted to use a two-address register machine, we will explain [shortly](#c-3-sample-non-leaf-function) why the two-address register machine offers worse code density and extendability in practice than it appears based on this table.\n\nAs for the choice between a stack machine with only basic stack manipulation primitives or one supporting compound stack primitives as well, the case for the more sophisticated stack machine appears to be weaker: it offers only one or two fewer bytes of code at the expense of using considerably more opcode space for stack manipulation, and the optimized code using these additional instructions is hard for programmers to write and for compilers to automatically generate.\n\n### C.2.1. Register calling conventions: some registers must be preserved by functions\n\nUp to this point, we have considered the machine code of only one function, without taking into account the interplay between this function and other functions in the same program.\n\nUsually a program consists of more than one function, and when a function is not a \"simple\" or \"leaf\" function, it must call other functions. Therefore, it becomes important whether a called function preserves all or at least some registers. If it preserves all registers except those used to return results, the caller can safely keep its local and temporary variables in certain registers; however, the callee needs to save all the registers it will use for its temporary values somewhere (usually into the stack, which also exists on register machines), and then restore the original values. On the other hand, if the called function is allowed to destroy all registers, it can be written in the manner described in [C.1.2](#c-1-2-three-address-register-machine), [C.1.3](#c-1-3-two-address-register-machine), and [C.1.4](#c-1-4-one-address-register-machine), but the caller will now be responsible for saving all its temporary values into the stack before the call, and restoring these values afterwards.\n\nIn most cases, calling conventions for register machines require preservation of some but not all registers. We will assume that $m\\leq n$ registers will be preserved by functions (unless they are used for return values), and that these registers are $\\texttt{r}$ $(n-m)$ $\\ldots$ $\\texttt{r}$ $(n-1)$. Case $m=0$ corresponds to the case \"the callee is free to destroy all registers\" considered so far; it is quite painful for the caller. Case $m=n$ corresponds to the case \"the callee must preserve all registers\"; it is quite painful for the callee, as we will see in a moment. Usually a value of $m$ around $n/2$ is used in practice.\n\nThe following sections consider cases $m=0$, $m=8$, and $m=16$ for our register machines with $n=16$ registers.\n\n### C.2.2. Case $m=0$: no registers to preserve\n\nThis case has been considered and summarized in [C.2](#c-2-comparison-of-machine-code-for-sample-leaf-function) and [Table 1](#table-1) above.\n\n### C.2.3. Case $m=n=16$: all registers must be preserved\n\nThis case is the most painful one for the called function. It is especially difficult for leaf functions like the one we have been considering, which do not benefit at all from the fact that other functions preserve some registers when called—they do not call any functions, but instead must preserve all registers themselves.\n\nIn order to estimate the consequences of assuming $m=n=16$, we will assume that all our register machines are equipped with a stack, and with one-byte instructions $\\texttt{PUSH r}(i)$ and $\\texttt{POP r}(i)$, which push or pop a register into/from the stack. For example, the [three-address machine](#c-1-2-three-address-register-machine) code destroys the values in registers $\\texttt{r2}$, $\\texttt{r3}$, $\\texttt{r6}$, and $\\texttt{r7}$; this means that the code of this function must be augmented by four instructions $\\texttt{PUSH r2}$; $\\texttt{PUSH r3}$; $\\texttt{PUSH r6}$; $\\texttt{PUSH r7}$ at the beginning, and by four instructions $\\texttt{POP r7}$; $\\texttt{POP r6}$; $\\texttt{POP r3}$; $\\texttt{POP r2}$ right before the $\\texttt{RET}$ instruction, in order to restore the original values of these registers from the stack. These four additional $\\texttt{PUSH}$/$\\texttt{POP}$ pairs would increase the operation count and code size in bytes by $4\\times 2=8$. A similar analysis can be done for other register machines as well, leading to [Table 2](#table-2).\n\n<a id=\"table-2\"></a>\n\n| Machine | $\\mathit{r}$ | Operations |  |  | Code bytes |  |  | Opcode space |  |  |\n|---------|--------------|------------|-------|-------|------------|-------|-------|--------------|-------|-------|\n|         |              | data | arith | total | data | arith | **total** | data | **arith** | total |\n| 3-addr. (opt.) | *4* | 8 | 11 | 20 | 8 | 22 | **31** | 32/256 | **64/256** | 97/256 |\n| 3-addr. (real.) | *4* | 8 | 11 | 20 | 8 | 30 | **39** | 32/256 | **34/256** | 67/256 |\n| 2-addr. | *5* | 14 | 11 | 26 | 18 | 22 | **41** | 33/256 | **4/256** | 38/256 |\n| 1-addr. | *6* | 23 | 11 | 35 | 29 | 11 | **41** | 49/256 | **64/256** | 114/256 |\n| stack (basic) | *0* | 16 | 11 | 28 | 16 | 11 | **28** | 64/256 | **4/256** | 69/256 |\n| stack (comp.) | *0* | 9 | 11 | 21 | 15 | 11 | **27** | 84/256 | **4/256** | 89/256 |\n\n**Table 2.** A summary of machine code properties for hypothetical 3-address, 2-address, 1-address, and stack machines, generated for a [sample leaf function](#c-1-1-sample-source-file-for-a-leaf-function), assuming all of the 16 registers must be preserved by called functions ($m=n=16$). The new column labeled $r$ denotes the number of registers to be saved and restored, leading to $2r$ more operations and code bytes compared to [Table 1](#table-1). Newly-added $\\texttt{PUSH}$ and $\\texttt{POP}$ instructions for register machines also utilize 32/256 of the opcode space. The two rows corresponding to stack machines remain unchanged.\n\nWe see that under these assumptions the stack machines are the obvious winners in terms of code density, and are in the winning group with respect to extendability.\n\n### C.2.4. Case $m = 8$, $n = 16$: registers $\\texttt{r8}$ $\\ldots$ $\\texttt{r15}$ must be preserved\n\nThe analysis of this case is similar to the previous one. The results are summarized in [Table 3](#table-3).\n\n<a id=\"table-3\"></a>\n\n| Machine | $\\mathit{r}$ | Operations |  |  | Code bytes |  |  | Opcode space |  |  |\n|---------|--------------|------------|-------|-------|------------|-------|-------|--------------|-------|-------|\n|         |              | data | arith | total | data | arith | **total** | data | **arith** | total |\n| 3-addr. (opt.) | *0* | 0 | 11 | 12 | 0 | 22 | **23** | 32/256 | **64/256** | 97/256 |\n| 3-addr. (real.) | *0* | 0 | 11 | 12 | 0 | 30 | **31** | 32/256 | **34/256** | 67/256 |\n| 2-addr. | *0* | 4 | 11 | 16 | 8 | 22 | **31** | 33/256 | **4/256** | 38/256 |\n| 1-addr. | *1* | 13 | 11 | 25 | 19 | 11 | **31** | 49/256 | **64/256** | 114/256 |\n| stack (basic) | *0* | 16 | 11 | 28 | 16 | 11 | **28** | 64/256 | **4/256** | 69/256 |\n| stack (comp.) | *0* | 9 | 11 | 21 | 15 | 11 | **27** | 84/256 | **4/256** | 89/256 |\n\n**Table 3.** A summary of machine code properties for hypothetical 3-address, 2-address, 1-address and stack machines, generated for a [sample leaf function](#c-1-1-sample-source-file-for-a-leaf-function), assuming that only the last 8 of the 16 registers must be preserved by called functions ($m=8$, $n=16$). This table is similar to [Table 2](#table-2), but has smaller values of $r$.\n\nNotice that the resulting table is very similar to [Table 1](#table-1), apart from the \"Opcode space\" columns and the row for the one-address machine. Therefore, the conclusions of [C.2](#c-2-comparison-of-machine-code-for-sample-leaf-function) still apply in this case, with some minor modifications. We must emphasize, however, that *these conclusions are valid only for leaf functions, i.e., functions that do not call other functions*. Any program aside from the very simplest will have many non-leaf functions, especially if we are minimizing resulting machine code size (which prevents inlining of functions in most cases).\n\n### C.2.5. A fairer comparison using a binary code instead of a byte code\n\nThe reader may have noticed that our preceding discussion of $k$-address register machines and stack machines depended very much on our insistence that complete instructions be encoded by an integer number of bytes. If we had been allowed to use a \"bit\" or \"binary code\" instead of a byte code for encoding instructions, we could more evenly balance the opcode space used by different machines. For instance, the opcode of `SUB` for a three-address machine had to be either 4-bit (good for code density, bad for opcode space) or 12-bit (very bad for code density), because the complete instruction has to occupy a multiple of eight bits (e.g., 16 or 24 bits), and $3\\cdot 4=12$ of those bits have to be used for the three register names.\n\nTherefore, let us get rid of this restriction.\n\nNow that we can use any number of bits to encode an instruction, we can choose all opcodes of the same length for all the machines considered. For instance, all arithmetic instructions can have 8-bit opcodes, as the stack machine does, using $1/256$ of the opcode space each; then the three-address register machine will use 20 bits to encode each complete arithmetic instruction. All $\\texttt{MOV}$s, $\\texttt{XCHG}$s, $\\texttt{PUSH}$es, and $\\texttt{POP}$s on register machines can be assumed to have 4-bit opcodes, because this is what we do for the most common stack manipulation primitives on a stack machine. The results of these changes are shown in [Table 4](#table-4).\n\nWe can see that the performance of the various machines is much more balanced, with the stack machine still the winner in terms of the code density, but with the three-address machine enjoying the second place it really merits. If we were to consider the decoding speed and the possibility of parallel execution of instructions, we would have to choose the three-address machine, because it uses only 12 instructions instead of 21.\n\n<a id=\"table-4\"></a>\n\n| Machine | $\\mathit{r}$ | Operations |  |  | Code bytes |  |  | Opcode space |  |  |\n|---------|--------------|------------|-------|-------|------------|-------|-------|--------------|-------|-------|\n|         |              | data | arith | total | data | arith | **total** | data | **arith** | total |\n| 3-addr. | *0* | 0 | 11 | 12 | 0 | 27.5 | **28.5** | 64/256 | **4/256** | 69/256 |\n| 2-addr. | *0* | 4 | 11 | 16 | 6 | 22 | **29** | 64/256 | **4/256** | 69/256 |\n| 1-addr. | *1* | 13 | 11 | 25 | 16 | 16.5 | **32.5** | 64/256 | **4/256** | 69/256 |\n| stack (basic) | *0* | 16 | 11 | 28 | 16 | 11 | **28** | 64/256 | **4/256** | 69/256 |\n| stack (comp.) | *0* | 9 | 11 | 21 | 15 | 11 | **27** | 84/256 | **4/256** | 89/256 |\n\n**Table 4.** A summary of machine code properties for hypothetical 3-address, 2-address, 1-address and stack machines, generated for a [sample leaf function](#c-1-1-sample-source-file-for-a-leaf-function), assuming that only 8 of the 16 registers must be preserved by functions ($m=8$, $n=16$). This time we can use fractions of bytes to encode instructions, so as to match opcode space used by different machines. All arithmetic instructions have 8-bit opcodes, all data/stack manipulation instructions have 4-bit opcodes. In other respects this table is similar to [Table 3](#table-3).\n\n---\n\n## C.3   Sample non-leaf function\n\nThis section compares the machine code for different register machines for a sample non-leaf function. Again, we assume that either $m=0$, $m=8$, or $m=16$ registers are preserved by called functions, with $m=8$ representing the compromise made by most modern compilers and operating systems.\n\n### C.3.1. Sample source code for a non-leaf function\n\nA sample source file may be obtained by replacing the built-in integer type with a custom *Rational* type, represented by a pointer to an object in memory, in our function for solving systems of [two linear equations](#c-1-1-sample-source-file-for-a-leaf-function):\n\n```\nstruct Rational;\ntypedef struct Rational *num;\nextern num r_add(num, num);\nextern num r_sub(num, num);\nextern num r_mul(num, num);\nextern num r_div(num, num);\n\n(num, num) r_f(num a, num b, num c, num d, num e, num f) {\n  num D = r_sub(r_mul(a, d), r_mul(b, c));   // a*d-b*c\n  num Dx = r_sub(r_mul(e, d), r_mul(b, f));  // e*d-b*f\n  num Dy = r_sub(r_mul(a, f), r_mul(e, c));  // a*f-e*c\n  return (r_div(Dx, D), r_div(Dy, D));      // Dx/D, Dy/D\n}\n```\n\nWe will ignore all questions related to allocating new objects of type *Rational* in memory (e.g., in heap), and to preventing memory leaks. We may assume that the called subroutines $\\texttt{r\\_sub}$, $\\texttt{r\\_mul}$, and so on allocate new objects simply by advancing some pointer in a pre-allocated buffer, and that unused objects are later freed by a garbage collector, external to the code being analysed.\n\nRational numbers will now be represented by pointers, addresses, or references, which will fit into registers of our hypothetical register machines or into the stack of our stack machines. If we want to use TVM as an instance of these stack machines, we should use values of type *Cell* to represent such references to objects of type *Rational* in memory.\n\nWe assume that subroutines (or functions) are called by a special $\\texttt{CALL}$ instruction, which is encoded by three bytes, including the specification of the function to be called (e.g., the index in a \"global function table\").\n\n### C.3.2. Three-address and two-address register machines, $m=0$ preserved registers\n\nBecause our sample function does not use built-in arithmetic instructions at all, compilers for our hypothetical three-address and two-address register machines will produce the same machine code. Apart from the previously introduced $\\texttt{PUSH r}(i)$ and $\\texttt{POP r}(i)$ one-byte instructions, we assume that our two- and three-address machines support the following two-byte instructions: $\\texttt{MOV r}(i)\\texttt{,s}(j)$, $\\texttt{MOV s}(j)\\texttt{,r}(i)$, and $\\texttt{XCHG r}(i)\\texttt{,s}(j)$, for $0\\leq i,j\\leq 15$. Such instructions occupy only 3/256 of the opcode space, so their addition seems quite natural.\n\nWe first assume that $m=0$ (i.e., that all subroutines are free to destroy the values of all registers). In this case, our machine code for $\\texttt{r\\_f}$ does not have to preserve any registers, but has to save all registers containing useful values into the stack before calling any subroutines. A size-optimizing compiler might produce the following code:\n\n```\nPUSH r4     // STACK: e\nPUSH r1     // STACK: e b\nPUSH r0     //     .. e b a\nPUSH r6     //     .. e b a f\nPUSH r2     //     .. e b a f c\nPUSH r3     //     .. e b a f c d\nMOV r0,r1   // b\nMOV r1,r2   // c\nCALL r_mul  // bc\nPUSH r0     //     .. e b a f c d bc\nMOV r0,s4   // a\nMOV r1,s1   // d\nCALL r_mul  // ad\nPOP r1      // bc; .. e b a f c d\nCALL r_sub  // D:=ad-bc\nXCHG r0,s4  // b ; .. e D a f c d\nMOV r1,s2   // f\nCALL r_mul  // bf\nPOP r1      // d ; .. e D a f c\nPUSH r0     //     .. e D a f c bf\nMOV r0,s5   // e\nCALL r_mul  // ed\nPOP r1      // bf; .. e D a f c\nCALL r_sub  // Dx:=ed-bf\nXCHG r0,s4  // e ; .. Dx D a f c\nPOP r1      // c ; .. Dx D a f\nCALL r_mul  // ec\nXCHG r0,s1  // a ; .. Dx D ec f\nPOP r1      // f ; .. Dx D ec\nCALL r_mul  // af\nPOP r1      // ec; .. Dx D\nCALL r_sub  // Dy:=af-ec\nXCHG r0,s1  // Dx; .. Dy D\nMOV r1,s0   // D\nCALL r_div  // x:=Dx/D\nXCHG r0,s1  // Dy; .. x D\nPOP r1      // D ; .. x\nCALL r_div  // y:=Dy/D\nMOV r1,r0   // y\nPOP r0      // x ; ..\nRET\n```\n\nWe have used 41 instructions: 17 one-byte (eight $\\texttt{PUSH}$/$\\texttt{POP}$ pairs and one $\\texttt{RET}$), 13 two-byte ($\\texttt{MOV}$ and $\\texttt{XCHG}$; out of them 11 \"new\" ones, involving the stack), and 11 three-byte ($\\texttt{CALL}$), for a total of $17\\cdot1+13\\cdot2+11\\cdot3=76$ bytes.<a id=\"ref-fn32\"></a><sup>[32](#fn32)</sup>\n\n### C.3.3. Three-address and two-address register machines, $m=8$ preserved registers\n\nNow we have eight registers, $\\texttt{r8}$ to $\\texttt{r15}$, that are preserved by subroutine calls. We might keep some intermediate values there instead of pushing them into the stack. However, the penalty for doing so consists in a $\\texttt{PUSH}$/$\\texttt{POP}$ pair for every such register that we choose to use, because our function is also required to preserve its original value. It seems that using these registers under such a penalty does not improve the density of the code, so the optimal code for three- and two-address machines for $m=8$ [preserved registers](#c-3-2-three-address-and-two-address-register-machines,-preserved-registers) is the same, with a total of 42 instructions and 74 code bytes.\n\n### C.3.4. Three-address and two-address register machines, $m=16$ preserved registers\n\nThis time *all* registers must be preserved by the subroutines, excluding those used for returning the results. This means that our code must preserve the original values of $\\texttt{r2}$ to $\\texttt{r5}$, as well as any other registers it uses for temporary values. A straightforward way of writing the code of our subroutine would be to push registers $\\texttt{r2}$ up to, say, $\\texttt{r8}$ into the stack, then perform all the operations required, using $\\texttt{r6}$—$\\texttt{r8}$ for intermediate values, and finally restore registers from the stack. However, this would not optimize code size. We choose another approach:\n\n```\nPUSH r0     // STACK: a\nPUSH r1     // STACK: a b\nMOV r0,r1   // b\nMOV r1,r2   // c\nCALL r_mul  // bc\nPUSH r0     //     .. a b bc\nMOV r0,s2   // a\nMOV r1,r3   // d\nCALL r_mul  // ad\nPOP r1      // bc; .. a b\nCALL r_sub  // D:=ad-bc\nXCHG r0,s0  // b;  .. a D\nMOV r1,r5   // f\nCALL r_mul  // bf\nPUSH r0     //     .. a D bf\nMOV r0,r4   // e\nMOV r1,r3   // d\nCALL r_mul  // ed\nPOP r1      // bf; .. a D\nCALL r_sub  // Dx:=ed-bf\nXCHG r0,s1  // a ; .. Dx D\nMOV r1,r5   // f\nCALL r_mul  // af\nPUSH r0     //     .. Dx D af\nMOV r0,r4   // e\nMOV r1,r2   // c\nCALL r_mul  // ec\nMOV r1,r0   // ec\nPOP r0      // af; .. Dx D\nCALL r_sub  // Dy:=af-ec\nXCHG r0,s1  // Dx; .. Dy D\nMOV r1,s0   // D\nCALL r_div  // x:=Dx/D\nXCHG r0,s1  // Dy; .. x D\nPOP r1      // D ; .. x\nCALL r_div  // y:=Dy/D\nMOV r1,r0   // y\nPOP r0      // x\nRET\n```\n\nWe have used 39 instructions: 11 one-byte, 17 two-byte (among them 5 \"new\" instructions), and 11 three-byte, for a total of $11\\cdot1+17\\cdot2+11\\cdot3=78$ bytes. Somewhat paradoxically, the code size in bytes is slightly longer than in the [previous case](#c-3-2-three-address-and-two-address-register-machines,-preserved-registers), contrary to what one might have expected. This is partially due to the fact that we have assumed two-byte encodings for \"new\" $\\texttt{MOV}$ and $\\texttt{XCHG}$ instructions involving the stack, similarly to the \"old\" instructions. Most existing architectures (such as x86-64) use longer encodings (maybe even twice as long) for their counterparts of our \"new\" move and exchange instructions compared to the \"usual\" register-register ones. Taking this into account, we see that we would have obtained here 83 bytes (versus 87 for the [code](#c-3-2-three-address-and-two-address-register-machines,-preserved-registers)) assuming three-byte encodings of new operations, and 88 bytes (versus 98) assuming four-byte encodings. This shows that, for two-address architectures without optimized encodings for register-stack move and exchange operations, $m=16$ preserved registers might result in slightly shorter code for some non-leaf functions, at the expense of leaf functions [C.2.3](#c-2-3-case-%3A-all-registers-must-be-preserved) and [C.2.4](#c-2-4-case-%2C-%3A-registers-must-be-preserved), which would become considerably longer.\n\n### C.3.5. One-address register machine, $m=0$ preserved registers\n\nFor our one-address register machine, we assume that new register-stack instructions work through the accumulator only. Therefore, we have three new instructions, $\\texttt{LD s}(j)$ (equivalent to $\\texttt{MOV r0,s}(j)$ of two-address machines), $\\texttt{ST s}(j)$ (equivalent to $\\texttt{MOV s}(j)\\texttt{,r0}$), and $\\texttt{XCHG s}(j)$ (equivalent to $\\texttt{XCHG r0,s}(j)$). To make the comparison with two-address machines more interesting, we assume one-byte encodings for these new instructions, even though this would consume $48/256=3/16$ of the opcode space.\n\nBy adapting the [code](#c-3-2-three-address-and-two-address-register-machines%2C-preserved-registers) to the one-address machine, we obtain the following:\n\n```\nPUSH r4     // STACK: e\nPUSH r1     // STACK: e b\nPUSH r0     //     .. e b a\nPUSH r6     //     .. e b a f\nPUSH r2     //     .. e b a f c\nPUSH r3     //     .. e b a f c d\nLD s1       // r0:=c\nXCHG r1     // r0:=b, r1:=c\nCALL r_mul  // bc\nPUSH r0     //     .. e b a f c d bc\nLD s1       // d\nXCHG r1     // r1:=d\nLD s4       // a\nCALL r_mul  // ad\nPOP r1      // bc; .. e b a f c d\nCALL r_sub  // D:=ad-bc\nXCHG s4     // b ; .. e D a f c d\nXCHG r1\nLD s2       // f\nXCHG r1     // r0:=b, r1:=f\nCALL r_mul  // bf\nPOP r1      // d ; .. e D a f c\nPUSH r0     //     .. e D a f c bf\nLD s5       // e\nCALL r_mul  // ed\nPOP r1      // bf; .. e D a f c\nCALL r_sub  // Dx:=ed-bf\nXCHG s4     // e ; .. Dx D a f c\nPOP r1      // c ; .. Dx D a f\nCALL r_mul  // ec\nXCHG s1     // a ; .. Dx D ec f\nPOP r1      // f ; .. Dx D ec\nCALL r_mul  // af\nPOP r1      // ec; .. Dx D\nCALL r_sub  // Dy:=af-ec\nXCHG s1     // Dx; .. Dy D\nPOP r1      // D ; .. Dy\nPUSH r1     //     .. Dy D\nCALL r_div  // x:=Dx/D\nXCHG s1     // Dy; .. x D\nPOP r1      // D ; .. x\nCALL r_div  // y:=Dy/D\nXCHG r1     // r1:=y\nPOP r0      // r0:=x ; ..\nRET\n```\n\nWe have used 45 instructions: 34 one-byte and 11 three-byte, for a total of 67 bytes. Compared to the 76 bytes used by [two- and three-address machines](#c-3-2-three-address-and-two-address-register-machines%2C-preserved-registers), we see that, again, the one-address register machine code may be denser than that of two-register machines, at the expense of utilizing more [opcode space](#c-2-comparison-of-machine-code-for-sample-leaf-function). However, this time the extra 3/16 of the opcode space was used for data manipulation instructions, which do not depend on specific arithmetic operations or user functions invoked.\n\n\n### C.3.6. One-address register machine, $m=8$ preserved registers\n\nAs explained [above](#c-3-3-three-address-and-two-address-register-machines%2C-preserved-registers), the preservation of $\\texttt{r8}$—$\\texttt{r15}$ between subroutine calls does not improve the size of our previously written code, so the one-address machine will use for $m=8$ the same [code](#c-3-5-one-address-register-machine%2C-preserved-registers).\n\n### C.3.7. One-address register machine, $m=16$ preserved registers\n\nWe simply adapt the [code](#c-3-4-three-address-and-two-address-register-machines%2C-preserved-registers) to the one-address register machine:\n\n```\nPUSH r0     // STACK: a\nPUSH r1     // STACK: a b\nMOV r0,r1   // b\nMOV r1,r2   // c\nCALL r_mul  // bc\nPUSH r0     //     .. a b bc\nLD s2       // a\nMOV r1,r3   // d\nCALL r_mul  // ad\nPOP r1      // bc; .. a b\nCALL r_sub  // D:=ad-bc\nXCHG s0     // b;  .. a D\nMOV r1,r5   // f\nCALL r_mul  // bf\nPUSH r0     //     .. a D bf\nMOV r0,r4   // e\nMOV r1,r3   // d\nCALL r_mul  // ed\nPOP r1      // bf; .. a D\nCALL r_sub  // Dx:=ed-bf\nXCHG s1     // a ; .. Dx D\nMOV r1,r5   // f\nCALL r_mul  // af\nPUSH r0     //     .. Dx D af\nMOV r0,r4   // e\nMOV r1,r2   // c\nCALL r_mul  // ec\nMOV r1,r0   // ec\nPOP r0      // af; .. Dx D\nCALL r_sub  // Dy:=af-ec\nXCHG s1     // Dx; .. Dy D\nPOP r1      // D ; .. Dy\nPUSH r1     //     .. Dy D\nCALL r_div  // x:=Dx/D\nXCHG s1     // Dy; .. x D\nPOP r1      // D ; .. x\nCALL r_div  // y:=Dy/D\nMOV r1,r0   // y\nPOP r0      // x\nRET\n```\n\nWe have used 40 instructions: 18 one-byte, 11 two-byte, and 11 three-byte, for a total of $18\\cdot1+11\\cdot2+11\\cdot3=73$ bytes.\n\n### C.3.8. Stack machine with basic stack primitives\n\nWe reuse the [code](#c-1-5-stack-machine-with-basic-stack-primitives), simply replacing arithmetic primitives (VM instructions) with subroutine calls. The only substantive modification is the insertion of the previously optional $\\texttt{XCHG s1}$ before the third multiplication, because even an optimizing compiler cannot now know whether $\\texttt{CALL r\\_mul}$ is a commutative operation. We have also used the \"tail recursion optimization\" by replacing the final $\\texttt{CALL r\\_div}$ followed by $\\texttt{RET}$ with $\\texttt{JMP r\\_div}$.\n\n```\nPUSH s5     // a b c d e f a\nPUSH s3     // a b c d e f a d\nCALL r_mul  // a b c d e f ad\nPUSH s5     // a b c d e f ad b\nPUSH s5     // a b c d e f ad b c\nCALL r_mul  // a b c d e f ad bc\nCALL r_sub  // a b c d e f ad-bc\nXCHG s3     // a b c ad-bc e f d\nPUSH s2     // a b c ad-bc e f d e\nXCHG s1     // a b c ad-bc e f e d\nCALL r_mul  // a b c ad-bc e f ed\nXCHG s5     // a ed c ad-bc e f b\nPUSH s1     // a ed c ad-bc e f b f\nCALL r_mul  // a ed c ad-bc e f bf\nXCHG s1,s5  // a f c ad-bc e ed bf\nCALL r_sub  // a f c ad-bc e ed-bf\nXCHG s3     // a f ed-bf ad-bc e c\nCALL r_mul  // a f ed-bf ad-bc ec\nXCHG s3     // a ec ed-bf ad-bc f\nXCHG s1,s4  // ad-bc ec ed-bf a f\nCALL r_mul  // D ec Dx af\nXCHG s1     // D ec af Dx\nXCHG s2     // D Dx af ec\nCALL r_sub  // D Dx Dy\nXCHG s1     // D Dy Dx\nPUSH s2     // D Dy Dx D\nCALL r_div  // D Dy x\nXCHG s2     // x Dy D\nJMP r_div   // x y\n```\n\nWe have used 29 instructions; assuming one-byte encodings for all stack operations, and three-byte encodings for $\\texttt{CALL}$ and $\\texttt{JMP}$ instructions, we end up with 51 bytes.\n\n### C.3.9. Stack machine with compound stack primitives\n\nWe again reuse the [code](#c-1-7-stack-machine-with-compound-stack-primitives-and-manually-optimized-code), replacing arithmetic primitives with subroutine calls and making the tail recursion optimization:\n\n\n```\nPUSH2 s5,s2    // a b c d e f a d\nCALL r_mul     // a b c d e f ad\nPUSH2 s5,s4    // a b c d e f ad b c\nCALL r_mul     // a b c d e f ad bc\nCALL r_sub     // a b c d e f ad-bc\nPUXC s2,s3     // a b c ad-bc e f e d\nCALL r_mul     // a b c D e f ed\nXCHG3 s6,s0,s5 //  (same as XCHG s2,s6; XCHG s1,s0; XCHG s0,s5)\n               // e f c D a ed b\nPUSH s5        // e f c D a ed b f\nCALL r_mul     // e f c D a ed bf\nCALL r_sub     // e f c D a ed-bf\nXCHG s4        // e Dx c D a f\nCALL r_mul     // e Dx c D af\nXCHG2 s4,s2    // D Dx af e c\nCALL r_mul     // D Dx af ec\nCALL r_sub     // D Dx Dy\nXCPU s1,s2     // D Dy Dx D\nCALL r_div     // D Dy x\nXCHG s2        // x Dy D\nJMP r_div      // x y\n```\n\nThis code uses only 20 instructions, 9 stack-related and 11 control flow-related ($\\texttt{CALL}$ and $\\texttt{JMP}$), for a total of 48 bytes.\n\n\n## C.4   Comparison of machine code for sample non-leaf function\n\n[Table 5](#table-5) summarizes the properties of machine code corresponding to the [same source file](#c-3-1-sample-source-code-for-a-non-leaf-function). We consider only the \"realistically\" encoded three-address machines. Three-address and two-address machines have the same code density properties, but differ in the utilization of opcode space. The one-address machine, somewhat surprisingly, managed to produced shorter code than the two-address and three-address machines, at the expense of using up more than half of all opcode space. The stack machine is the obvious winner in this code density contest, without compromizing its excellent extendability (measured in opcode space used for arithmetic and other data transformation instructions).\n\n<a id=\"table-5\"></a>\n\n| Machine          | $m$   | **Operations** |     |     | **Code bytes** |     |     | **Opcode space** |     |     |\n|------------------|--------|---------------|-----|-----|----------------|-----|-----|------------------|-----|-----|\n|                  |        | data | cont. | total | data | cont. | **total** | data | **arith** | total |\n| 3-addr.          | *0,8*  | 29 | 12 | 41 | 42 | 34 | **76** | 35/256 | **34/256** | 72/256 |\n|                  | *16*   | 27 | 12 | 39 | 44 | 34 | **78** |          |        |          |\n| 2-addr.          | *0,8*  | 29 | 12 | 41 | 42 | 34 | **76** | 37/256 | **4/256** | 44/256 |\n|                  | *16*   | 27 | 12 | 39 | 44 | 34 | **78** |          |        |          |\n| 1-addr.          | *0,8*  | 33 | 12 | 45 | 33 | 34 | **67** | 97/256 | **64/256** | 164/256 |\n|                  | *16*   | 28 | 12 | 40 | 39 | 34 | **73** |          |        |          |\n| stack (basic)    | $-$    | 18 | 11 | 29 | 18 | 33 | **51** | 64/256 | **4/256** | 71/256 |\n| stack (comp.)    | $-$    | 9 | 11 | 20 | 15 | 33 | **48** | 84/256 | **4/256** | 91/256 |\n\n**Table 5**: A summary of machine code properties for hypothetical 3-address, 2-address, 1-address, and stack machines, generated for a [sample non-leaf function](#c-3-1-sample-source-code-for-a-non-leaf-function), assuming $m$ of the 16 registers must be preserved by called subroutines.\n\n### C.4.1. Combining with results for leaf functions\n\nIt is instructive to compare this table with the results in [C.2](#c-2-comparison-of-machine-code-for-sample-leaf-function) for a sample leaf function, summarized in [Table 1](#table-1) (for $m=0$ preserved registers) and the very similar [Table 3](#table-3) (for $m=8$ preserved registers), and, if one is still interested in case $m=16$ (which turned out to be worse than $m=8$ in almost all situations), also to [Table 2](#table-2).\n\nWe see that the stack machine beats all register machines on non-leaf functions. As for the leaf functions, only the three-address machine with the \"optimistic\" encoding of arithmetic instructions was able to beat the stack machine, winning by 15%, by compromising its extendability. However, the same three-address machine produces 25% longer code for non-leaf functions. If a typical program consists of a mixture of leaf and non-leaf functions in approximately equal proportion, then the stack machine will still win.\n\n### C.4.2. A fairer comparison using a binary code instead of a byte code\n\nSimilarly to [C.2.5](#c-2-5-a-fairer-comparison-using-a-binary-code-instead-of-a-byte-code), we may offer a fairer comparison of different register machines and the stack machine by using arbitrary binary codes instead of byte codes to encode instructions, and matching the opcode space used for data manipulation and arithmetic instructions by different machines. The results of this modified comparison are summarized in [Table 6](#table-6). We see that the stack machines still win by a large margin, while using less opcode space for stack/data manipulation.\n\n<a id=\"table-6\"></a>\n\n| Machine          | $m$   | **Operations** |     |     | **Code bytes** |     |     | **Opcode space** |     |     |\n|------------------|--------|---------------|-----|-----|----------------|-----|-----|------------------|-----|-----|\n|                  |        | data | cont. | total | data | cont. | **total** | data | **arith** | total |\n| 3-addr.          | *0,8*  | 29 | 12 | 41 | 35.5 | 34 | **69.5** | 110/256 | **4/256** | 117/256 |\n|                  | *16*   | 27 | 12 | 39 | 35.5 | 34 | **69.5** |          |        |          |\n| 2-addr.          | *0,8*  | 29 | 12 | 41 | 35.5 | 34 | **69.5** | 110/256 | **4/256** | 117/256 |\n|                  | *16*   | 27 | 12 | 39 | 35.5 | 34 | **69.5** |          |        |          |\n| 1-addr.          | *0,8*  | 33 | 12 | 45 | 33 | 34 | **67** | 112/256 | **4/256** | 119/256 |\n|                  | *16*   | 28 | 12 | 40 | 33.5 | 34 | **67.5** |          |        |          |\n| stack (basic)    | $-$    | 18 | 11 | 29 | 18 | 33 | **51** | 64/256 | **4/256** | 71/256 |\n| stack (comp.)    | $-$    | 9 | 11 | 20 | 15 | 33 | **48** | 84/256 | **4/256** | 91/256 |\n\n\n**Table 6**: A summary of machine code properties for hypothetical 3-address, 2-address, 1-address, and stack machines, generated for a [sample non-leaf function](#c-3-1-sample-source-code-for-a-non-leaf-function), assuming $m$ of the 16 registers must be preserved by called subroutines. This time we use fractions of bytes to encode instructions, enabling a fairer comparison. Otherwise, this table is similar to [Table 5](#table-5).\n\n\n### C.4.3. Comparison with real machines\n\nNote that our hypothetical register machines have been considerably optimized to produce shorter code than actually existing register machines; the latter are subject to other design considerations apart from code density and extendability, such as backward compatibility, faster instruction decoding, parallel execution of neighboring instructions, ease of automatically producing optimized code by compilers, and so on.\n\nFor example, the very popular two-address register architecture x86-64 produces code that is approximately twice as long as our \"ideal\" results for the two-address machines. On the other hand, our results for the stack machines are directly applicable to TVM, which has been explicitly designed with the considerations presented in this appendix in mind. Furthermore, the actual TVM code is even *shorter* (in bytes) than shown in [Table 5](#table-5) because of the presence of the two-byte $\\texttt{CALL}$ instruction, allowing TVM to call up to 256 user-defined functions from the dictionary at $\\texttt{c3}$. This means that one should subtract 10 bytes from the results for stack machines in [Table 5](#table-5) if one wants to specifically consider TVM, rather than an abstract stack machine; this produces a code size of approximately 40 bytes (or shorter), almost half that of an abstract two-address or three-address machine.\n\n### C.4.4. Automatic generation of optimized code\n\nAn interesting point is that the stack machine code in our samples might have been generated automatically by a very simple optimizing compiler, which rearranges values near the top of the stack appropriately before invoking each primitive or calling a function as explained in [2.2.2](#2-2-2-basic-stack-manipulation-primitives-suffice) and [2.2.5](#2-2-5-semantics-of-compound-stack-operations). The only exception is the unimportant [manual](#c-1-7-stack-machine-with-compound-stack-primitives-and-manually-optimized-code) $\\texttt{XCHG3}$ optimization, which enabled us to shorten the code by one more byte.\n\nBy contrast, the heavily optimized (with respect to size) code for register machines shown in [C.3.2](#c-3-2-three-address-and-two-address-register-machines%2C-preserved-registers) and [C.3.3](#c-3-3-three-address-and-two-address-register-machines%2C-preserved-registers) is unlikely to be produced automatically by an optimizing compiler. Therefore, if we had compared compiler-generated code instead of manually-generated code, the advantages of stack machines with respect to code density would have been even more striking.\n\n## References\n\n[1] N. Durov, *Telegram Open Network*, 2017.\n\n\n## Footnotes\n\n<span id=\"fn1\">**1**</span> For example, there are no floating-point arithmetic operations (which could be efficiently implemented using hardware-supported *double* type on most modern CPUs) present in TVM, because the result of performing such operations is dependent on the specific underlying hardware implementation and rounding mode settings. Instead, TVM supports special integer arithmetic operations, which can be used to simulate fixed-point arithmetic if needed. [Back ↑](#ref-fn1)\n\n<span id=\"fn2\">**2**</span> The production version will likely require some tweaks and modifications prior to launch, which will become apparent only after using the experimental version in the test environment for some time. [Back ↑](#ref-fn2)\n\n<span id=\"fn3\">**3**</span> A high-level smart-contract language might create a visibility of variables for the ease of programming; however, the high-level source code working with variables will be translated into TVM machine code keeping all the values of these variables in the TVM stack. [Back ↑](#ref-fn3)\n\n<span id=\"fn4\">**4**</span> In the TON Blockchain context, `c7` is initialized with a singleton *Tuple*, the only component of which is a *Tuple* containing blockchain-specific data. The smart contract is free to modify `c7` to store its temporary data provided the first component of this *Tuple* remains intact. [Back ↑](#ref-fn4)\n\n<span id=\"fn5\">**5**</span> Strictly speaking, there is also the current *library context*, which consists of a dictionary with 256-bit keys and cell values, used to load library reference cells of [Types of exotic cells](#3-1-7-types-of-exotic-cells). [Back ↑](#ref-fn5)\n\n<span id=\"fn6\">**6**</span> Our inclusion of `r0` here creates a minor conflict with our assumption that the accumulator register, if present, is also `r0`; for simplicity, we will resolve this problem by assuming that the first argument to a function is passed in the accumulator. [Back ↑](#ref-fn6)\n\n<span id=\"fn7\">**7**</span> For instance, if one writes a function for extracting square roots, this function will always accept its argument and return its result in the same registers, in contrast with a hypothetical built-in square root instruction, which could allow the programmer to arbitrarily choose the source and destination registers. Therefore, a user-defined function is tremendously less flexible than a built-in instruction on a register machine. [Back ↑](#ref-fn7)\n\n<span id=\"fn8\">**8**</span> Of course, if the second option is used, this will destroy the original arrangement of $x$ in the top of the stack. In this case, one should either issue a `SWAP` before `XCHG s(j')`, or replace the previous operation `XCHG s(i)` with `XCHG s1, s(i)`, so that $x$ is exchanged with `s1` from the beginning. [Back ↑](#ref-fn8)\n\n<span id=\"fn9\">**9**</span> Notice that the most common `XCHG s(i)` operation is not really required here if we do not insist on keeping the same temporary value or variable always in the same stack location, but rather keep track of its subsequent locations. We will move it to some other location while preparing the arguments to the next primitive or function call. [Back ↑](#ref-fn9)\n\n<span id=\"fn10\">**10**</span> An alternative, arguably better, translation of `PU`$O'$ `s(i_1)`,...,`s(i_γ)` consists of the translation of $O'$ `s(i_2)`,...,`s(i_γ)`, followed by `PUSH s(i_1+α-1)`; `XCHG s(γ-1)`. [Back ↑](#ref-fn10)\n\n<span id=\"fn11\">**11**</span> From the perspective of low-level cell operations, these data bits and cell references are not intermixed. In other words, an (ordinary) cell essentially is a couple consisting of a list of up to 1023 bits and of a list of up to four cell references, without prescribing an order in which the references and the data bits should be deserialized, even though TL-B schemes appear to suggest such an order. [Back ↑](#ref-fn11)\n\n<span id=\"fn12\">**12**</span> From a theoretical perspective, we might say that a cell $c$ has an infinite sequence of hashes $(\\text{Hash}_i(c))_{i\\geq1}$, which eventually stabilizes: $\\text{Hash}_i(c)\\to\\text{Hash}_\\infty(c)$. Then the level $l$ is simply the largest index $i$, such that $\\text{Hash}_i(c)\\neq\\text{Hash}_\\infty(c)$. [Back ↑](#ref-fn12)\n\n<span id=\"fn13\">**13**</span> A pruned branch cell $c'$ of level $l$ is *bound* by a Merkle (proof or update) cell $c$ if there are exactly $l$ Merkle cells on the path from $c$ to its descendant $c'$, including $c$. [Back ↑](#ref-fn13)\n\n<span id=\"fn14\">**14**</span> Negative numbers are represented using two's complement. For instance, integer $-17$ is serialized by instruction `STI 8` into bitstring `xEF`. [Back ↑](#ref-fn14)\n\n<span id=\"fn15\">**15**</span> A description of an older version of TL may be found at https://core.telegram.org/mtproto/TL. [Back ↑](#ref-fn15)\n\n<span id=\"fn16\">**16**</span> The field's name is useful for representing values of the type being defined in human-readable form, but it does not affect the binary serialization. [Back ↑](#ref-fn16)\n\n<span id=\"fn17\">**17**</span> This is the \"linear negation\" operation $(-)^\\perp$ of linear logic, hence our notation `~`. [Back ↑](#ref-fn17)\n\n<span id=\"fn18\">**18**</span> In fact, $f$ may receive $m$ extra arguments and return $m$ modified values, which are passed to the next invocation of $f$. This may be used to implement \"map\" and \"reduce\" operations with dictionaries. [Back ↑](#ref-fn18)\n\n<span id=\"fn19\">**19**</span> Versions of this operation may be introduced where $f$ and $g$ receive an additional bitstring argument, equal to the key (for leaves) or to the common prefix of all keys (for forks) in the corresponding subtree. [Back ↑](#ref-fn19)\n\n<span id=\"fn20\">**20**</span> If there are no bits of data left in `code`, but there is still exactly one reference, an implicit `JMP` to the cell at that reference is performed instead of an implicit `RET`. [Back ↑](#ref-fn20)\n\n<span id=\"fn21\">**21**</span> Technically, TVM may simply invoke a virtual method `run()` of the continuation currently in `cc`. [Back ↑](#ref-fn21)\n\n<span id=\"fn22\">**22**</span> The already used savelist `cc.save` of the new `cc` is emptied before the execution starts. [Back ↑](#ref-fn22)\n\n<span id=\"fn23\">**23**</span> The implementation of `REPEAT` involves an extraordinary continuation that remembers the remaining number of iterations, the body of the loop $c$, and the return continuation $c'$. (The latter term represents the remainder of the body of the function that invoked `REPEAT`, which would be normally stored in `c0` of the new `cc`.) [Back ↑](#ref-fn23)\n\n<span id=\"fn24\">**24**</span> An important point here is that the tree of cells representing a TVM program cannot have cyclic references, so using `CALLREF` along with a reference to a cell higher up the tree would not work. [Back ↑](#ref-fn24)\n\n<span id=\"fn25\">**25**</span> This is not exactly true. A more precise statement is that usually the codepage of the newly-created continuation is a known function of the current codepage. [Back ↑](#ref-fn25)\n\n<span id=\"fn26\">**26**</span> This is another important mechanism of backward compatibility. All values of newly-added types, as well as values belonging to extended original types that do not belong to the original types (e.g., 513-bit integers that do not fit into 257 bits in the example above), are treated by all instructions (except stack manipulation instructions, which are naturally polymorphic, [Polymorphism of stack manipulation primitives](#2-3-3-polymorphism-of-stack-manipulation-primitives)) in the old codepages as \"values of incorrect type\", and generate type-checking exceptions accordingly. [Back ↑](#ref-fn26)\n\n<span id=\"fn27\">**27**</span> If the cell dumps are hexadecimal, encodings consisting of an integral number of hexadecimal digits (i.e., having length divisible by four bits) might be equally convenient. [Back ↑](#ref-fn27)\n\n<span id=\"fn28\">**28**</span> Notice that it is the probability of occurrence in the code that counts, not the probability of being executed. An instruction occurring in the body of a loop executed a million times is still counted only once. [Back ↑](#ref-fn28)\n\n<span id=\"fn29\">**29**</span> Notice that any modifications after launch cannot be done unilaterally; rather they would require the support of at least two-thirds of validators. [Back ↑](#ref-fn29)\n\n<span id=\"fn30\">**30**</span> The preliminary version of TVM does not use codepage -2 for this purpose. This may change in the future. [Back ↑](#ref-fn30)\n\n<span id=\"fn31\">**31**</span> It is interesting to compare this code with that generated by optimizing C compilers for the x86-64 architecture. First of all, the integer division operation for x86-64 uses the one-address form, with the (double-length) dividend to be supplied in accumulator pair `r2:r0`. The quotient is also returned in `r0`. As a consequence, two single-to-double extension operations (`CDQ` or `CQO`) and at least one move operation need to be added. Secondly, the encoding used for arithmetic and move operations is less optimistic than in our example above, requiring about three bytes per operation on average. As a result, we obtain a total of 43 bytes for 32-bit integers, and 68 bytes for 64-bit integers. [Back ↑](#ref-fn31)\n\n<span id=\"fn32\">**32**</span> Code produced for this function by an optimizing compiler for x86-64 architecture with size-optimization enabled actually occupied 150 bytes, due mostly to the fact that actual instruction encodings are about twice as long as we had optimistically assumed. [Back ↑](#ref-fn32)"
  },
  {
    "path": "from-ethereum.mdx",
    "content": "---\ntitle: \"Coming from Ethereum\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\nimport { Image } from '/snippets/image.jsx';\n\nLearn how to develop and build on TON coming from the Ethereum (EVM) ecosystem.\n\n## Execution model\n\n### Asynchronous blockchain\n\nA fundamental aspect of TON development is the asynchronous execution model. Messages sent by one contract take time to arrive at another, so the resulting transactions for processing incoming messages occur after the current transaction terminates.\n\nCompared to Ethereum, where multiple messages and state changes on different contracts can be processed within the same atomic transaction, a TON transaction represents a state change only for one account and only for a processing of a single message. Even though in both blockchains a signed included-in-block unit is called a \"transaction\", one transaction on Ethereum usually corresponds to several transactions on TON, that are processed over a span of several blocks.\n\n| Action description                                                                             | Ethereum                               | TON                              |\n| :--------------------------------------------------------------------------------------------- | -------------------------------------- | -------------------------------- |\n| Single message processing with state change on one contract                                    | Message call or \"internal transaction\" | Transaction                      |\n| Number of state changes and messages on different accounts produced from initial contract call | Transaction                            | Chain of transactions or \"trace\" |\n\nConsider a practical example: liquidity withdrawal on a DEX.\n\n- On Ethereum, it appears as a single atomic transaction with multiple contract calls inside it. This transaction has a single hash and is included in one block.\n\n  <Image\n    src=\"/resources/images/from-ethereum/burn-tx-eth-light.png\"\n    darkSrc=\"/resources/images/from-ethereum/burn-tx-eth-dark.png\"\n    alt=\"ETH burn\"\n  />\n\n- The same operation on TON consists of a sequence of more than 10 transactions. Each arrow on this image represents a distinct finalized transaction, with its own hash, inclusion block, and all the other properties:\n\n  <Image\n    src=\"/resources/images/from-ethereum/burn-tx-ton-light.png\"\n    darkSrc=\"/resources/images/from-ethereum/burn-tx-ton-dark.png\"\n    alt=\"TON burn\"\n  />\n\nExecuting a large transaction on Ethereum or any other EVM-based blockchain comes with certain limitations: [call depth](https://ethereum.org/developers/docs/evm/#evm-instructions) of 1,024 nested calls and the [block gas limit](https://ethereum.org/developers/docs/blocks/#block-size). With TON's asynchronous execution model, a trace — a chain of transactions — can have any length, as long as there are enough fees to continue it. For example, the [trace](https://tonviewer.com/transaction/e887503f7dac857be80487e3ed0774db962379d1c153e6df7b9b5313c657ab94) resulting from this message consisted of more than 1.5 million transactions, lasting more than 4,000 blocks until completion.\n\n### On-chain get methods\n\nAnother difference is in the [get methods](/tvm/get-method). Both Ethereum and TON support them, allowing data to be retrieved from contracts without paying fees. However, in TON, get methods cannot be called on-chain: a contract cannot synchronously retrieve data from another contract during a transaction. This is a consequence of TON's asynchronous model: by the moment transaction that called a get method would start its execution, data might already change.\n\n### Account model\n\nIn Ethereum, there are two types of accounts: externally owned accounts (EOA), and contract accounts. EOAs are human-controlled entities, each represented by a private-public key pair. They sign transactions and each has its own balance; the community often refers to them as \"wallets\".\n\nIn TON, there is no such separation. Every valid address represents an on-chain [account](/foundations/addresses/overview), each with its own state and balance, that could be changed through transactions. This means that \"wallets\" in TON are smart contracts that operate under the same rules as any other contract on the blockchain.\n\nThe [TON wallet](/standard/wallets/comparison) smart contract works as a proxy: handles an external message, checks message is sent by the wallet's owner using regular [public-key cryptography](https://en.wikipedia.org/wiki/Public-key_cryptography), and sends an internal message somewhere further in the network.\n\n### Limited contract storage\n\nIn Ethereum, it's possible to store any amount of data in a single contract. Unbounded maps and arrays are considered standard practice. TON sets a limit to the amount of data a contract can store. This means that ERC-20-like fungible tokens cannot be implemented in the same way as in an EVM chain, using a single map within a single contract.\n\n[The limit](/foundations/config) for contract storage is 65,536 unique cells contract storage, where a cell [stores up to](/foundations/serialization/cells) 1,023 bits. Messages are constrained by two size limits: 8,192 cells or 2<sup>21</sup> bits among them, whichever is smaller.\n\n<Aside\n  type=\"danger\"\n>\n  Every map that is expected to grow beyond 1,000 values is dangerous. In the TVM map, key access is asymptotically logarithmic, meaning that gas consumption continuously increases to find keys as the map grows.\n</Aside>\n\nInstead, [sharding](/contract-dev/contract-sharding) should be used.\n\n## Ecosystem\n\n### Tooling\n\nThe recommended programming language for smart contract development in TON is [Tolk](/languages/tolk). Other established languages are also used in the ecosystem; more information about them is available [here](/languages/tact).\n\nFor off-chain software, Typescript is the most adopted language in TON. Most of the [tooling](/contract-dev/blueprint/overview), bindings and [SDKs](/ecosystem/sdks) are implemented in Typescript.\n\n| Use case                              | Ethereum tool         | TON counterpart                                                                                                |\n| :------------------------------------ | --------------------- | -------------------------------------------------------------------------------------------------------------- |\n| Blockchain interaction                | Ethers, Web3.js, Viem | [`@ton/ton`](https://www.npmjs.com/package/@ton/ton), [Asset-sdk](https://github.com/ton-community/assets-sdk) |\n| Wallet connection protocol            | Walletconnect, Wagmi  | [TonConnect](https://github.com/ton-connect)                                                                   |\n| Dev environment framework / scripting | Hardhat, Truffle      | [Blueprint](https://github.com/ton-org/blueprint)                                                              |\n| Simulation engine                     | Revm & Reth           | [Sandbox](https://github.com/ton-org/sandbox)                                                                  |\n\nFor low-level manipulation of TON-specific data structures, there is [`@ton/core`](https://www.npmjs.com/package/@ton/core). Another library with wrappers for most important contracts and HTTP APIs is [`@ton/ton`](https://www.npmjs.com/package/@ton/ton).\n\n### Services\n\nWeb3 developers often rely on specific products and services for on-chain development.\nThe following table showcases some use cases that existing TON services support.\n\n| Use case                                | Ethereum service | TON service                                                          |\n| --------------------------------------- | ---------------- | -------------------------------------------------------------------- |\n| User-friendly explorer                  | Etherscan        | [Tonviewer](https://tonviewer.com/), [Tonscan](https://tonscan.org/) |\n| Open-source dev explorer                | Blockscout       | [TON Explorer](https://explorer.toncoin.org/)                        |\n| Debugger                                | Remix Debugger   | [TxTracer](https://txtracer.ton.org/)                                |\n| IDE                                     | Remix IDE        | [Web IDE](https://ide.ton.org/)                                      |\n| Asm playground and compilation explorer | EVM.Codes        | [TxTracer](https://txtracer.ton.org/)                                |\n\n### Standards\n\nThe table maps Ethereum standards and proposals, including ERC and EIP, to their TON counterparts, referred to as TEP.\n\nDue to significant differences in execution models, most of the standards in TON differ significantly in semantics and general approach compared to their Ethereum analogs.\n\n| Description                             | Ethereum standard                       | TON Standard (TEP)                                                 |\n| --------------------------------------- | --------------------------------------- | ------------------------------------------------------------------ |\n| Fungible token standard                 | ERC-20                                  | [Jettons (TEP-0074)](/standard/tokens/jettons/overview)            |\n| Non-fungible token standard             | ERC-721                                 | [NFT standard (TEP-0062)](/standard/tokens/nft/overview)           |\n| Token metadata                          | ERC-4955 (Not exactly, but close match) | [Token Data Standard (TEP-0064)](/standard/tokens/metadata)        |\n| NFT royalty standard                    | EIP-2981                                | [NFT Royalty Standard (TEP-0066)](/standard/tokens/nft/comparison) |\n| DNS-like registry                       | ENS (EIP-137)                           | [DNS Standard (TEP-0081)](/foundations/services)                   |\n| Soulbound / account-bound token concept | EIP-4973                                | [SBT Standard (TEP-0085)](/standard/tokens/nft/comparison#sbt)     |\n| Wallet connection protocol              | WalletConnect / EIP-1193                | [TonConnect (TEP-0115)](/ecosystem/ton-connect/overview)           |\n"
  },
  {
    "path": "get-support.mdx",
    "content": "---\ntitle: \"Get support\"\n---\n\nUse <kbd>Ctrl + K</kbd> to do an indexed search with AI fallback, or press <kbd>Ctrl + I</kbd> to open the assistant panel directly.\n\n## Telegram chats, channels, and bots\n\n- [Official TON Developers folder](https://t.me/addlist/dyiIa5Skb3JiN2Fk) - main collection of channels to subscribe to:\n  - Mainnet and testnet status updates.\n  - Developer news.\n  - Contests and grants.\n  - Job opportunities.\n  - Ecosystem news.\n\nValidators and nodes:\n\n- [TON Validators Support bot](https://t.me/validators_help_bot) - tech support for validators.\n- [TON Node Help chat](https://t.me/ton_node_help) - tech support chat group for non-validator nodes, like archive nodes or liteservers.\n\nAPIs:\n\n- [TON Center API Tech Support bot](https://t.me/toncenter_help_bot) - tech support for [TON Center APIs](https://toncenter.com).\n  - To get API keys, use the general [TON Center bot](https://t.me/toncenter)\n\nMiscellaneous:\n\n- [TON Help bot](https://t.me/ton_help_bot) - tech support for TON Core products (bridge, vesting, multisig, etc).\n\n## Builders portal\n\n- [TON Builders Portal](https://builders.ton.org) - main entry point for new projects: support programs, resources, and partner offers.\n\n## Security audit firms, agencies, and freelancers\n\n- [TON Talent Directory](https://ton.org/en/talents) - list of professionals, agencies, and auditors.\n- [Auditors in TON Talent Directory](https://ton.org/en/talents?auditors) - find security auditors for smart contracts and TON-based applications.\n\n## Bug bounty programs\n\n- [TON Security Bug Bounty on GitHub](https://github.com/ton-blockchain/bug-bounty) - description and links to all relevant projects and resources to research vulnerabilities in.\n- [TON Security Bug Bounty bot in Telegram](https://t.me/ton_bugs_bot) - send general blockchain security reports to this Telegram bot.\n- [HackenProof](https://hackenproof.com/programs/ton) - websites, web apps, and Telegram mini-apps operated by TON Foundation.\n\n## GitHub repository\n\n- [Main TON monorepo](https://github.com/ton-blockchain/ton) - source code for the node and validator, lite-client, tonlib, FunC compiler, and related tools.\n"
  },
  {
    "path": "index.mdx",
    "content": "---\ntitle: \"TON documentation\"\ndescription: \"TON is a blockchain platform designed for scalable smart contracts, applications, and payments at consumer scale.\"\nmode: \"custom\"\n\"og:image\": \"resources/logo/og-image.png\"\n\"twitter:image\": \"resources/logo/og-image.png\"\n---\n\nexport const Journey = ({ title, description, children }) => {\n  return (\n    <div className=\"card block font-normal group mt-2 px-6 pt-5 pb-4 ring-2 ring-transparent rounded-2xl !bg-transparent border border-gray-950/10 dark:border-white/10 w-full max-full\">\n      <h3 className=\"mb-1 text-balance text-base sm:text-xl font-semibold tracking-tight text-gray-900 dark:text-gray-200\">\n        {title}\n      </h3>\n      <p className=\"text-pretty text-base prose prose-gray dark:prose-invert\">\n        {description}\n      </p>\n      {children && (\n        <div className=\"mt-2 overflow-x-auto\">\n          <div className=\"flex flex-row gap-4 py-1\">\n            {children}\n          </div>\n        </div>\n      )}\n    </div>\n  );\n};\n\nexport const JourneyStep = ({ title, icon, iconType, href, cta, children }) => {\n  return (\n    <div className=\"flex-none w-52 max-h-64\">\n      <a\n        className=\"card block font-normal group ring-2 ring-transparent rounded-2xl !bg-transparent border border-gray-950/10 dark:border-white/10 overflow-hidden w-full h-full cursor-pointer hover:!border-primary dark:hover:!border-primary-light\"\n        {...(href && { href: href })}\n      >\n        <div className=\"px-6 py-5 h-full flex flex-col\" data-component-part=\"card-content-container\">\n          {icon && (\n            <div className=\"h-6 w-6 mb-4 fill-gray-800 dark:fill-gray-100 text-gray-800 dark:text-gray-100 shrink-0\" data-component-part=\"card-icon\">\n              <Icon icon={icon} iconType={iconType} color=\"#0098EA\" size={16} />\n            </div>\n          )}\n          <div className=\"flex-1 flex flex-col min-h-0\">\n            <h2 className=\"not-prose font-semibold text-base text-gray-800 dark:text-white shrink-0\" contentEditable=\"false\" data-component-part=\"card-title\">{title}</h2>\n            {children && (<div className=\"prose mt-1 font-normal text-sm leading-6 text-gray-600 dark:text-gray-400 flex-1 overflow-hidden\" data-component-part=\"card-content\"><span data-as=\"p\">{children}</span></div>)}\n            {cta && (\n              <div className=\"mt-8 shrink-0\" data-component-part=\"card-cta\"><button className=\"text-left text-gray-600 gap-2 dark:text-gray-400 text-sm font-medium flex flex-row items-center hover:text-primary dark:hover:text-primary-light\">{cta}<svg width=\"3\" height=\"24\" viewBox=\"0 -9 3 24\" className=\"rotate-0 overflow-visible h-6\"><path d=\"M0 0L3 3L0 6\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\"></path></svg></button></div>\n            )}\n          </div>\n        </div>\n      </a>\n    </div>\n  );\n};\n\n<div\n  className=\"relative w-full box-border flex flex-col mx-auto px-6 max-w-xl sm:max-w-2xl md:max-w-3xl lg:max-w-4xl xl:max-w-5xl\"\n>\n  {/* hero section */}\n  <div className=\"relative isolate\">\n    {/* color splash */}\n    <div\n      aria-hidden=\"true\"\n      className=\"absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-60\"\n    >\n      <div\n        style={{ clipPath: \"polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)\" }}\n        className=\"relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#2d83ec] to-[#1ac9ff] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]\"\n      />\n    </div>\n    {/* content */}\n    <div className=\"py-8 sm:py-12 lg:py-16 flex flex-col lg:flex-row lg:items-start lg:gap-0 xl:gap-0\">\n      <div className=\"hidden lg:flex justify-start mr-8\" >\n        <img\n          src=\"/resources/logo/ton.svg\"\n          alt=\"TON logo\"\n          className=\"h-32 w-auto\"\n          noZoom=\"true\"\n        />\n      </div>\n      <div className=\"w-full lg:flex-[2] mx-auto lg:mx-0 lg:max-w-2xl\">\n        <div className=\"text-left\">\n          <h1\n              className=\"text-balance text-4xl sm:text-4xl font-semibold tracking-tight text-gray-900 dark:text-gray-200\"\n          >\n            TON documentation\n          </h1>\n          <p\n            className=\"mt-8 max-w-xl text-pretty text-xl sm:text-xl prose prose-gray dark:prose-invert\"\n          >\n            TON is a blockchain platform designed for scalable smart contracts, applications, and payments at consumer scale.\n          </p>\n        </div>\n      </div>\n    </div>\n    {/* color splash */}\n    <div\n      aria-hidden=\"true\"\n      className=\"absolute inset-x-0 top-[calc(100%-13rem)] -z-10 transform-gpu overflow-hidden blur-3xl sm:top-[calc(100%-40rem)]\"\n    >\n      <div\n        style={{ clipPath: \"polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)\" }}\n        className=\"relative left-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#1ac9ff] to-[#2d83ec] opacity-30 sm:left-[calc(50%+24rem)] sm:w-[72.1875rem]\"\n      />\n    </div>\n  </div>\n\n  {/* journeys */}\n  <section\n    id=\"journeys\"\n    tabIndex={-1}\n    className=\"relative mt-0 py-0 sm:py-2 flex flex-col gap-4 focus:outline-none dark:focus:outline-none\"\n  >\n    <div className=\"flex flex-col gap-4\">\n      <div className=\"text-left\">\n        <h2\n          className=\"text-balance text-xl sm:text-2xl font-semibold tracking-tight text-gray-900 dark:text-gray-200\"\n        >\n          Choose your path\n        </h2>\n      </div>\n      <Journey\n        title=\"Beginner\"\n        description=\"TON fundamentals for newcomers entering Web3 through TON.\"\n      >\n        <JourneyStep\n          title=\"How to read this documentation?\"\n          iconType=\"solid\"\n          href=\"/start-here\"\n        />\n        <JourneyStep\n          title=\"Writing your first smart contract\"\n          iconType=\"solid\"\n          href=\"/contract-dev/first-smart-contract\"\n        />\n        <JourneyStep\n          title=\"Using a TON wallet\"\n          iconType=\"solid\"\n          href=\"/ecosystem/wallet-apps/tonkeeper\"\n        />\n        <JourneyStep\n          title=\"Introduction to Tolk\"\n          iconType=\"solid\"\n          href=\"/languages/tolk/overview\"\n        />\n      </Journey>\n      <Journey\n        title=\"Apps\"\n        description=\"Everything one needs to build applications on TON.\"\n      >\n        <JourneyStep\n          title=\"Connect wallets to the app\"\n          iconType=\"solid\"\n          href=\"/ecosystem/ton-connect/overview\"\n        >\n        </JourneyStep>\n        <JourneyStep\n          title=\"Manage and track assets with AppKit\"\n          iconType=\"solid\"\n          href=\"/ecosystem/appkit/overview\"\n        >\n        </JourneyStep>\n        <JourneyStep\n          title=\"Access the blockchain via APIs\"\n          iconType=\"solid\"\n          href=\"/ecosystem/api/overview\"\n        >\n        </JourneyStep>\n        <JourneyStep\n          title=\"Build apps using SDKs\"\n          iconType=\"solid\"\n          href=\"/ecosystem/sdks\"\n        >\n        </JourneyStep>\n      </Journey>\n      <Journey\n        title=\"Smart contracts\"\n        description=\"Build, debug, and deploy smart contracts on TON.\"\n      >\n       <JourneyStep\n          title=\"Tools to build\"\n          href=\"/contract-dev/blueprint/overview\"\n        >\n        </JourneyStep>\n        <JourneyStep\n          title=\"TVM exit codes\"\n          href=\"/tvm/exit-codes\"\n        >\n        </JourneyStep>\n        <JourneyStep\n          title=\"TVM instructions\"\n          href=\"/tvm/instructions\"\n        >\n        </JourneyStep>\n        <JourneyStep\n          title=\"Debugging smart contracts\"\n          href=\"/contract-dev/debug\"\n        >\n        </JourneyStep>\n      </Journey>\n      <Journey\n        title=\"Nodes\"\n        description=\"Run and manage TON blockchain nodes.\"\n      >\n        <JourneyStep\n          title=\"Nodes overview\"\n          href=\"/ecosystem/nodes/overview\"\n        >\n        </JourneyStep>\n        <JourneyStep\n          title=\"Validator node\"\n          href=\"/ecosystem/nodes/overview#validator-node\"\n        >\n        </JourneyStep>\n        <JourneyStep\n          title=\"C++ node setup\"\n          href=\"/ecosystem/nodes/cpp/setup-mytonctrl\"\n        >\n        </JourneyStep>\n        <JourneyStep\n          title=\"Rust node setup\"\n          href=\"/ecosystem/nodes/rust/quick-start\"\n        >\n        </JourneyStep>\n       </Journey>\n    </div>\n  </section>\n\n  {/* troubleshooting */}\n  <section\n    id=\"troubleshooting\"\n    tabIndex={-1}\n    className=\"relative mt-8 md:mt-4 py-1 sm:py-2 flex flex-col gap-4 focus:outline-none dark:focus:outline-none\"\n  >\n    <div className=\"text-left\">\n      <h2\n        className=\"text-balance text-2xl sm:text-2xl font-semibold tracking-tight text-gray-900 dark:text-gray-200\"\n      >\n        Troubleshooting\n      </h2>\n      <p className=\"mt-2 text-pretty sm:text-lg prose prose-gray dark:prose-invert\">\n        Can't find what you need? Use <kbd>Ctrl + K</kbd> to search and ask AI, or <kbd>Ctrl + I</kbd> to open the assistant panel.\n      </p>\n      <p className=\"mt-2 text-pretty sm:text-lg prose prose-gray dark:prose-invert\">\n        Still stuck? Discuss issues and best practices with other community members.\n      </p>\n    </div>\n    <Columns cols={3}>\n      <Card\n        title=\"Get support\"\n        icon=\"life-ring\"\n        iconType=\"solid\"\n        href=\"/get-support\"\n      >\n        Learn how to get help on the dedicated page\n      </Card>\n      <Card\n        title=\"Telegram\"\n        icon=\"telegram\"\n        iconType=\"solid\"\n        arrow=\"true\"\n        href=\"https://t.me/addlist/1r5Vcb8eljk5Yzcy\"\n      >\n        Add the folder with many developer chats\n      </Card>\n      <Card\n        title=\"TON Talents\"\n        icon=\"user-group\"\n        iconType=\"solid\"\n        arrow=\"true\"\n        href=\"https://ton.org/en/talents\"\n      >\n        Seek skilled professionals and agencies\n      </Card>\n    </Columns>\n  </section>\n</div>\n"
  },
  {
    "path": "languages/fift/deep-dive.mdx",
    "content": "---\ntitle: \"Fift deep dive\"\nsidebarTitle: \"Deep dive\"\nnoindex: \"true\"\n---\n\nFift is a high-level stack-based language used for local manipulation of cells and other TVM primitives. Its primary purpose is to compile TVM assembly code into contract code as a bag-of-cells (BoC).\n\n<Aside type=\"caution\">\n\n  **Advanced topic notice** This section covers low-level interactions with TON's implementation details. Before proceeding, ensure you have:\n\n  - Solid experience with stack-based programming paradigms\n  - Understanding of virtual machine architectures\n  - Familiarity with low-level data structures\n\n</Aside>\n\n## Simple arithmetic\n\nUse the Fift interpreter as a calculator with reverse Polish notation:\n\n```fift\n6 17 17 * * 289 + .\n2023 ok\n```\n\nThis example calculates:\n\n1. `17 * 17 = 289`\n2. `6 * 289 = 1734`\n3. `1734 + 289 = 2023`\n\n## Standard output\n\n```fift\n27 emit .\"[30;1mgrey text\" 27 emit .\"[37m\"\ngrey text ok\n```\n\n- `emit` prints the Unicode character corresponding to the number on top of the stack\n- `.\"...\"` outputs a constant string\n\n## Defining functions (Fift words)\n\nTo define a word, follow these steps:\n\n1. **Enclose the word's effects** in curly braces `{}`.\n2. **Add a colon `:`** after the closing brace.\n3. **Specify the word's name** after the colon.\n\nThe first line defines the word `increment` as a function that increases `x` by `1`.\n\n**Examples:**\n\n```fift\n// Fift.fif\n{ x 1 + } : increment\n{ minmax drop } : min\n{ minmax nip } : max\n```\n\nIn TON, multiple **defining words** exist, not just `:`. They differ in behavior:\n\n- **Active words** – Operate inside curly braces `{}`.\n- **Prefix words** – Do not require a trailing space.\n\n```fift\n// Fift.fif\n{ bl word 1 2 ' (create) } \"::\" 1 (create)\n{ bl word 0 2 ' (create) } :: :\n{ bl word 2 2 ' (create) } :: :_\n{ bl word 3 2 ' (create) } :: ::_\n{ bl word 0 (create) } : create\n```\n\n## Conditional execution\n\nExecute code blocks conditionally using `cond`:\n\n```fift\n{ { .\"true \" } { .\"false \" } cond } : ?.   4 5 = ?.  4 5 < ?.\nfalse true  ok\n{ .\"hello \" } execute .\"world\"\nhello world ok\n```\n\n## Loops\n\nUse loop primitives for repetitive operations:\n\n```fift\n// GetOpt.fif\n// ( l c -- l') Removes first c elements from list l\n{ ' safe-cdr swap times } : list-delete-first\n```\n\nLoop word `times` takes two arguments - let's call them `cont` and `n` - and executes `cont` `n` times.\nHere `list-delete-first` takes continuation of `safe-cdr` (command deleting head from Lisp-style list), places it under `c`, and then `c` times removes head from list present on stack.\n`while`/`until` provide conditional looping.\n\n## Comments\n\nComments in Fift are defined in `Fift.fif` and come in two forms:\n1. **Single-line comments**: Start with `//` and continue to the end of the line\n2. **Multiline comments**: Start with `/*` and end with `*/`\n\n```fift\n// Fift.fif\n{ 0 word drop 0 'nop } :: //\n{ char \" word 1 { swap { abort } if drop } } ::_ abort\"\n{ { bl word dup \"\" $= abort\"comment extends after end of file\" \"*/\" $= } until 0 'nop } :: /*\n```\n\n#### How comments work\n\nFift programs are sequences of words that transform the stack or define new words. Comments must work even during word definitions, requiring them to be **active words** (defined with `::`).\n\nBreaking down the `//` definition:\n1. `0` - Pushes zero onto the stack\n2. `word` - Reads characters until reaching one matching the top stack value (zero is special - skips leading spaces then reads to end of line)\n3. `drop` - Removes the comment text from the stack\n4. `0` - Pushes zero again (number of results for `::` definition)\n5. `'nop` - Pushes an execution token that does nothing (equivalent to `{ nop }`)\n\n\n## Using Fift for defining TVM assembly codes\n\n```fift\n// Asm.fif (line order reversed)\nx{00} @Defop NOP\n{ 1 ' @addop does create } : @Defop\n{ tuck sbitrefs @ensurebitrefs swap s, } : @addop\n{ @havebitrefs ' @| ifnot } : @ensurebitrefs\n{ 2 pick brembitrefs 1- 2x<= } : @havebitrefs\n{ rot >= -rot <= and } : 2x<=\n...\n```\n\n### How `@Defop` works\n\n`@Defop` checks available space for the opcode using `@havebitrefs`. If space is insufficient, it writes to another builder via `@|` (implicit jump).\n\n**Important:** Always use `x{A988} @addop` instead of `x{A988} s,` to avoid compilation failures when space is limited.\n\n### Including cells in contracts\n\nYou can embed large bag-of-cells into contracts:\n\n```fift\n<b 8 4 u, 8 4 u, \"fift/blob.boc\" file>B B>boc ref, b> <s @Defop LDBLOB\n```\n\nThis defines an opcode that:\n1. Writes `x{88}` (`PUSHREF`) when included in the program\n2. Adds a reference to the specified bag-of-cells\n3. Pushes the cell to the TVM stack when executing `LDBLOB`\n\n## Special features\n\n### Ed25519 cryptography\n\nFift provides built-in support for Ed25519 cryptographic operations:\n- **`newkeypair`** - Generates a private-public key pair\n- **`priv>pub`** - Derives a public key from a private key\n- **`ed25519_sign[_uint]`** - Creates a signature for given data using a private key\n- **`ed25519_chksign`** - Verifies an Ed25519 signature\n\n### TVM interaction\n\n- **`runvmcode` and similar commands** - Executes TVM with a code slice taken from the stack\n\n### File operations\n\n- **Save BoC to file**:\n\n  ```fift\n  boc>B \".../contract.boc\" B>file\n  ```\n\n## Continue learning\n\n- [Fift: A Brief Introduction](/resources/pdfs/fiftbase.pdf) - _Nikolai Durov_\n"
  },
  {
    "path": "languages/fift/fift-and-tvm-assembly.mdx",
    "content": "---\ntitle: \"Fift and TVM assembly\"\nnoindex: \"true\"\n---\n\nFift is a stack-based programming language with TON-specific features that can work with cells. TVM assembly is another stack-based language designed for TON that also handles cells. What's the difference between them?\n\n## Key differences\n\nFift executes at **compile-time** - when your compiler builds the smart contract code BoC after processing FunC code. Fift can appear in different forms:\n\n- TVM opcode definitions in `Asm.fif`:\n\n  ```fift\n  // Tuple primitives\n  x{6F0} @Defop(4u) TUPLE\n  x{6F00} @Defop NIL\n  x{6F01} @Defop SINGLE\n  x{6F02} dup @Defop PAIR @Defop CONS\n  ```\n\n- `wallet_v3_r2.fif`:\n\n  ```fift\n  \"Asm.fif\" include\n  <{ SETCP0 DUP IFNOTRET // Return if recv_internal\n     DUP 85143 INT EQUAL OVER 78748 INT EQUAL OR IFJMP:<{ // \"seqno\" and \"get_public_key\" get-methods\n       1 INT AND c4 PUSHCTR CTOS 32 LDU 32 LDU NIP 256 PLDU CONDSEL  // cnt or pubk\n     }>\n     INC 32 THROWIF    // Fail unless recv_external\n     9 PUSHPOW2 LDSLICEX DUP 32 LDU 32 LDU 32 LDU     // signature in_msg subwallet_id valid_until msg_seqno cs\n     NOW s1 s3 XCHG LEQ 35 THROWIF    // signature in_msg subwallet_id cs msg_seqno\n     c4 PUSH CTOS 32 LDU 32 LDU 256 LDU ENDS    // signature in_msg subwallet_id cs msg_seqno stored_seqno stored_subwallet public_key\n     s3 s2 XCPU EQUAL 33 THROWIFNOT    // signature in_msg subwallet_id cs public_key stored_seqno stored_subwallet\n     s4 s4 XCPU EQUAL 34 THROWIFNOT    // signature in_msg stored_subwallet cs public_key stored_seqno\n     s0 s4 XCHG HASHSU    // signature stored_seqno stored_subwallet cs public_key msg_hash\n     s0 s5 s5 XC2PU    // public_key stored_seqno stored_subwallet cs msg_hash signature public_key\n     CHKSIGNU 35 THROWIFNOT    // public_key stored_seqno stored_subwallet cs\n     ACCEPT\n     WHILE:<{\n       DUP SREFS    // public_key stored_seqno stored_subwallet cs _51\n     }>DO<{    // public_key stored_seqno stored_subwallet cs\n       8 LDU LDREF s0 s2 XCHG    // public_key stored_seqno stored_subwallet cs _56 mode\n       SENDRAWMSG\n     }>    // public_key stored_seqno stored_subwallet cs\n     ENDS SWAP INC    // public_key stored_subwallet seqno'\n     NEWC 32 STU 32 STU 256 STU ENDC c4 POP\n  }>c\n  ```\n\nThe last code fragment resembles TVM assembly because most of it actually is TVM assembly. Here's why:\n\nImagine explaining programming concepts to a trainee. Your instructions become part of their program, processed twice - similar to how opcodes in capital letters (SETCP0, DUP, etc.) are processed by both Fift and TVM.\n\nThink of Fift as a teaching language where you can introduce high-level concepts to a learner. Just as a trainee programmer gradually absorbs and applies new concepts, Fift allows you to define custom commands and abstractions. The `Asm.fif` file demonstrates this perfectly - it's essentially a collection of TVM opcode definitions.\n\nTVM assembly, in contrast, is like the trainee's final working program. While it operates with fewer built-in features (it can't perform cryptographic signing, for instance), it has direct access to the blockchain environment during contract execution. Where Fift works at compile-time to shape the contract's code, TVM assembly runs that code on the actual blockchain.\n\n## Smart contract usage\n\n### (Fift) Including large BoCs in contracts\n\nWhen using `toncli`, you can include large BoCs by:\n\n1. Editing `project.yaml` to include `fift/blob.fif`:\n\n```yaml\ncontract:\n  fift:\n    - fift/blob.fif\n  func:\n    - func/code.fc\n```\n\n2. Adding the BoC to `fift/blob.boc`\n\n2. Including this code in `fift/blob.fif`:\n\n```fift\n<b 8 4 u, 8 4 u, \"fift/blob.boc\" file>B B>boc ref, b> <s @Defop LDBLOB\n```\n\nNow you can access the blob in your contract:\n\n```func\ncell load_blob() asm \"LDBLOB\";\n\n() recv_internal() {\n    send_raw_message(load_blob(), 160);\n}\n```\n\n### (TVM assembly) Converting integers to strings\n\nFift primitives can't convert integers to strings at runtime because Fift operates at compile-time. For runtime conversion, use TVM assembly like this solution from TON Smart Challenge 3:\n\n```func\ntuple digitize_number(int value)\n  asm \"NIL WHILE:<{ OVER }>DO<{ SWAP TEN DIVMOD s1 s2 XCHG TPUSH }> NIP\";\n\nbuilder store_number(builder msg, tuple t)\n  asm \"WHILE:<{ DUP TLEN }>DO<{ TPOP 48 ADDCONST ROT 8 STU SWAP }> DROP\";\n\nbuilder store_signed(builder msg, int v) inline_ref {\n  if (v < 0) {\n    return msg.store_uint(45, 8).store_number(digitize_number(-v));\n  } elseif (v == 0) {\n    return msg.store_uint(48, 8);\n  } else {\n    return msg.store_number(digitize_number(v));\n  }\n}\n```\n\n### (TVM assembly) Efficient modulo multiplication\n\nCompare these implementations:\n\n```func\nint mul_mod(int a, int b, int m) inline_ref {               ;; 1232 gas units\n  (_, int r) = muldivmod(a % m, b % m, m);\n  return r;\n}\nint mul_mod_better(int a, int b, int m) inline_ref {        ;; 1110 gas units\n  (_, int r) = muldivmod(a, b, m);\n  return r;\n}\nint mul_mod_best(int a, int b, int m) asm \"x{A988} s,\";     ;; 65 gas units\n```\n\nThe `x{A988}` opcode implements an optimized division operation with built-in multiplication (as specified in [section 5.2 Division](/tvm/instructions#A988)). This specialized instruction directly computes just the modulo remainder of the operation, skipping unnecessary computation steps. The `s,` suffix then handles the result storage - it takes the resulting slice from the stack's top and efficiently writes it into the target builder. Together, this combination delivers substantial gas savings compared to conventional approaches.\n"
  },
  {
    "path": "languages/fift/multisig.mdx",
    "content": "---\ntitle: \"Simple multisig contract with Fift\"\nsidebarTitle: \"Simple multisig contract\"\nnoindex: \"true\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nThis information is **very low-level**. It could be hard for newcomers and designed for advanced people who want to understand [Fift](/languages/fift). The use of Fift is not required in everyday tasks.\n\n## Overview\n\nThis tutorial helps you learn how to deploy your multisig contract. Recall that a $(n, k)$-multisig contract is a multi-signature wallet with $n$ private key holders, which accepts requests to send messages if the request (a.k.a. order, query) collects at least $k$ holders' signatures.\n\nBased on the original multisig contract code and updates by akifoq:\n\n- [Original TON Blockchain multisig-code.fc](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/multisig-code.fc)\n- [akifoq/multisig](https://github.com/akifoq/multisig) with Fift libraries to work with multisig.\n\n<Aside\n  type=\"tip\"\n  title=\"Prefer videos over text?\"\n>\n  Watch this if you are new to multi-signature wallets: [What is Multisig Technology? (video)](https://www.youtube.com/watch?v=yeLqe_gg2u0)\n</Aside>\n\n## What you'll learn\n\n- How to create and customize a simple multisig wallet.\n- How to deploy a multisig wallet using a Lite client.\n- How to sign a request and send it in a message to the blockchain.\n\n## Set up your environment\n\nBefore we begin our journey, check and prepare your environment.\n\n- Install `func`, `fift`, `lite-client` binaries, and `fiftlib` from the [latest GitHub release](https://github.com/ton-blockchain/ton/releases/latest).\n- Clone the [repository](https://github.com/akifoq/multisig) and open its directory in CLI.\n\n```shell\ngit clone https://github.com/akifoq/multisig.git\ncd ./multisig\n```\n\n## Get started\n\n1. Compile the code to Fift.\n1. Prepare multisig owner's keys.\n1. Deploy your contract.\n1. Interact with the deployed multisig wallet in the blockchain.\n\n### Compile the contract\n\nCompile the contract to Fift with:\n\n```shell\nfunc -o multisig-code.fif -SPA stdlib.fc multisig-code.fc\n```\n\n### Prepare multisig owner's keys\n\n#### Create participant's keys\n\nTo create a key, you need to run:\n\n```shell\nfift -s new-key.fif $KEY_NAME$\n```\n\n- Where `KEY_NAME` is the file name where the private key will be written.\n\nFor example:\n\n```shell\nfift -s new-key.fif multisig_key\n```\n\nWe'll receive a `multisig_key.pk` file with the private key inside.\n\n#### Collect public keys\n\nAlso, the script will issue a public key in the format:\n\n```\nPublic key = Pub5XqPLwPgP8rtryoUDg2sadfuGjkT4DLRaVeIr08lb8CB5HW\n```\n\nAnything after `Public key = ` needs to be saved somewhere!\n\nLet's store it in a file called `keys.txt`. It's essential to have one public key per line.\n\n### Deploy your contract\n\n#### Deploy via `lite-client`\n\nAfter creating all the keys, you need to collect the public keys into a text file, `keys.txt`.\n\nFor example:\n\n```shell\nPubExXl3MdwPVuffxRXkhKN1avcGYrm6QgJfsqdf4dUc0an7/IA\nPubH821csswh8R1uO9rLYyP1laCpYWxhNkx+epOkqwdWXgzY4\n```\n\nAfter that, you need to run:\n\n```shell\nfift -s new-multisig.fif 0 $WALLET_ID$ wallet $KEYS_COUNT$ ./keys.txt\n```\n\n- `$WALLET_ID$`: the wallet number assigned to the current key. It is recommended that each new wallet with the same key use a unique `$WALLET_ID$`.\n- `$KEYS_COUNT$`: the number of keys needed for confirmation, usually equal to the number of public keys.\n\n<Aside\n  title=\"Wallet ID explained\"\n>\n  It is possible to create many wallets with the same keys (Alice's key, Bob's key). What should we do if Alice and Bob already share a wallet? That's why `$WALLET_ID$` is crucial here.\n</Aside>\n\nThe script will output something like:\n\n```shell\nnew wallet address = 0:4bbb2660097db5c72dd5e9086115010f0f8c8501e0b8fef1fe318d9de5d0e501\n\n(Saving address to file wallet.addr)\n\nNon-bounceable address (for init): 0QBLuyZgCX21xy3V6QhhFQEPD4yFAeC4_vH-MY2d5dDlAbel\n\nBounceable address (for later access): kQBLuyZgCX21xy3V6QhhFQEPD4yFAeC4_vH-MY2d5dDlAepg\n\n(Saved wallet creating query to file wallet-create.boc)\n```\n\nKeep the bounceable address — this is the wallet address we will be using.\n\n<Aside>\n  If you have a \"public key must be 48 characters long\" error, please make sure your `keys.txt` uses Unix-style line endings (LF). For example, line endings can be changed via Sublime Text.\n</Aside>\n\n#### Activate your contract\n\nYou need to send some TON to the newly generated wallet. For example, 0.5 TON. You can send testnet coins via [`@testgiver_ton_bot`](https://t.me/testgiver_ton_bot).\n\nAfter that, run `lite-client`:\n\n```shell\nlite-client -C global.config.json\n```\n\n<Aside\n  title=\"Where to get global.config.json?\"\n>\n  You can get a fresh config file `global.config.json` for [Mainnet](https://ton.org/global-config.json) or [Testnet](https://ton.org/testnet-global.config.json).\n</Aside>\n\nAfter starting a Lite client, it's best to run the `time` command in the `lite-client` console to make sure the connection was successful:\n\n```shell\ntime\n```\n\nOkay, Lite client works!\n\nAfter that, you need to deploy the wallet. Run the command:\n\n```shell\nsendfile ./wallet-create.boc\n```\n\nAfter that, the wallet will be ready to work within a minute.\n\n### Interact with a multisig wallet\n\n#### Create a request\n\nFirst, you need to create a message request:\n\n```shell\nfift -s create-msg.fif $ADDRESS$ $AMOUNT$ $MESSAGE$\n```\n\n- `$ADDRESS$` - address where to send coins.\n- `$AMOUNT$` - number of coins (in TON).\n- `$MESSAGE$` - the file name for the compiled message.\n\nFor example:\n\n```shell\nfift -s create-msg.fif EQApAj3rEnJJSxEjEHVKrH3QZgto_MQMOmk8l72azaXlY1zB 0.1 message\n```\n\n<Aside type=\"tip\">\n  Use the `-C comment` attribute to add a comment for your transaction. To get more information, run the `create-msg.fif` file without parameters.\n</Aside>\n\n#### Choose a wallet\n\nNext, you need to choose a wallet to send coins from:\n\n```shell\nfift -s create-order.fif $WALLET_ID$ $MESSAGE$ -t $AWAIT_TIME$\n```\n\nWhere:\n\n- `$WALLET_ID$` — ID of the wallet backed by this multisig contract.\n- `$AWAIT_TIME$` — time in seconds the smart contract will await signatures from the multisig wallet owners for the request.\n- `$MESSAGE$` — name of the message BoC file created in the previous step.\n\n<Aside>\n  The request expires if `$AWAIT_TIME$` elapses before the request is signed. As usual, `$AWAIT_TIME$` equals a couple of hours (7200 seconds).\n</Aside>\n\nFor example:\n\n```shell\nfift -s create-order.fif 0 message -t 7200\n```\n\nThe resulting file is saved as `order.boc`.\n\n<Aside>\n  `order.boc` must be shared with key holders; they must sign it.\n</Aside>\n\n#### Sign your part\n\nTo sign, run:\n\n```shell\nfift -s add-signature.fif $KEY$ $KEY_INDEX$\n```\n\n- `$KEY$` - file name containing the private key to sign, without extension.\n- `$KEY_INDEX$` - index of the given key in `keys.txt` (zero-based).\n\nFor example, for our `multisig_key.pk` file:\n\n```shell\nfift -s add-signature.fif multisig_key 0\n```\n\n#### Create a message\n\nAfter everyone has signed the order, it needs to be turned into a message for the wallet and signed again with the following command:\n\n```shell\nfift -s create-external-message.fif wallet $KEY$ $KEY_INDEX$\n```\n\nIn this case, only one signature from a wallet owner is enough. The idea is that you can't attack a contract with invalid signatures.\n\nFor example:\n\n```shell\nfift -s create-external-message.fif wallet multisig_key 0\n```\n\n#### Send the signed message to the TON blockchain\n\nAfter that, start `lite-client` again:\n\n```shell\nlite-client -C global.config.json\n```\n\nAnd finally, we want to send our sign! Just run:\n\n```shell\nsendfile wallet-query.boc\n```\n\nIf everyone else signed the request, it would be completed!\n\nYou did it!\n\n## See also\n\n- [Multisignature wallet v2](https://github.com/ton-blockchain/multisig-contract-v2)\n"
  },
  {
    "path": "languages/fift/overview.mdx",
    "content": "---\ntitle: \"Fift language overview\"\nsidebarTitle: \"Overview\"\nnoindex: \"true\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside>\n  The official language of TON Blockchain is [Tolk](/languages/tolk), and all other languages are deemed legacy. That said, you can still use them and contribute to the surrounding tooling or documentation.\n</Aside>\n\nFift is a [stack-based](https://en.wikipedia.org/wiki/Stack-oriented_programming) general-purpose [tacit](https://en.wikipedia.org/wiki/Tacit_programming) programming language optimized for creating, debugging, and managing smart contracts on TON Blockchain.\n\nIt has been specifically designed to interact with TON Virtual Machine (TVM) and TON Blockchain. In particular, it offers native support for 257-bit integer arithmetic and cell manipulation, as well as an interface to the Ed25519-based cryptography employed by TON.\n\nFift also includes a macro assembler for TVM code, which is a common intermediate target of higher-level languages such as [Tolk](/languages/tolk), [FunC](/languages/func/overview), and [Tact](/languages/tact), as well as a common textual bitcode representation of smart contracts. For more examples of the latter, see [various blockchain explorers](/ecosystem/explorers/overview) and disassembled smart contracts.\n\n## Installation\n\n### Interpreter and libraries\n\nFift interpreter binaries for Windows, macOS (Intel or Arm64), and Ubuntu can be downloaded from the [latest GitHub release](https://github.com/ton-blockchain/ton/releases/latest).\n\nMake sure to also download the necessary libraries — download and unpack the `smartcont_lib.zip`. The `lib/` folder inside contains standard libraries of Fift, which must be exposed to it when running the interpreter.\n\nConsider the following example installation steps:\n\n<Steps>\n  <Step\n    title=\"Download the latest Fift binary\"\n  >\n    <Tabs>\n      <Tab\n        title=\"Windows\"\n      >\n        Go to the [latest GitHub release](https://github.com/ton-blockchain/ton/releases/latest), download `fift.exe` and place it somewhere on your `PATH`. To see the current state of the `PATH` variable, run `echo $env:PATH` in the PowerShell.\n      </Tab>\n\n      <Tab\n        title=\"Linux\"\n      >\n        Go to the [latest GitHub release](https://github.com/ton-blockchain/ton/releases/latest), download `fift-linux-x86_64` (64-bit, x86 arch) or `fift-linux-arm64` (64-bit, Arm arch), and place it somewhere on your `$PATH` as `fift`. To see the current state of the `$PATH` variable, run `echo $PATH | tr ':' '\\n'` in the terminal.\n      </Tab>\n\n      <Tab\n        title=\"macOS\"\n      >\n        Go to the [latest GitHub release](https://github.com/ton-blockchain/ton/releases/latest), download `fift-mac-x86-64` (64-bit, Intel) or `fift-mac-arm64` (64-bit, Apple Silicon), and place it somewhere on your `$PATH` as `fift`. To see the current state of the `$PATH` variable, run `echo $PATH | tr ':' '\\n'` in the terminal.\n      </Tab>\n    </Tabs>\n  </Step>\n\n  <Step\n    title=\"Download Fift's standard libraries\"\n  >\n    - Download `smartcont_lib.zip` from the [latest GitHub release](https://github.com/ton-blockchain/ton/releases/latest).\n    - Unzip it and extract the contents.\n    - Move the extracted `lib/` folder somewhere convenient. You can also place it under a different name.\n      - For example, for Linux and macOS, it can be moved to `~/.local/lib/fiftlib`\n      - For Windows, to `~/.fiftlib`\n  </Step>\n\n  <Step\n    title=\"Run Fift\"\n  >\n    To invoke the Fift binary, you'll need to pass it the standard libraries as such:\n\n    ```shell\n    fift -I /path/to/extracted/lib -i Asm.fif\n    ```\n\n    If you see errors or red-colored output lines, double-check the placement of the Fift binary and related libraries from previous steps.\n\n    Otherwise, write the following and press \"Enter\":\n\n    ```fift\n    2 2 + .s\n    ```\n\n    If you see \"4 ok\", then Fift has been successfully installed on your machine!\n\n    To learn about other launch options, add the `-h` flag by the end of the prior Fift invocation command.\n  </Step>\n</Steps>\n\n<Aside type=\"tip\">\n  For Linux and macOS, it might be convenient to make an alias as such:\n\n  ```shell\n  # Within .bash_aliases or .zsh_aliases\n  alias fift=\"/path/to/fift -I /path/to/extracted/lib -i Asm.fif\"\n  ```\n</Aside>\n\n### Additional tooling\n\n#### Extensions and plugins\n\n- [VS Code extension](https://marketplace.visualstudio.com/items?itemName=ton-core.vscode-ton) - powerful and feature-rich extension for Visual Studio Code (VSCode) and VSCode-based editors like VSCodium, Cursor, Windsurf, and others.\n  - Get it on the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=ton-core.vscode-ton).\n  - Get it on the [Open VSX Registry](https://open-vsx.org/extension/ton-core/vscode-ton).\n  - Or install from the [`.vsix` files in nightly releases](https://github.com/ton-blockchain/ton-language-server/releases).\n- [JetBrains IDEs plugin](https://plugins.jetbrains.com/plugin/23382-ton) - provides syntax highlighting, code navigation, and more.\n- [Language Server (LSP Server)](https://github.com/ton-blockchain/ton-language-server) - supports Sublime Text, (Neo)Vim, Helix, and other editors with LSP support.\n\n#### Online utilities\n\n- [TxTracer: Assembly playground](https://txtracer.ton.org/play/)\n- [TxTracer: Code explorer with assembly output](https://txtracer.ton.org/code-explorer/)\n- [TxTracer: TVM instruction table](https://txtracer.ton.org/spec/)\n\n## Getting started\n\nHere is a simple `Hello, World!` example written in Fift:\n\n```fift\n.\"Hello, World!\"\n```\n\nWhen [executed with `fift` binary](#installation), it produces the following output:\n\n```txt\nHello, World! ok\n```\n\nThere, `ok` means successful end of execution of the given code snippet.\n\n<Aside\n  type=\"caution\"\n>\n  When things go awry, there may still be an `ok` by the end, albeit prefixed with several red lines of cryptic-looking stack traces. Those are how Fift reports errors, and this is one of the major reasons why Fift is considered a legacy language.\n\n  **Any errors encountered during execution clear the stack!**\n\n  Hence, to actually know what happened, one needs to preemptively check stack contents. For that, use the [\"printf debugging\"](https://en.wikipedia.org/wiki/Debugging#printf_debugging) approach with the `.s` word — it dumps current stack contents to the console without modifying the stack.\n\n  ```fift\n  \"Hello, \" .s\n  // \"Hello, \"\n\n  \"World!\" .s\n  // \"Hello, \" \"World!\"\n\n  $+\n  // \"Hello, World!\"\n\n  type\n  // Hello, World! ok\n  // Now, the stack is clear.\n  ```\n</Aside>\n\nTo continue learning Fift, see the [educational materials](#educational-materials) section, or move to the follow-up references.\n\n<Columns cols={2}>\n  <Card\n    title=\"Fift and TVM assembly\"\n    href=\"/languages/fift/fift-and-tvm-assembly\"\n  />\n\n  <Card\n    title=\"Deep dive into Fift\"\n    href=\"/languages/fift/deep-dive\"\n  />\n\n  <Card\n    title=\"Simple multi-signature wallet\"\n    href=\"/languages/fift/multisig\"\n  />\n\n  <Card\n    title=\"Whitepapers (see below)\"\n    href=\"#whitepapers\"\n  />\n</Columns>\n\n## Educational materials\n\n### Whitepapers\n\n<Aside>\n  While most of the information described there holds some truth, the `fiftbase.pdf` whitepaper is still considered legacy due to a lack of updates and gradual integration of its contents into actual documentation pages.\n\n  However, it is the most exhaustive reference manual on Fift to date, so you can still use it to learn a lot about Fift.\n</Aside>\n\n<Columns cols={2}>\n  <Card\n    title=\"Fift language specification, web version\"\n    href=\"/languages/fift/whitepaper\"\n  >\n    Tacit stack-based programming language with a deep connection to TVM.\n  </Card>\n\n  <Card\n    title=\"Fift language specification, PDF\"\n    arrow\n    href=\"/resources/pdfs/fiftbase.pdf\"\n  >\n    Original documentation written by Dr. Nikolai Durov, a comprehensive whitepaper.\n  </Card>\n</Columns>\n\n### Articles\n\n<Columns cols={2}>\n  <Card\n    title=\"Introduction to Fift\"\n    arrow=\"true\"\n    href=\"https://blog.ton.org/introduction-to-fift\"\n  />\n</Columns>\n\n### Videos and playlists\n\n<Columns cols={2}>\n  <Card\n    title=\"«His majesty Fift»\"\n    arrow=\"true\"\n    href=\"https://www.youtube.com/@WikiMar/videos\"\n    cta=\"In Russian\"\n  />\n</Columns>\n\n### Examples\n\n<Columns cols={2}>\n  <Card\n    title=\"Simple multi-signature wallet\"\n    href=\"/languages/fift/multisig\"\n  />\n\n  <Card\n    title=\"Multi-signature wallet v2\"\n    arrow=\"true\"\n    href=\"https://github.com/ton-blockchain/multisig-contract-v2\"\n  />\n</Columns>\n\n## See also\n\n- [Multisignature wallet v2](https://github.com/ton-blockchain/multisig-contract-v2)\n- [Forth language](https://en.wikipedia.org/wiki/Forth_\\(programming_language\\))\n- [Factor language](https://en.wikipedia.org/wiki/Factor_\\(programming_language\\))\n- [Uiua language](https://www.uiua.org/)\n- [Concatenative languages](https://www.concatenative.org/wiki/view/Concatenative%20language)\n"
  },
  {
    "path": "languages/fift/whitepaper.mdx",
    "content": "---\ntitle: \"Fift: A Brief Introduction\"\nsidebarTitle: \"Whitepaper\"\ndescription: \"Whitepaper by Dr. Nikolai Durov\"\nnoindex: \"true\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n**Author**: Nikolai Durov <br />\n**Date**: July 4, 2019 <br />\n<Icon icon=\"file-pdf\" size={16} />: [Original whitepaper, PDF](/resources/pdfs/fiftbase.pdf)\n\n## Introduction\n\nThis document provides a brief description of Fift, a stack-based general-purpose programming language optimized for creating, debugging, and managing TON Blockchain smart contracts.\n\nFift has been specifically designed to interact with the TON Virtual Machine (TON VM or TVM) and the  TON Blockchain. In particular, it offers native support for 257-bit integer arithmetic and TVM cell manipulation shared with TVM, as well as an interface to the Ed25519-based cryptography employed by the TON Blockchain. A macro assembler for TVM code, useful for writing new smart contracts, is also included in the Fift distribution.\n\nBeing a stack-based language, Fift is not unlike Forth. Because of the brevity of this text, some knowledge of Forth might be helpful for understanding Fift.1 However, there are significant differences between the two languages. For instance, Fift enforces runtime type-checking, and keeps values of different types (not only integers) in its stack.\n\nA list of words (built-in functions, or primitives) defined in Fift, along with their brief descriptions, is presented in _Appendix A_.\n\nPlease note that the current version of this document describes a preliminary test version of Fift; some minor details are likely to change in the future.\n\n## Contents\n\n1. [**Overview**](#1-overview)\n\n2. [**Fift basics**](#2-fift-basics)\n   1. [List of Fift stack value types](#2-1-list-of-fift-stack-value-types)\n   2. [Comments](#2-2-comments)\n   3. [Terminating Fift](#2-3-terminating-fift)\n   4. [Simple integer arithmetic](#2-4-simple-integer-arithmetic)\n   5. [Stack manipulation words](#2-5-stack-manipulation-words)\n   6. [Defining new words](#2-6-defining-new-words)\n   7. [Named constants](#2-7-named-constants)\n   8. [Integer and fractional constants, or literals](#2-8-integer-and-fractional-constants-or-literals)\n   9. [String literals](#2-9-string-literals)\n   10. [Simple string manipulation](#2-10-simple-string-manipulation)\n   11. [Boolean expressions, or flags](#2-11-boolean-expressions-or-flags)\n   12. [Integer comparison operations](#2-12-integer-comparison-operations)\n   13. [String comparison operations](#2-13-string-comparison-operations)\n   14. [Named and unnamed variables](#2-14-named-and-unnamed-variables)\n   15. [Tuples and arrays](#2-15-tuples-and-arrays)\n   16. [Lists](#2-16-lists)\n   17. [Atoms](#2-17-atoms)\n   18. [Command line arguments in script mode](#2-18-command-line-arguments-in-script-mode)\n\n3. [**Blocks, loops, and conditionals**](#3-blocks-loops-and-conditionals)\n   1. [Defining and executing blocks](#3-1-defining-and-executing-blocks)\n   2. [Conditional execution of blocks](#3-2-conditional-execution-of-blocks)\n   3. [Simple loops](#3-3-simple-loops)\n   4. [Loops with an exit condition](#3-4-loops-with-an-exit-condition)\n   5. [Recursion](#3-5-recursion)\n   6. [Throwing exceptions](#3-6-throwing-exceptions)\n\n4. [**Dictionary, interpreter, and compiler**](#4-dictionary-interpreter-and-compiler)\n   1. [The state of the Fift interpreter](#4-1-the-state-of-the-fift-interpreter)\n   2. [Active and ordinary words](#4-2-active-and-ordinary-words)\n   3. [Compiling literals](#4-3-compiling-literals)\n   4. [Defining new active words](#4-4-defining-new-active-words)\n   5. [Defining words and dictionary manipulation](#4-5-defining-words-and-dictionary-manipulation)\n   6. [Dictionary lookup](#4-6-dictionary-lookup)\n   7. [Creating and manipulating word lists](#4-7-creating-and-manipulating-word-lists)\n   8. [Custom defining words](#4-8-custom-defining-words)\n\n5. [**Cell manipulation**](#5-cell-manipulation)\n   1. [Slice literals](#5-1-slice-literals)\n   2. [Builder primitives](#5-2-builder-primitives)\n   3. [Slice primitives](#5-3-slice-primitives)\n   4. [Cell hash operations](#5-4-cell-hash-operations)\n   5. [Bag-of-cells operations](#5-5-bag-of-cells-operations)\n   6. [Binary file I/O and Bytes manipulation](#5-6-binary-file-i-o-and-bytes-manipulation)\n\n6. [**TON-specific operations**](#6-ton-specific-operations)\n   1. [Ed25519 cryptography](#6-1-ed25519-cryptography)\n   2. [Smart-contract address parser](#6-2-smart-contract-address-parser)\n   3. [Dictionary manipulation](#6-3-dictionary-manipulation)\n   4. [Invoking TVM from Fift](#6-4-invoking-t-v-m-from-fift)\n\n7. [**Using the Fift assembler**](#7-using-the-fift-assembler)\n   1. [Loading the Fift assembler](#7-1-loading-the-fift-assembler)\n   2. [Fift assembler basics](#7-2-fift-assembler-basics)\n   3. [Pushing integer constants](#7-3-pushing-integer-constants)\n   4. [Immediate arguments](#7-4-immediate-arguments)\n   5. [Immediate continuations](#7-5-immediate-continuations)\n   6. [Control flow: loops and conditionals](#7-6-control-flow-loops-and-conditionals)\n   7. [Macro definitions](#7-7-macro-definitions)\n   8. [Larger programs and subroutines](#7-8-larger-programs-and-subroutines)\n\n8. [**References**](#references)\n9. [**Appendix A: List of Fift words**](#appendix-a%3A-list-of-fift-words)\n\n## 1 Overview\n\nFift is a simple stack-based programming language designed for testing and debugging the TON Virtual Machine and the TON Blockchain, but potentially useful for other purposes as well. When Fift is invoked (usually by executing a binary file called `fift`), it either reads, parses, and interprets one or several source files indicated in the command line, or enters the interactive mode and interprets Fift commands read and parsed from the standard input. There is also a \"script mode\", activated by command line switch `-s`, in which all command line arguments except the first one are passed to the Fift program by means of the variables `$n` and `$#`. In this way, Fift can be used both for interactive experimentation and debugging as well as for writing simple scripts.\n\nAll data manipulated by Fift is kept in a (LIFO) stack. Each stack entry is supplemented by a _type tag_, which unambiguously determines the type of the value kept in the corresponding stack entry. The types of values supported by Fift include _Integer_ (representing signed 257-bit integers), _Cell_ (representing a TVM cell, which consists of up to 1023 data bits and up to four references to other cells), _Slice_ (a partial view of a _Cell_ used for parsing cells), and _Builder_ (used for building new cells). These data types (and their implementations) are shared with TVM, and can be safely passed from the Fift stack to the TVM stack and back when necessary (e.g., when TVM is invoked from Fift by using a Fift primitive such as `runvmcode`).\n\nIn addition to the data types shared with TVM, Fift introduces some unique data types, such as _Bytes_ (arbitrary byte sequences), _String_ (UTF-8 strings), _WordList_, and _WordDef_ (used by Fift to create new \"words\" and manipulate their definitions). In fact, Fift can be extended to manipulate arbitrary \"objects\" (represented by the generic type _Object_), provided they are derived from C++ class `td::CntObject` in the current implementation.\n\nFift source files and libraries are usually kept in text files with the suffix `.fif`. A search path for libraries and included files is passed to the Fift executable either in a `-I` command line argument or in the `FIFTPATH` environment variable. If neither is set, the default library search path `/usr/lib/fift` is used.\n\nOn startup, the standard Fift library is read from the file `Fift.fif` before interpreting any other sources. It must be present in the library search path, otherwise Fift execution will fail.\n\nA fundamental Fift data structure is its global _dictionary_, containing _words_ — or, more precisely, _word definitions_ — that correspond both to builtin primitives and functions and to user-defined functions **`*`**. A word can be executed in Fift simply by typing its name (a UTF-8 string without space characters) in interactive mode. When Fift starts up, some words (_primitives_) are already defined (by some C++ code in the current implementation); other words are defined in the standard library `Fift.fif`. After that, the user may extend the dictionary by defining new words or redefining old ones.\n\n<Aside>\n\n  Fift words are typically shorter than functions or subroutines of other programming languages, such as Forth or Factor.\n\n</Aside>\n\nThe dictionary is supposed to be split into several _vocabularies_, or _namespaces_; however, _namespaces_ are not implemented yet, so all words are currently defined in the same global namespace.\n\nThe Fift parser for input source files and for the standard input (in the interactive mode) is rather simple: the input is read line-by-line, then blank characters are skipped, and the longest prefix of the remaining line that is (the name of) a dictionary word is detected and removed from the input line **`*`**. After that, the word thus found is executed, and the process repeats until the end of the line. When the input line is exhausted, a subsequent line is read from the current input file or the standard input.\n\n<Aside>\n\n  Notice that in contrast to Forth, Fift word names are case-sensitive: `dup` and `DUP` are distinct words.\n\n</Aside>\n\nIn order to be detected, most words require a blank character or an end-of-line immediately after them; this is reflected by appending a space to their names in the dictionary. Other words, called _prefix words_, do not require a blank character immediately after them.\n\nIf no word is found, the string consisting of the first remaining characters of the input line until the next blank or end-of-line character is interpreted as an _Integer_ and pushed into the stack. For instance, if we invoke Fift, type `2 3 + .` (and press Enter), Fift first pushes an _Integer_ constant equal to `2` into its stack, followed by another integer constant equal to `3`. After that, the built-in primitive `+` is parsed and found in the dictionary; when invoked, it takes the two topmost elements from the stack and replaces them with their sum (`5` in our example). Finally, `.` is a primitive that prints the decimal representation of the top-of-stack _Integer_, followed by a space. As a result, we observe `\"5 ok\"` printed by the Fift interpreter into the standard output. The string `\"ok\"` is printed by the interpreter whenever it finishes interpreting a line read from the standard input in the interactive mode.\n\nA list of built-in words may be found in Appendix A.\n\n## 2 Fift basics\n\nThis chapter provides an introduction into the basic features of the Fift programming language. The discussion is informal and incomplete at first, but gradually becomes more formal and more precise. In some cases, later chapters and Appendix A provide more details about the words first mentioned in this chapter; similarly, some tricks that will be dutifully explained in later chapters are already used here where appropriate.\n\n### 2.1 List of Fift stack value types\n\nCurrently, the values of the following data types can be kept in a Fift stack:\n\n| Type | Description | Denoted&nbsp;by\n| :--- | :---------- | :-------------:\n| _`Integer`_ | A signed 257-bit integer. Usually denoted by `x`, `y`, or `z` in the stack notation (when the stack effect of a Fift word is described). | `x|y|z`\n| _`Cell`_ | A TVM cell, consisting of up to `1023` data bits and up to `4` references to other cells. Usually denoted by `c` or its variants, such as `c0` or `c2`. | `c|c2`\n| _`Slice`_ | A partial view of a TVM cell, used for parsing data from Cells. | `s`\n| _`Builder`_ | A partially built _Cell_, containing up to `1023` data bits and up to four references; can be used to create new Cells. | `b`\n| _`Null`_ | A type with exactly one `\"null\"` value. Used to initialize new _Box_'es. Usually denoted by `⊥`. | `⊥`\n| _`Tuple`_ | An ordered collection of values of any of these types (not necessarily the same); can be used to represent values of arbitrary algebraic data types and Lisp-style lists. |\n| _`String`_ | A (usually printable) UTF-8 string. | `S`\n| _`Bytes`_ | An arbitrary sequence of 8-bit bytes, typically used to represent binary data. | `B`\n| _`WordList`_ | A (partially created) list of word references, used for creating new Fift word definitions. | `l`\n| _`WordDef`_ | An execution token, usually representing the definition of an existing Fift word. | `e`\n| _`Box`_ | A location in memory that can be used to store one stack value. | `p`\n| _`Atom`_ | A simple entity uniquely identified by its name, a string. Can be used to represent identifiers, labels, operation names, tags, and stack markers. | `a`\n| _`Object`_ | An arbitrary C++ object of any class derived from base class `td::CntObject;` may be used by Fift extensions to manipulate other data types and interface with other C++ libraries. |\n\nThe first six types listed above are shared with TVM; the remainder are Fift-specific. Notice that not all TVM stack types are present in Fift. For instance, the TVM _Continuation_ type is not explicitly recognized by Fift; if a value of this type ends up in a Fift stack, it is manipulated as a generic _Object_.\n\n### 2.2 Comments\n\nFift recognizes two kinds of comments:\n\n- `\"// \"` (which must be followed by a space) opens a single-line comment until the end of the line, and `/*` defines a multi-line comment until `*/`. Both words `//` and `/*` are defined in the standard Fift library (`Fift.fif`).\n\n### 2.3 Terminating Fift\n\nThe word `bye` terminates the Fift interpreter with a zero exit code. If a non-zero exit code is required (for instance, in Fift scripts), one can use word `halt`, which terminates Fift with the given exit code (passed as an _Integer_ at the top of the stack). In contrast, quit does not quit to the operating system, but rather exits to the top level of the Fift interpreter.\n\n### 2.4 Simple integer arithmetic\n\nWhen Fift encounters a word that is absent from the dictionary, but which can be interpreted as an integer constant (or \"literal\"), its value is pushed into the stack (as explained in 2.8 in more detail). Apart from that, several integer arithmetic primitives are defined:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`+`** | _`(x y – x + y)`_ | replaces two _Integer_'s `x` and `y` passed at the top of the stack with their sum `x + y`. All deeper stack elements remain intact. If either `x` or `y` is not an _Integer_, or if the sum does not fit into a signed 257-bit _Integer_, an exception is thrown.\n| **`-`** | _`(x y – x − y)`_ | computes the difference `x − y` of two _Integer_'s `x` and `y`. Notice that the first argument `x` is the second entry from the top of the stack, while the second argument `y` is taken from the top of the stack.\n| **`negate`** | _`(x – −x)`_ | changes the sign of an _Integer_.\n| **`*`** | _`(x y – xy)`_ | computes the product `xy` of two _Integer_'s `x` and `y`.\n| **`/`** | _`(x y – q := ⌊x/y⌋)`_ | computes the floor-rounded quotient `⌊x/y⌋` of two _Integer_'s.\n| **`mod`** | _`(x y – r := x mod y)`_ | computes the remainder `x` mod `y = x − y · ⌊x/y⌋` of division of `x` by `y`.\n| **`/mod`** | _`(x y – q r)`_ | computes both the quotient and the remainder.\n| **`/c, /r`** | _`(x y – q)`_ | division words similar to `/`, but using ceiling rounding `(q := ⌈x/y⌉)` and nearest-integer rounding `(q := ⌊1/2 + x/y⌋)`, respectively.\n| **`/cmod, /rmod`** | _`(x y – q r := x − qy)`_ | division words similar to `/mod`, but using ceiling or nearest-integer rounding.\n| **`<<`** | _`(x y – x · 2^y )`_ | computes an arithmetic left shift of binary number `x` by `y ≥ 0` positions, yielding `x · 2 y`.\n| **`>>`** | _`(x y – q := ⌊x · 2^−y⌋)`_ | computes an arithmetic right shift by `y ≥ 0` positions.\n| **`>>c, >>r`** | _`(x y – q)`_ | similar to `>>`, but using ceiling or nearest-integer rounding.\n| **`and, or, xor`** | _`(x y – x ⊕ y)`_ | compute the bitwise `AND`, `OR`, or `XOR` of two _Integer_'s.\n| **`not`** | _`(x – −1 − x)`_ | bitwise complement of an _Integer_.\n| **`*/`** | _`(x y z – ⌊xy/z⌋)`_ | _\"multiply-then-divide\"_: multiplies two integers `x` and `y` producing a 513-bit intermediate result, then divides the product by `z`.\n| **`*/mod`** | _`(x y z – q r)`_ | similar to `*/`, but computes both the quotient and the remainder.\n| **`*/c, */r`** | _`(x y z – q)`_ | similar to `*/`, but using ceiling or nearest-integer rounding.\n| **`*/cmod, */rmod`** | _`(x y z – q r)`_ | similar to `*/mod`, but using ceiling or nearest-integer rounding.\n| **`*>>, *>>c, *>>r`** | _`(x y z – q)`_ | similar to `*/` and its variants, but with division replaced with a right shift. Computes $q := \\frac{xy}{2^z}$ rounded in the indicated fashion (floor, ceiling, or nearest integer).\n| **`<</, <</c, <</r`** | _`(x y z – q)`_ | similar to `*/`, but with multiplication replaced with a left shift. Computes $q := 2^{z} * \\frac{x}{y}$ rounded in the indicated fashion (notice the different order of arguments `y` and `z` compared to `*/`).\n\nIn addition, the word `.` may be used to print the decimal representation of an _Integer_ passed at the top of the stack (followed by a single space), and `\"x.\"` prints the hexadecimal representation of the top-of-stack integer. The integer is removed from the stack afterwards.\n\nThe above primitives can be employed to use the Fift interpreter in interactive mode as a simple calculator for arithmetic expressions represented in reverse Polish notation (with operation symbols after the operands). For instance,\n\n```fift\n7 4 - .\n```\n\ncomputes `7 − 4 = 3` and prints `\"3 ok\"`, and\n\n```fift\n2 3 4 * + .\n2 3 + 4 * .\n```\n\ncomputes `2 + 3 · 4 = 14` and `(2 + 3) · 4 = 20`, and prints `\"14 20 ok\"`.\n\n### 2.5 Stack manipulation words\n\nStack manipulation words rearrange one or several values near the top of the stack, regardless of their types, and leave all deeper stack values intact. Some of the most often used stack manipulation words are listed below:\n\n<Aside>\n\n  Notice that Fift word names are case-sensitive, so one cannot type DUP instead of dup.\n\n</Aside>\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`dup`** | _`(x – x x)`_ | duplicates the top-of-stack entry. If the stack is empty, throws an exception.\n| **`drop`** | _`(x – )`_ | removes the top-of-stack entry.\n| **`swap`** | _`(x y – y x)`_ | interchanges the two topmost stack entries.\n| **`rot`** | _`(x y z – y z x)`_ | rotates the three topmost stack entries.\n| **`-rot`** | _`(x y z – z x y)`_ | rotates the three topmost stack entries in the opposite direction. Equivalent to `rot rot`.\n| **`over`** | _`(x y – x y x)`_ | creates a copy of the second stack entry from the top over the top-of-stack entry.\n| **`tuck`** | _`(x y – y x y)`_ | equivalent to `swap over`.\n| **`nip`** | _`(x y – y)`_ | removes the second stack entry from the top. Equivalent to `swap drop`.\n| **`2dup`** | _`(x y – x y x y)`_ | equivalent to `over over`.\n| **`2drop`** | _`(x y – )`_ | equivalent to `drop drop`.\n| **`2swap`** | _`(a b c d – c d a b)`_ | interchanges the two topmost pairs of stack entries.\n| **`pick`** | _`(xn ... x0 n – xn ... x0 xn)`_ | creates a copy of the `n-th` entry from the top of the stack, where `n ≥ 0` is also passed in the stack. In particular, `0 pick` is equivalent to `dup`, and `1 pick` to `over`.\n| **`roll`** | _`(xn ... x0 n – xn−1 ... x0 xn)`_ | rotates the top `n` stack entries, where `n ≥ 0` is also passed in the stack. In particular, `1 roll` is equivalent to `swap`, and `2 roll` to `rot`.\n| **`-roll`** | _`(xn ... x0 n – x0 xn ... x1)`_ | rotates the top `n` stack entries in the opposite direction, where `n ≥ 0` is also passed in the stack. In particular, `1 -roll` is equivalent to `swap`, and `2 -roll` to `-rot`.\n| **`exch`** | _`(xn ... x0 n – x0 ... xn)`_ | interchanges the top of the stack with the `n-th` stack entry from the top, where `n ≥ 0` is also taken from the stack. In particular, `1 exch` is equivalent to `swap`, and `2 exch` to `swap rot`.\n| **`exch2`** | _`(... n m – ... )`_ | interchanges the `n-th` stack entry from the top with the `m-th` stack entry from the top, where `n ≥ 0`, `m ≥ 0` are taken from the stack.\n| **`?dup`** | _`(x – x x or 0)`_ | duplicates an _Integer_ `x`, but only if it is non-zero. Otherwise leaves it intact.\n\nFor instance, `\"5 dup * .\"` will compute `5 · 5 = 25` and print `\"25 ok\"`.\n\nOne can use the word \".s\" — which prints the contents of the entire stack, starting from the deepest elements, without removing the elements printed from the stack—to inspect the contents of the stack at any time, and to check the effect of any stack manipulation words. For instance,\n\n```fift\n1 2 3 4 .s\nrot .s\n```\n\nprints\n\n```fift\n1 2 3 4\nok\n1 3 4 2\nok\n```\n\nWhen Fift does not know how to print a stack value of an unknown type, it instead prints `???`.\n\n### 2.6 Defining new words\n\nIn its simplest form, defining new Fift words is very easy and can be done with the aid of three special words: `{`, `}`, and `:`. One simply opens the definition with `{` (necessarily followed by a space), then lists all the words that constitute the new definition, then closes the definition with `}` (also followed by a space), and finally assigns the resulting definition (represented by a _WordDef_ value in the stack) to a new word by writing `: <new-word-name>`. For instance,\n\n```fift\n{ dup * } : square\n```\n\ndefines a new word `square`, which executes `dup` and `*` when invoked. In this way, typing `5 square` becomes equivalent to typing `5 dup *`, and produces the same result `(25)`:\n\n```fift\n5 square .\n```\n\nprints `\"25 ok\"`. One can also use the new word as a part of new definitions:\n\n```fift\n{ dup square square * } : **5\n3 **5 .\n```\n\nprints `\"243 ok\"`, which indeed is `3^5`.\n\nIf the word indicated after `:` is already defined, it is tacitly redefined. However, all existing definitions of other words will continue to use the old definition of the redefined word. For instance, if we redefine `square` after we have already defined `**5` as above, `**5` will continue to use the original definition of `square`.\n\n### 2.7 Named constants\n\nOne can define _(named) constants_ — i.e., words that push a predefined value when invoked—by using the defining word constant instead of the defining word `:` (colon). For instance,\n\n```fift\n1000000000 constant Gram\n```\n\ndefines a constant `Gram` equal to _Integer_ `10^9`. In other words, `1000000000` will be pushed into the stack whenever `Gram` is invoked:\n\n```fift\nGram 2 * .\n```\n\nprints `\"2000000000 ok\"`.\n\nOf course, one can use the result of a computation to initialize the value of a constant:\n\n```fift\nGram 1000 / constant mGram\nmGram .\n```\n\nprints `\"1000000 ok\"`.\n\nThe value of a constant does not necessarily have to be an _Integer_. For instance, one can define a string constant in the same way:\n\n```fift\n\"Hello, world!\" constant hello\nhello type cr\n```\n\nprints `\"Hello, world!\"` on a separate line.\n\nIf a constant is redefined, all existing definitions of other words will continue to use the old value of the constant. In this respect, a constant does not behave as a global variable.\nOne can also store two values into one \"double\" constant by using the\ndefining word `2constant`. For instance:\n\n```fift\n355 113 2constant pifrac\n```\n\ndefines a new word `pifrac`, which will push `355` and `113` (in that order) when invoked. The two components of a double constant can be of different types.\nIf one wants to create a constant with a fixed name within a block or a colon definition, one should use `=: ` and `2=: ` instead of `constant` and `2constant`:\n\n```fift\n{ dup =: x dup * =: y } : setxy\n3 setxy x . y . x y + .\n7 setxy x . y . x y + .\n```\n\nproduces\n\n```fift\n3 9 12 ok\n7 49 56 ok\n```\n\nIf one wants to recover the execution-time value of such a \"constant\", one can prefix the name of the constant with the word `@'`:\n\n```fift\n{ .\"( \" @' x . .\", \" @' y . .\") \" } : showxy\n3 setxy showxy\n```\n\nproduces `(3, 9) ok`.\n\nThe drawback of this approach is that `@'` has to look up the current definition of constants `x` and `y` in the dictionary each time `showxy` is executed. Variables provide a more efficient way to achieve similar results.\n\n### 2.8 Integer and fractional constants, or literals\n\nFift recognizes unnamed integer constants (called literals to distinguish them from named constants) in decimal, binary, and hexadecimal formats. Binary literals are prefixed by `0b`, hexadecimal literals are prefixed by `0x`, and decimal literals do not require a prefix. For instance, `0b1011`, `11`, and `0xb` represent the same integer `(11)`. An integer literal may be prefixed by a minus sign `-` to change its sign; the minus sign is accepted both before and after the `0x` and `0b` prefixes.\n\nWhen Fift encounters a string that is absent from the dictionary but is a valid integer literal (fitting into the 257-bit signed integer type _Integer_), its value is pushed into the stack.\n\nApart from that, Fift offers some support for decimal and common fractions. If a string consists of two valid integer literals separated by a slash `/`, then Fift interprets it as a fractional literal and represents it by two _Integer_'s `p` and `q` in the stack, the numerator `p` and the denominator `q`. For instance, `-17/12` pushes `−17` and `12` into the Fift stack (being thus equivalent to `-17 12`), and `-0x11/0b1100` does the same thing. Decimal, binary, and hexadecimal fractions, such as `2.39` or `-0x11.ef`, are also represented by two integers `p` and `q`, where `q` is a suitable power of the base (10, 2, or 16, respectively). For instance, `2.39` is equivalent to `239 100`, and `-0x11.ef` is equivalent to `-0x11ef 0x100`.\n\nSuch a representation of fractions is especially convenient for using them with the scaling primitive */ and its variants, thus converting common and decimal fractions into a suitable fixed-point representation. For instance, if we want to represent fractional amounts of Grams by integer amounts of nanotons, we can define some helper words:\n\n```fift\n1000000000 constant Gram\n{ Gram * } : Gram*\n{ Gram swap */r } : Gram*/\n```\n\nand then write `2.39 Gram*/` or `17/12 Gram*/` instead of integer literals `2390000000` or `1416666667`.\n\nIf one needs to use such Gram literals often, one can introduce a new active prefix word `GR$` as follows:\n\n```fift\n{ bl word (number) ?dup 0= abort\"not a valid Gram amount\"\n  1- { Gram swap */r } { Gram * } cond\n  1 'nop\n} ::_ GR$\n```\n\nmakes `GR$3`, `GR$2.39`, and `GR$17/12` equivalent to integer literals `3000000000`, `2390000000`, and `1416666667`, respectively. Such values can be printed in similar form by means of the following words:\n\n```fift\n{ dup abs <# ' # 9 times char . hold #s rot sign #>\n  nip -trailing0 } : (.GR)\n{ (.GR) .\"GR$\" type space } : .GR\n-17239000000 .GR\n```\n\nproduces `GR$-17.239 ok`. The above definitions make use of tricks explained in later portions of this document (especially Chapter 4).\n\nWe can also manipulate fractions by themselves by defining suitable _\"rational arithmetic words\"_:\n\n```fift\n// a b c d -- (a*d-b*c) b*d\n{ -rot over * 2swap tuck * rot - -rot * } : R-\n// a b c d -- a*c b*d\n{ rot * -rot * swap } : R*\n// a b --\n{ swap ._ .\"/\" . } : R.\n1.7 2/3 R- R.\n```\n\nwill output `\"31/30 ok\"`, indicating that `1.7 − 2/3 = 31/30`. Here `\"._\"` is a variant of `\".\"` that does not print a space after the decimal representation of an _Integer_.\n\n### 2.9 String literals\n\n_String_ literals are introduced by means of the prefix word `\"`, which scans the remainder of the line until the next `\"` character, and pushes the string thus obtained into the stack as a value of type _String_. For instance, \"Hello, world!\" pushes the corresponding _String_ into the stack:\n\n```fift\n\"Hello, world!\" .s\n```\n\n### 2.10 Simple string manipulation\n\nThe following words can be used to manipulate strings:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`\"<string>\"`** | _`( – S)`_ | pushes a _String_ literal into the stack.\n| **`.\"<string>\"`** | _`( – )`_ | prints a constant string into the standard output.\n| **`type`** | _`(S – )`_ | prints a _String_ `S` taken from the top of the stack into the standard output.\n| **`cr`** | _`( – )`_ | outputs a carriage return (or a newline character) into the standard output.\n| **`emit`** | _`(x – )`_ | prints a UTF-8 encoded character with Unicode codepoint given by _Integer_ `x` into the standard output.\n| **`char <string>`** | _`( – x)`_ | pushes an _Integer_ with the Unicode codepoint of the first character of `<string>`.\n| **`bl`** | _`( – x)`_ | pushes the Unicode codepoint of a space, i.e., 32.\n| **`space`** | _`( – )`_ | prints one space, equivalent to `bl emit`.\n| **`$+`** | _`(S S' – S+S')`_ | concatenates two strings.\n| **`$len`** | _`(S – x)`_ | computes the byte length (not the UTF-8 character length!) of a string.\n| **`+\"<string>\"`** | _`(S – S')`_ | concatenates _String_ `S` with a string literal. Equivalent to `\"string\" $+`.\n| **`word`** | _`(x – S)`_ | parses a word delimited by the character with the Unicode codepoint `x` from the remainder of the current input line and pushes the result as a _String_. For instance, `bl word abracadabra` type will print the string `\"abracadabra\"`. If $x = 0$, skips leading spaces, and then scans until the end of the current input line. If $x = 32$, skips leading spaces before parsing the next word.\n| **`(.)`** | _`(x – S)`_ | returns the _String_ with the decimal representation of _Integer_ `x`.\n| **`(number)`** | _`(S – 0 or x 1 or x y 2)`_ | attempts to parse the _String_ `S` as an integer or fractional literal as explained in 2.8.\n\nFor instance, .\"*\", \"*\" type, 42 emit, and char * emit are four different ways to output a single asterisk.\n\n### 2.11 Boolean expressions, or flags\n\nFift does not have a separate value type for representing boolean values. Instead, any non-zero _Integer_ can be used to represent truth (with `−1` being the standard representation), while a zero _Integer_ represents falsehood. Comparison primitives normally return `−1` to indicate success and `0` otherwise.\n\nConstants `true` and `false` can be used to push these special integers into the stack:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`true`** | _`( – −1)`_ | pushes −1 into the stack.\n| **`false`** | _`( – 0)`_ | pushes 0 into the stack.\n| **`0<>`** | _`(x – x != 0)`_ | pushes −1 if _Integer_ `x` is non-zero, 0 otherwise.\n\nIf boolean values are standard (either 0 or −1), they can be manipulated by means of bitwise logical operations and, or, xor, not. Otherwise, they must first be reduced to the standard form using `0<>`:\n\n### 2.12 Integer comparison operations\n\nSeveral integer comparison operations can be used to obtain boolean values:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`<`** | _`(x y – ?)`_ | checks whether `x < y` (i.e., pushes `−1` if `x < y`, `0` otherwise).\n| **`>, =, <>, <=, >=`** | _`(x y – ?)`_ | compare `x` and `y` and push `−1` or `0` depending on the result of the comparison.\n| **`0<`** | _`(x – ?)`_ | checks whether `x < 0` (i.e., pushes `−1` if `x` is negative, `0` otherwise). Equivalent to `0 <`.\n| **`0>, 0=, 0<>, 0<=, 0>=`** | _`(x – ?)`_ | compare `x` against zero.\n| **`cmp`** | _`(x y – z)`_ | pushes `1` if `x > y`, `−1` if `x < y`, and `0` if `x = y`.\n| **`sgn`** | _`(x – y)`_ | pushes `1` if `x > 0`, `−1` if `x < 0`, and `0 `if `x = 0`. Equivalent to `0 cmp`.\n\nExample:\n\n```fift\n2 3 < .\n```\n\nprints `\"-1 ok\"`, because `2` is less than `3`.\n\nA more convoluted example:\n\n```fift\n{ \"true \" \"false \" rot 0= 1+ pick type 2drop } : ?.\n2 3 < ?. 2 3 = ?. 2 3 > ?.\n```\n\nprints `\"true false false ok\"`.\n\n### 2.13 String comparison operations\n\nStrings can be lexicographically compared by means of the following words:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`$=`** | _`(S S' – ?)`_ | returns `−1` if strings `S` and `S'` are equal, `0` otherwise.\n| **`$cmp`** | _`(S S' – x)`_ | returns `0` if strings `S` and `S'` are equal, `−1` if `S` is lexicographically less than `S'`, and `1` if `S` is lexicographically greater than `S'`.\n\n### 2.14 Named and unnamed variables\n\nIn addition to constants introduced in 2.7, Fift supports variables, which are a more efficient way to represent changeable values. For instance, the last two code fragments of 2.7 could have been written with the aid of variables instead of constants as follows:\n\n```fift\nvariable x variable y\n{ dup x ! dup * y ! } : setxy\n3 setxy x @ . y @ . x @ y @ + .\n7 setxy x @ . y @ . x @ y @ + .\n{ .\"( \" x @ . .\", \" y @ . .\") \" } : showxy\n3 setxy showxy\n```\n\nproducing the same output as before:\n\n```fift\n3 9 12 ok\n7 49 56 ok\n( 3 , 9 ) ok\n```\n\nThe phrase variable `x` creates a new _Box_, i.e., a memory location that can be used to store exactly one value of any Fift-supported type, and defines `x` as a constant equal to this _Box_:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`variable`** | _`( – )`_ | scans a blank-delimited word name `S` from the remainder of the input, allocates an empty _Box_, and defines a new ordinary word `S` as a constant, which will push the new _Box_ when invoked. Equivalent to `hole constant`.\n| **`hole`** | _`( – p)`_ | creates a new _Box_ `p` that does not hold any value. Equivalent to `null box`.\n| **`box`** | _`(x – p)`_ | creates a new _Box_ containing specified value x. Equivalent to `hole tuck !`.\n\nThe value currently stored in a _Box_ may be fetched by means of word `@` (pronounced \"fetch\"), and modified by means of word `!` (pronounced \"store\"):\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`@`** | _`(p – x)`_ | fetches the value currently stored in _Box_ `p`.\n| **`!`** | _`(x p – )`_ | stores new value `x` into _Box_ `p`.\n\nSeveral auxiliary words exist that can modify the current value in a more sophisticated fashion:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`+!`** | _`(x p – )`_ | increases the integer value stored in _Box_ `p` by _Integer_ `x`. Equivalent to `tuck @ + swap !`.\n| **`1+!`** | _`(p – )`_ | increases the integer value stored in _Box_ `p` by one. Equivalent to `1 swap +!`.\n| **`0!`** | _`(p – )`_ | stores _Integer_ 0 into _Box_ `p`. Equivalent to `0 swap !`.\n\nIn this way we can implement a simple counter:\n\n```fift\nvariable counter\n{ counter 0! } : reset-counter\n{ counter @ 1+ dup counter ! } : next-counter\nreset-counter next-counter . next-counter . next-counter .\nreset-counter next-counter .\n```\n\nproduces\n\n```fift\n1 2 3 ok\n1 ok\n```\n\nAfter these definitions are in place, we can even forget the definition of `counter` by means of the phrase `forget counter`. Then the only way to access the value of this variable is by means of `reset-counter` and `next-counter`.\nVariables are usually created by `variable` with no value, or rather with a _Null_ value. If one wishes to create initialized variables, one can use the phrase `box constant`:\n\n```fift\n17 box constant x\nx 1+! x @ .\n```\n\nprints `\"18 ok\"`. One can even define a special defining word for initialized variables, if they are needed often:\n\n```fift\n{ box constant } : init-variable\n17 init-variable x\n\"test\" init-variable y\nx 1+! x @ . y @ type\n```\n\nprints `\"18 test ok\"`.\n\nThe variables have so far only one disadvantage compared to the constants: one has to access their current values by means of an auxiliary word @. Of course, one can mitigate this by defining a \"getter\" and a \"setter\" word for a variable, and use these words to write better-looking code:\n\n```fift\nvariable x-box\n{ x-box @ } : x\n{ x-box ! } : x!\n{ x x * 5 x * + 6 + } : f(x)\n{ .\"( \" x . .\", \" f(x) . .\") \" } : .xy\n3 x! .xy 5 x! .xy\n```\n\nprints `\"( 3 , 30 ) ( 5 , 56 ) ok\"`, which are the points `(x, f(x))` on the graph of `f(x) = x 2 + 5x + 6` with `x = 3` and `x = 5`.\n\nAgain, if we want to define \"getters\" for all our variables, we can first define a defining word as explained in 4.8, and use this word to define both a getter and a setter at the same time:\n\n```fift\n{ hole dup 1 ' @ does create 1 ' ! does create } : variable-set\nvariable-set x x!\nvariable-set y y!\n{ .\"x=\" x . .\"y=\" y . .\"x*y=\" x y * . cr } : show\n{ y 1+ y! } : up\n{ x 1+ x! } : right\n{ x y x! y! } : reflect\n2 x! 5 y!\n```\n\nshow up show right show up show reflect show produces\n\n```fift\nx=2 y=5 x*y=10\nx=2 y=6 x*y=12\nx=3 y=6 x*y=18\nx=3 y=7 x*y=21\nx=7 y=3 x*y=21\n```\n\n### 2.15 Tuples and arrays\n\nFift also supports _Tuples_, i.e., immutable ordered collections of arbitrary values of stack value types. When a _Tuple_ `t` consists of values `x1, ..., xn` (in that order), we write `t = (x1, ... , xn)`. The number `n` is called the length of _Tuple_ `t`; it is also denoted by `|t|`. Tuples of length two are also called _pairs_, tuples of length three are _triples_.\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`tuple`** | _`(x1 ... xn n – t)`_ | creates new _Tuple_ `t := (x1, ..., xn)` from `n ≥ 0` topmost stack values.\n| **`pair`** | _`(x y – t)`_ | creates new pair `t = (x, y)`. Equivalent to `2 tuple`.\n| **`triple`** | _`(x y z – t)`_ | creates new triple `t = (x, y, z)`. Equivalent to `3 tuple`.\n| **`\\|`** | _`( – t)`_ | creates an empty _Tuple_ `t = ()`. Equivalent to `0 tuple`.\n| **`,`** | _`(t x – t')`_ | appends `x` to the end of _Tuple_ `t`, and returns the resulting _Tuple_ `t'`.\n| **`.dump`** | _`(x – )`_ | dumps the topmost stack entry in the same way as `.s` dumps all stack elements.\n\nFor instance, both\n\n```fift\n| 2 , 3 , 9 , .dump\n```\n\nand\n\n```fift\n2 3 9 triple .dump\n```\n\nconstruct and print triple (2, 3, 9):\n\n```fift\n[ 2 3 9 ] ok\n```\n\nNotice that the components of a _Tuple_ are not necessarily of the same type, and that a component of a _Tuple_ can also be a _Tuple_:\n\n```fift\n1 2 3 triple 4 5 6 triple 7 8 9 triple triple constant Matrix\nMatrix .dump cr\n| 1 \"one\" pair , 2 \"two\" pair , 3 \"three\" pair , .dump\n```\n\nproduces\n\n```fift\n[ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ]\n[ [ 1 \"one\" ] [ 2 \"two\" ] [ 3 \"three\" ] ] ok\n```\n\nOnce a _Tuple_ has been constructed, we can extract any of its components, or completely unpack the _Tuple_ into the stack:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`untuple`** | _`(t n – x1 ... xn)`_ | returns all components of a _Tuple_ `t = (x1, ... , xn)`, but only if its length is equal to `n`. Otherwise throws an exception.\n| **`unpair`** | _`(t – x y)`_ | unpacks a pair `t = (x, y)`. Equivalent to `2 untuple`.\n| **`untriple`** | _`(t – x y z)`_ | unpacks a triple `t = (x, y, z)`. Equivalent to `3 untuple`.\n| **`explode`** | _`(t – x1 ... xn n)`_ | unpacks a _Tuple_ `t = (x1, ... , xn)` of unknown length `n`, and returns that length.\n| **`count`** | _`(t – n)`_ | returns the length `n = |t|` of _Tuple_ `t`.\n| **`tuple?`** | _`(t – ?)`_ | checks whether `t` is a _Tuple_, and returns `−1` or `0` accordingly.\n| **`[]`** | _`(t i – x)`_ | returns the `(i + 1)-st` component `ti+1` of _Tuple_ `t`, where `0 ≤ i < \\|t\\|`.\n| **`first`** | _`(t – x)`_ | returns the first component of `a` _Tuple_. Equivalent to `0 []`.\n| **`second`** | _`(t – x)`_ | returns the second component of `a` _Tuple_. Equivalent to `1 []`.\n| **`third`** | _`(t – x)`_ | returns the third component of `a` _Tuple_. Equivalent to `2 []`.\n\nFor instance, we can access individual elements and rows of a matrix:\n\n```fift\n1 2 3 triple 4 5 6 triple 7 8 9 triple triple constant Matrix\nMatrix .dump cr\nMatrix 1 [] 2 [] . cr\nMatrix third .dump cr\n```\n\nproduces\n\n```fift\n[ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ]\n6\n[ 7 8 9 ]\n```\n\nNotice that _Tuples_ are somewhat similar to arrays of other programming languages, but are immutable: we cannot change one individual component of a _Tuple_. If we still want to create something like an array, we need a _Tuple_ of _Box_'es:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`allot`** | _`(n – t)`_ | creates a _Tuple_ that consists of `n` new empty _Box_'es. Equivalent to `\\| { hole , } rot times`.\n\nFor instance,\n\n```fift\n10 allot constant A\n| 3 box , 1 box , 4 box , 1 box , 5 box , 9 box , constant B\n{ over @ over @ swap rot ! swap ! } : swap-values-of\n{ B swap [] } : B[]\n{ B[] swap B[] swap-values-of } : swap-B\n{ B[] @ . } : .B[]\n0 1 swap-B 1 3 swap-B 0 2 swap-B\n0 .B[] 1 .B[] 2 .B[] 3 .B[]\n```\n\ncreates an uninitialized array `A` of length `10`, an initialized array `B` of length `6`, and then interchanges some elements of `B` and prints the first four elements of the resulting `B`:\n\n```fift\n4 1 1 3 ok\n```\n\n### 2.16 Lists\n\nLisp-style lists can also be represented in Fift. First of all, two special words are introduced to manipulate values of type _Null_, used to represent the empty list (not to be confused with the empty _Tuple_):\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`null`** | _`( – ⊥)`_ | pushes the only value `⊥` of type _Null_, which is also used to represent an empty list.\n| **`null?`** | _`(x – ?)`_ | checks whether `x` is a _Null_. Can also be used to check whether a list is empty.\n\nAfter that, `cons` and `uncons` are defined as aliases for `pair` and `unpair`:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`cons`** | _`(h t – l)`_ | constructs a list `l` from its head (first element) `h` and its tail (the list consisting of all remaining elements) `t`. Equivalent to `pair`.\n| **`uncons`** | _`(l – h t)`_ | decomposes a non-empty list into its head and its tail. Equivalent to `unpair`.\n| **`car`** | _`(l – h)`_ | returns the head of a list. Equivalent to `first`.\n| **`cdr`** | _`(l – t)`_ | returns the tail of a list. Equivalent to `second`.\n| **`cadr`** | _`(l – h' )`_ | returns the second element of a list. Equivalent to `cdr car`.\n| **`list`** | _`(x1 ... xn n – l)`_ | constructs a list `l` of length `n` with elements `x1, ... , xn`, in that order. Equivalent to `null ' cons rot times`.\n| **`.l`** | _`(l – )`_ | prints a Lisp-style list `l`.\n\nFor instance,\n\n```fift\n2 3 9 3 tuple .dump cr\n`2 3 `9 3 list dup .dump space dup .l cr\n\"test\" swap cons .l cr\n```\n\nproduces\n\n```fift\n[ 2 3 9 ]\n[ 2 [ 3 [ 9 (`null`) ] ] ] (2 3 9)\n(\"test\" 2 3 9)\n```\n\nNotice that the three-element` lis`t (2 3 9) is distinct from the triple (2, 3, 9).\n\n### 2.17 Atoms\n\nAn _Atom_ is a simple entity uniquely identified by its name. _Atom_'s can be used to represent identifiers, labels, operation names, tags, and stack markers. Fift offers the following words to manipulate _Atom_'s:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`(atom)`** | _`(S x – a −1 or 0)`_ | returns the only _Atom_ `a` with the name given by _String_ `S`. If there is no such _Atom_ yet, either creates it (if _Integer_ `x` is non-zero) or returns a single zero to indicate failure (if `x` is zero).\n| **`atom`** | _`(S – a)`_ | returns the only _Atom_ `a` with the name `S`, creating such an atom if necessary. Equivalent to `true (atom) drop`.\n| **`'<word>`** | _`( – a)`_ | introduces an _Atom_ literal, equal to the only _Atom_ with the name equal to `\"<word>\"`. Equivalent to `\"<word>\" atom`.\n| **`anon`** | _`( – a)`_ | creates a new unique anonymous _Atom_.\n| **`atom?`** | _`(u – ?)`_ | checks whether `u` is an _Atom_.\n| **`eq?`** | _`(u v – ?)`_ | checks whether `u` and `v` are equal _Integer_ `s`, _Atom_'s, or _Null_'s. If they are not equal, or if they are of different types, or not of one of the types listed, returns zero.\n\nFor instance,\n\n```fift\n'+ 2 '* 3 4 3 list 3 list .l\n```\n\ncreates and prints the list\n\n```fift\n(+ 2 (* 3 4))\n```\n\nwhich is the Lisp-style representation of arithmetical expression `2 + 3 · 4`. An interpreter for such expressions might use `eq?` to check the operation sign:\n\n```fift\nvariable 'eval\n{ 'eval @ execute } : eval\n{ dup tuple? {\n    uncons uncons uncons\n    null? not abort\"three-element list` exp`ected\"\n    swap eval swap eval rot\n    dup '+ eq? { drop + } {\n      dup '- eq? { drop - } {\n        '* eq? not abort\"unknown operation\" *\n      } cond\n    } cond\n  } if\n} 'eval !\n'+ 2 '* 3 4 3 list 3 list dup .l cr eval . cr\n```\n\nprints\n\n```fift\n(+ 2 (* 3 4))\n14\n```\n\nIf we load `Lisp.fif` to enable Lisp-style list syntax, we can enter\n\n```fift\n\"Lisp.fif\" include\n( '+ 2 ( '* 3 4 ) ) dup .l cr eval . cr\n```\n\nwith the same result as before. The word `(`, defined in `Lisp.fif`, uses an anonymous _Atom_ created by `anon` to mark the current stack position, and then ) builds a list from several top stack entries, scanning the stack until the anonymous _Atom_ marker is found:\n\n```fift\nvariable ')\n{ \") without (\" abort } ') !\n{ ') @ execute } : )\n{ null { -rot 2dup eq? not } { swap rot cons } while 2drop\n} : list-until-marker\n{ anon dup ') @ 2 { ') ! list-until-marker } does ') ! } : (\n```\n\n### 2.18 Command line arguments in script mode\n\nThe Fift interpreter can be invoked in script mode by passing `-s` as a command line option. In this mode, all further command line arguments are not scanned for Fift startup command line options. Rather, the next argument after `-s` is used as the filename of the Fift source file, and all further command line arguments are passed to the Fift program by means of special words `$n` and `$#`:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`$#`** | _`( – x)`_ | pushes the total number of command-line arguments passed to the Fift program.\n| **`$n`** | _`( – S)`_ | pushes the n-th command-line argument as a _String_ `S`. For instance, `$0` pushes the name of the script being executed, `$1` the first command line argument, and so on.\n| **`$()`** | _`(x – S)`_ | pushes the x-th command-line argument similarly to `$n`, but with _Integer_ `x` taken from the stack.\n\nAdditionally, if the very first line of a Fift source file begins with the two characters `\"#!\"`, this line is ignored. In this way simple Fift scripts can be written in a *ix system. For instance, if\n\n```fift\n#!/usr/bin/fift -s\n{ .\"usage: \" $0 type .\"  \" cr\n  .\"Computes the product of two integers.\" cr 1 halt } : usage\n{ ' usage if } : ?usage\n$# 2 <> ?usage\n$1 (number) 1- ?usage\n$2 (number)` 1- `?usage\n* . cr\n```\n\nis saved into a file `cmd`line`.fif` in the current directory, and its execution bit is set (e.g., by `chmod 755 cmdline.fif`), then it can be invoked from the shell or any other program, provided the Fift interpreter is installed as `/usr/bin/fift`, and its standard library `Fift.fif` is installed as `/usr/lib/fift/Fift.fif`:\n\n```shell\n./cmdline.fif 12 -5\n```\n\nprints\n\n```shell\n-60\n```\n\nwhen invoked from a *ix shell such as the Bourne–again shell (Bash).\n\n## 3 Blocks, loops, and conditionals\n\nSimilarly to the arithmetic operations, the execution flow in Fift is controlled by stack-based primitives. This leads to an inversion typical of reverse Polish notation and stack-based arithmetic: one first pushes a block representing a conditional branch or the body of a loop into the stack, and then invokes a conditional or iterated execution primitive. In this respect, Fift is more similar to PostScript than to Forth.\n\n### 3.1 Defining and executing blocks\n\nA block is normally defined using the special words `{` and `}`. Roughly speaking, all words listed between `{` and `}` constitute the body of a new block, which is pushed into the stack as a value of type _WordDef_. A block may be stored as a definition of a new Fift word by means of the defining word `:` as explained in 2.6, or executed by means of the word execute:\n\n```fift\n17 { 2 * } execute .\n```\n\nprints `\"34 ok\"`, being essentially equivalent to `\"17 2 * .\"`. A slightly more convoluted example:\n\n```fift\n{ 2 * } 17 over execute swap execute .\n```\n\napplies \"anonymous function\" `x → 2x` twice to `17`, and prints the result `2 · (2 · 17) = 68`. In this way a block is an execution token, which can be duplicated, stored into a constant, used to define a new word, or executed.\n\nThe word `'` recovers the current definition of a word. Namely, the construct `' <word-name>` pushes the execution token equivalent to the current definition of the word `<word-name>`. For instance,\n\n```fift\n' dup execute\n```\n\nis equivalent to `dup`, and\n\n```fift\n' dup : duplicate\n```\n\ndefines duplicate as a synonym for (the current definition of) `dup`.\n\nAlternatively, we can duplicate a block to define two new words with the same definition:\n\n```fift\n{ dup * }\ndup : square : **2\n```\n\ndefines both square and `**2` to be equivalent to `dup *`.\n\n### 3.2 Conditional execution of blocks\n\nConditional execution of blocks is achieved using the words `if`, `ifnot`, and `cond`:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`if`** | _`(x e – )`_ | executes `e` (which must be an execution token, i.e., a _WordDef_),^5 but only if _Integer_ `x` is non-zero.\n| **`ifnot`** | _`(x e – )`_ | executes execution token `e`, but only if _Integer_ `x` is zero.\n| **`cond`** | _`(x e e' – )`_ | if _Integer_ `x` is non-zero, executes `e`, otherwise executes `e'`.\n\nFor instance, the last example in 2.12 can be more conveniently rewritten as\n\n```fift\n{ { .\"true \" } { .\"false \" } cond } : ?.\n2 3 < ?. 2 3 = ?. 2 3 > ?.\n```\n\nstill resulting in `\"true false false ok\"`.\n\nNotice that blocks can be arbitrarily nested, as already shown in the previous example. One can write, for example,\n\n```fift\n{ ?dup\n  { 0<\n    { .\"negative \" }\n    { .\"positive \" }\n    cond\n  }\n  { .\"zero \" }\n  cond\n} : chksign\n-17 chksign\n```\n\nto obtain `\"negative ok\"`, because `−17` is negative.\n\n<Aside>\n\n  A _WordDef_ is more general than a _WordList_. For instance, the definition of the primitive `+` is a _WordDef_, but not a _WordList_, because `+` is not defined in terms of other Fift words.\n\n</Aside>\n\n### 3.3 Simple loops\n\nThe simplest loops are implemented by times:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`times`** | _`(e n – )`_ | executes `e` exactly `n` times, if `n ≥ 0`. If `n` is negative, throws an exception.\n\nFor instance,\n\n```fift\n1 { 10 * } 70 times .\n```\n\ncomputes and prints `10^70`.\n\nWe can use this kind of loop to implement a simple factorial function:\n\n```fift\n{ 0 1 rot { swap 1+ tuck * } swap times nip } : fact\n5 fact .\n```\n\nprints `\"120 ok\"`, because `5! = 1 · 2 · 3 · 4 · 5 = 120`.\n\nThis loop can be modified to compute Fibonacci numbers instead:\n\n```fift\n{ 0 1 rot { tuck + } swap times nip } : fibo\n6 fibo .\n```\n\ncomputes the sixth Fibonacci number F6 = 13.\n\n### 3.4 Loops with an exit condition\n\nMore sophisticated loops can be created with the aid of `until` and `while`:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`until`** | _`(e – )`_ | executes `e`, then removes the top-of-stack integer and checks whether it is zero. If it is, then begins a new iteration of the loop by executing `e`. Otherwise exits the loop.\n| **`while`** | _`(e e' – )`_ | executes `e`, then removes and checks the top-of-stack integer. If it is zero, exits the loop. Otherwise executes `e'` , then begins a new loop iteration by executing `e` and checking the exit condition afterwards.\n\nFor instance, we can compute the first two Fibonacci numbers greater than 1000:\n\n```fift\n{ 1 0 rot { -rot over + swap rot 2dup >= } until drop } : fib-gtr\n1000 fib-gtr . .\n```\n\nprints `\"1597 2584 ok\"`.\n\nWe can use this word to compute the first 70 decimal digits of the golden ratio `φ = (1 + √5) / 2 ≈ 1.61803`:\n\n```fift\n1 { 10 * } 70 times dup fib-gtr */ .\n```\n\nprints `\"161803 ... 2604 ok\"`.\n\n### 3.5 Recursion\n\nNotice that, whenever a word is mentioned inside a `{...}` block, the current (compile-time) definition is included in the _WordList_ being created. In this way we can refer to the previous definition of a word while defining a new version of it:\n\n```fift\n{ + . } : print-sum\n{ .\"number \" . } : .\n{ 1+ . } : print-next\n2 . 3 . 2 3 print-sum 7 print-next\n```\n\nproduces `\"number 2 number 3 5 number 8 ok\"`. Notice that `print-sum` continues to use the original definition of `\".\"`, but `print-next` already uses the modified `\".\"`.\n\nThis feature may be convenient on some occasions, but it prevents us from introducing recursive definitions in the most straightforward fashion. For instance, the classical recursive definition of the factorial\n\n```fift\n{ ?dup { dup 1- fact * } { 1 } cond } : fact\n```\n\nwill fail to compile, because `fact` happens to be an undefined word when the definition is compiled.\n\nA simple way around this obstacle is to use the word `@'` that looks up the current definition of the next word during the execution time and then executes it, similarly to what we already did before:\n\n```fift\n{ ?dup { dup 1- @' fact * } { 1` } cond } : fact\n5 fact .\n```\n\nproduces `\"120 ok\"`, as expected.\n\nHowever, this solution is rather inefficient, because it uses a dictionary lookup each time fact is recursively executed. We can avoid this dictionary lookup by using variables:\n\n```fift\nvariable 'fact\n{ 'fact @ execute } : fact\n{ ?dup { dup 1- fact * } { 1 } cond } '`fact '!\n5 fact '.\n```\n\nThis somewhat longer definition of the factorial avoids dictionary lookups at execution time by introducing a special variable `'fact` to hold the final definition of the factorial. Then, `fact` is defined to execute whatever _WordDef_ is currently stored in `'fact`, and once the body of the recursive definition of the factorial is constructed, it is stored into this variable by means of the phrase `'fact !`, which replaces the more customary phrase `: fact`.\n\n<Aside>\n\n  Variables that hold a _WordDef_ to be executed later are called _vector variables_. The process of replacing `fact` with `'fact @ execute`, where `'fact` is a vector variable, is _called vectorization_.\n\n</Aside>\n\nWe could rewrite the above definition by using special \"getter\" and \"setter\" words for vector variable 'fact as we did for variables in 2.14:\n\n```fift\nvariable 'fact\n{ 'fact @ execute } : fact\n{ 'fact ! } : :fac't\nforget 'fact\n{ ?du'p { dup 1- fact '* } { 1 } cond } :fact\n5 fact .\n```\n\nIf we need to introduce a lot of recursive and mutually-recursive definitions, we might first introduce a custom defining word for simultaneously defining both the \"getter\" and the \"setter\" words for anonymous vector variables, similarly to what we did before:\n\n```fift\n{ hole dup 1 { @ execute } does create 1 ' ! does create } : vector-set\nvector-set fact :fact\n{ ?dup { dup 1- fact * } { 1 } cond } :fact\n5 fact .\n```\n\nThe first three lines of this fragment define `fact` and `:fact` essentially in the same way they had been defined in the first four lines of the previous fragment.\n\nIf we wish to make `fact` unchangeable in the future, we can add a forget `:fact` line once the definition of the factorial is complete:\n\n```fift\n{ hole dup 1 { @ execute } does create 1 ' ! does create } : vector-set\nvector-set fact :fact\n{ ?dup { dup 1- fact * } { 1 } cond } :fact\nforget :fact\n5 fact .\n```\n\nAlternatively, we can modify the definition of `vector-set` in such a way that `:fact` would forget itself once it is invoked:\n\n```fift\n{ hole dup 1 { @ execute } does create\n  bl word tuck 2 { (forget) ! } does swap 0 (create)\n} : vector-set-once\nvector-set`-onc`e fact :fact\n{ ?dup { dup 1- fact * } { 1 } cond } :fact\n5 fact .\n```\n\nHowever, some vector variables must be modified more than once, for instance, to modify the behavior of the comparison word less in a merge sort algorithm:\n\n```fift\n{ hole dup 1 { @ execute } does create 1 ' ! does create } : vector-set\nvector-set sort :sort\nvector-set merge :merge\nvector-set less :less\n{ null null rot\n  { dup null? not }\n  { uncons swap rot cons -rot } while drop\n} : split\n{ dup null? { drop } {\n    over null? { nip } {\n      over car over car less ' swa'p if\n      uncons rot merge cons\n    } cond\n  } cond\n} :merge\n{ dup null? {\n    dup cdr null? {\n      split sort swap sort merge\n    } ifnot\n  } ifnot\n} :sort\nforget :merge\nforget :sort\n// set 'less' to compare numbers, sort a list of numbers\n' < :less\n3 1 4 1 5 9 2 6 5 9 list\ndup .l cr sort .l cr\n// set 'less' to compare strings, sort a list of strings\n{ $cmp 0< } :less\n\"once\" \"upon\" \"a\" \"time\" \"there\" \"lived\" \"a\" \"kitten\" 8 list\ndup .l cr sort .l cr\n```\n\nproducing the following output:\n\n```fift\n(3 1 4 1 5 9 2 6 5)\n(1 1 2 3 4 5 5 6 9)\n(\"once\" \"upon\" \"a\" \"time\" \"there\" \"lived\" \"a\" \"kitten\")\n(\"a\" \"a\" \"kitten\" \"live'd\" \"once\" \"there\" \"time\" \"upon\")\n```\n\n### 3.6 Throwing exceptions\n\nTwo built-in words are used to throw exceptions:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`abort`** | _`(S – )`_ | throws an exception with an error message taken from _String_ `S`.\n| **`abort\"<message>\"`** | _`(x – )`_ | throws an exception with the error message `\"<message>\"` if the _Integer_ `x` is non-zero.\n\nThe exception thrown by these words is represented by the C++ exception `fift::IntError` with its value equal to the specified string. It is normally handled within the Fift interpreter itself by aborting all execution up to the top level and printing a message with the name of the source file being interpreted, the line number, the currently interpreted word, and the specified error message. For instance:\n\n```fift\n{ dup 0= abort\"Division by zero\" / } : safe/\n5 0 safe/ .\n```\n\nprints `\"safe/: Division by zero\"`, without the usual `\"ok\"`. The stack is cleared in the process.\n\nIncidentally, when the Fift interpreter encounters an unknown word that cannot be parsed as an integer literal, an exception with the message `\"-?\"` is thrown, with the effect indicated above, including the stack being cleared.\n\n## 4 Dictionary, interpreter, and compiler\n\nIn this chapter we present several specific Fift word's for dictionary manipulation and compiler control. The \"compiler\" is the part of the Fift interpreter that builds lists of word references (represented by _WordList_ stack values) from word names; it is activated by the primitive `{` employed for defining blocks as explained in 2.6 and 3.1.\n\nMost of the information included in this chapter is rather sophisticated and may be skipped during a first reading. However, the techniques described here are heavily employed by the Fift assembler, used to compile TVM code. Therefore, this section is indispensable if one wishes to understand the current implementation of the Fift assembler.\n\n### 4.1 The state of the Fift interpreter\n\nThe state of the Fift interpreter is controlled by an internal integer variable called `state`, currently unavailable from Fift itself. When `state` is zero, all words parsed from the input (i.e., the Fift source file or the standard input in the interactive mode) are looked up in the dictionary and immediately executed afterwards. When `state` is positive, the words found in the dictionary are not executed. Instead, they (or rather the references to their current definitions) are compiled, i.e., added to the end of the _WordList_ being constructed.\n\nTypically, `state` equals the number of the currently open blocks. For instance, after interpreting `{ 0= { .\"zero\"` the `state` variable will be equal to two, because there are two nested blocks. The _WordList_ being constructed is kept at the top of the stack.\n\nThe primitive `{` simply pushes a new empty _WordList_ into the stack, and increases `state` by one. The primitive `}` throws an exception if `state` is already zero; otherwise it decreases `state` by one, and leaves the resulting _WordList_ in the stack, representing the block just constructed. After that, if the resulting value of `state` is non-zero, the new block is compiled as a literal (unnamed constant) into the encompassing block.\n\n<Aside>\n\n  The word `}` also transforms this _WordList_ into a _WordDef_, which has a different type tag and therefore is a different Fift value, even if the same underlying C++ object is used by the C++ implementation.\n\n</Aside>\n\n### 4.2 Active and ordinary words\n\nAll dictionary words have a special flag indicating whether they are active words or ordinary words. By default, all words are ordinary. In particular, all words defined with the aid of `\":\"` and constant are ordinary.\n\nWhen the Fift interpreter finds a word definition in the dictionary, it checks whether it is an ordinary word. If it is, then the current word definition is either executed (if `state` is zero) or \"compiled\" (if `state` is greater than zero) as explained in 4.1.\n\nOn the other hand, if the word is active, then it is always executed, even if `state` is positive. An active word is expected to leave some values `x1 ... xn n e` in the stack, where `n ≥ 0` is an integer, `x1 ... xn` are `n` values of arbitrary types, and `e` is an execution token (a value of type _WordDef_). After that, the interpreter performs different actions depending on `state`: if `state` is zero, then `n` is discarded and `e` is executed, as if a `nip execute` phrase were found. If `state` is non-zero, then this collection is \"compiled\" in the current _WordList_ (located immediately below `x1` in the stack) in the same way as if the `(compile)` primitive were invoked. This compilation amounts to adding some code to the end of the current _WordList_ that would push `x1, ... , xn` into the stack when invoked, and then adding a reference to `e`, representing a delayed execution of `e`. If `e` is equal to the special value `'nop`, representing an execution token that does nothing when executed, then this last step is omitted.\n\n### 4.3 Compiling literals\n\nWhen the Fift interpreter encounters a word that is absent from the dictionary, it invokes the primitive (number) to attempt to parse it as an integer or fractional literal. If this attempt succeeds, then the special value `'nop` is pushed, and the interpretation proceeds in the same way as if an active word were encountered. In other words, if state is zero, then the literal is simply left in the stack; otherwise, (compile) is invoked to modify the current _WordList_ so that it would push the literal when executed.\n\n### 5.4 Defining new active words\n\nNew active words are defined similarly to new ordinary words, but using `::` instead of `:`. For instance,\n\n```fift\n{ bl word 1 ' type } :: say\n```\n\ndefines the active word `say`, which scans the next blank-separated word after itself and compiles it as a literal along with a reference to the current definition of type into the current _WordList_ (if state is non-zero, i.e., if the Fift interpreter is compiling a block). When invoked, this addition to the block will push the stored string into the stack and execute type, thus printing the next word after say. On the other hand, if state is zero, then these two actions are performed by the Fift interpreter immediately. In this way,\n\n```fift\n1 2 say hello + .\n```\n\nwill print `\"hello3 ok\"`, while\n\n```fift\n{ 2 say hello + . } : test\n1 test 4 test\n```\n\nwill print `\"hello3 hello6 ok\"`.\n\nOf course, a block may be used to represent the required action instead of `' type`. For instance, if we want a version of say that prints a space after the stored word, we can write\n\n```fift\n{ bl word 1 { type space } } :: say\n{ 2 say hello + . } : test\n1 test 4 test\n```\n\nto obtain `\"hello 3 hello 6 ok\"`.\n\nIncidentally, the words `\"` (introducing a string literal) and `.\"` (printing a string literal) can be defined as follows:\n\n```fift\n{ char \" word 1 'nop } ::_ \"\n{ char \" word 1 ' type } ::_ .\"\n```\n\nThe new defining word `\"::_\"` defines an active prefix word, i.e., an active word that does not require a space afterwards.\n\n### 4.5 Defining words and dictionary manipulation\n\n_Defining words_ are words that define new words in the Fift dictionary. For instance, `:`, `::_`, and `constant` are defining words. All of these defining words might have been defined using the primitive `(create)`; in fact, the user can introduce custom defining words if so desired. Let us list some defining words and dictionary manipulation words:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`create <word-name>`** | _`(e – )`_ | defines a new ordinary word with the name equal to the next word scanned from the input, using _WordDef_ `e` as its definition. If the word already exists, it is tacitly redefined.\n| **`(create)`** | _`(e S x – )`_ | creates a new word with the name equal to _String_ `S` and definition equal to _WordDef_ e, using flags passed in _Integer_ $0 ≤ x ≤ 3$. If bit +1 is set in `x`, creates an active word; if bit +2 is set in `x`, creates a prefix word.\n| **`: <word-name>`** | _`(e – )`_ | defines a new ordinary word `<word-name>` in the dictionary using _WordDef_ `e` as its definition. If the specified word is already present in the dictionary, it is tacitly redefined.\n| **`forget <word-name>`** | _`( – )`_ | forgets (removes from the dictionary) the definition of the specified word.\n| **`(forget)`** | _`(S – )`_ | forgets the word with the name specified in _String_ `S`. If the word is not found, throws an exception.\n| **`:_ <word-name>`** | _`(e – )`_ | defines a new ordinary prefix word `<word-name>`, meaning that a blank or an end-of-line character is not required by the Fift input parser after the word name. In all other respects it is similar to `:`.\n| **`:: <word-name>`** | _`(e – )`_ | defines a new active word `<word-name>` in the dictionary using _WordDef_ `e` as its definition. If the specified word is already present in the dictionary, it is tacitly redefined.\n| **`::_ <word-name>`** | _`(e – )`_ | defines a new active prefix word `<word-name>`, meaning that a blank or an end-of-line character is not required by the Fift input parser after the word name. In all other respects it is similar to `::`.\n| **`constant <word-name>`** | _`(x – )`_ | defines a new ordinary word `<word-name>` that would push the given value `x` when invoked.\n| **`2constant <word-name>`** | _`(x y – )`_ | defines a new ordinary word named `<word-name>` that would push the given values `x` and `y` (in that order) when invoked.\n| **`=: <word-name>`** | _`(x – )`_ | defines a new ordinary word `<word-name>` that would push the given value `x` when invoked, similarly to `constant`, but works inside blocks and colon definitions.\n| **`2=: <word-name>`** | _`(x y – )`_ | defines a new ordinary word `<word-name>` that would push the given values `x` and `y` (in that order) when invoked, similarly to `2constant`, but works inside blocks and colon definitions.\n\nNotice that most of the above words might have been defined in terms of `(create)`:\n\n```fift\n{ bl word 1 2 ' (create) } \"::\" 1 (create)\n{ bl word 0 2 ' (create) } :: :\n{ bl word 2 2 ' (create) } :: :_\n{ bl word 3 2 ' (create) } :: ::_\n{ bl word 0 (create) } : create\n{ bl word (forget) } : forget\n```\n\n### 4.6 Dictionary lookup\n\nThe following words can be used to look up words in the dictionary:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`' <word-name>`** | _`( – e)`_ | pushes the definition of the word `<word-name>`, recovered at the compile time. If the indicated word is not found, throws an exception. Notice that `' <word-name>` execute is always equivalent to `<word-name>` for ordinary words, but not for active words.\n| **`nop`** | _`( – )`_ | does nothing.\n| **`'nop`** | _`( – e)`_ | pushes the default definition of `nop` — an execution token that does nothing when executed.\n| **`find`** | _`(S – e −1 or e 1 or 0)`_ | looks up _String_ `S` in the dictionary and returns its definition as a _WordDef_ `e` if found, followed by `−1` for ordinary words or `1` for active words. Otherwise pushes `0`.\n| **`(') <word-name>`** | _`( – e)`_ | similar to `'`, but returns the definition of the specified word at execution time, performing a dictionary lookup each time it is invoked. May be used to recover current values of constants inside word definitions and other blocks by using the phrase `(') <word-name> execute`.\n| **`@' <word-name>`** | _`( – e)`_ | similar to `(')`, but recovers the definition of the specified word at execution time, performing a dictionary lookup each time it is invoked, and then executes this definition. May be used to recover current values of constants inside word definitions and other blocks by using the phrase `@' <word-name>`, equivalent to `(') <word-name> execute`.\n| **`[compile] <word-name>`** | _`( – )`_ | compiles `<word-name>` as if it were an ordinary word, even if it is active. Essentially equivalent to `' <word-name> execute`.\n| **`words`** | _`( – )`_ | prints the names of all words currently defined in the dictionary.\n\n### 4.7 Creating and manipulating word lists\n\nIn the Fift stack, lists of references to word definitions and literals, to be used as blocks or word definitions, are represented by the values of the type _WordList_. Some words for manipulating _WordList_'s include:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`{`** | _`( – l)`_ | an active word that increases internal variable state by one and pushes a new empty _WordList_ into the stack.\n| **`}`** | _`(l – e)`_ | an active word that transforms a _WordList_ `l` into a _WordDef_ (an execution token) `e`, thus making all further modifications of `l` impossible, and decreases internal variable state by one and pushes the integer `1`, followed by a `'nop`. The net effect is to transform the constructed _WordList_ into an execution token and push this execution token into the stack, either immediately or during the execution of an outer block.\n| **`({)`** | _`( – l)`_ | pushes an empty _WordList_ into the stack.\n| **`(})`** | _`(l – e)`_ | transforms a _WordList_ into an execution token, making all further modifications impossible.\n| **`(compile)`** | _`(l x1 ... xn n e – l' )`_ | extends _WordList_ `l` so that it would push `0 ≤ n ≤ 255` values `x1, ... , xn` into the stack and execute the execution token `e` when invoked, where `0 ≤ n ≤ 255` is an _Integer_. If `e` is equal to the special value `'nop`, the last step is omitted.\n| **`does`** | _`(x1 ... xn n e – e' )`_ | creates a new execution token `e'` that would push `n` values `x1, ... , xn` into the stack and then execute `e`. It is roughly equivalent to a combination of `({), (compile), and (})`.\n\n### 4.8 Custom defining words\n\nThe word does is actually defined in terms of simpler words:\n'\n```fift\n{ swap ({) over 2+ -roll swap (compile) (}) } : does\n```\n\nIt is especially useful for defining custom defining words. For instance, `constant` and `2constant` may be defined with the aid of `does` and `create`:\n\n```fift\n{ 1 'nop does create } : constant\n{ 2 'nop does create } : 2constant\n```\n\nOf course, non-trivial actions may be performed by the words defined by means of such custom defining words. For instance,\n\n```fift\n{ 1 { type space } does create } : says\n\"hello\" says hello\n\"unknown error\" says error\n{ hello error } : test\ntest\n```\n\nwill print `\"hello unknown error ok\"`, because `hello` is defined by means of a custom defining word says to print `\"hello\"` whenever invoked, and similarly error prints `\"unknown error\"` when invoked. The above definitions are essentially equivalent to\n\n```fift\n{ .\"hello\" } : hello\n{ .\"unknown error\" } : error\n```\n\nHowever, custom defining words may perform more sophisticated actions when invoked, and process their arguments at compile time. For instance, the message can be computed in a non-trivial fashion:\n\n```fift\n\"Hello, \" \"world!\" $+ says hw\n```\n\ndefines word `hw`, which prints `\"Hello, world!\"` when invoked. The string with this message is computed once at compile time (when `says` is invoked), not at execution time (when `hw` is invoked).\n\n## 5 Cell manipulation\n\nWe have discussed the basic Fift primitives not related to TVM or the TON Blockchain so far. Now we will turn to TON-specific words, used to manipulate Cells.\n\n### 5.1 Slice literals\n\nRecall that a (TVM) _Cell_ consists of at most `1023` data bits and at most four references to other _Cell_'s, a _Slice_ is a read-only view of a portion of a _Cell_, and a _Builder_ is used to create new _Cell_'s. Fift has special provisions for defining _Slice_ literals (i.e., unnamed constants), which can also be transformed into _Cell_'s if necessary.\n\n_Slice_ literals are introduced by means of active prefix words `x{` and `b{`:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`b{<binary-data>}`** | _`( – s)`_ | creates a _Slice_ `s` that contains no references and up to 1023 data bits specified in `<binary-data>`, which must be a string consisting only of the characters '0' and '1'.\n| **`x{<hex-data>}`** | _`( – s)`_ | creates a _Slice_ `s` that contains no references and up to 1023 data bits specified in `<hex-data>`. More precisely, each hex digit from `<hex-data>` is transformed into four binary digits in the usual fashion. After that, if the last character of `<hex-data>` is an underscore _, then all trailing binary zeroes and the binary one immediately preceding them are removed from the resulting binary string.\n\nIn this way, `b{00011101}` and `x{1d}` both push the same _Slice_ consisting of eight data bits and no references. Similarly, `b{111010}` and `x{EA_}` push the same _Slice_ consisting of six data bits. An empty _Slice_ can be represented as `b{}` or `x{}`.\n\nIf one wishes to define constant _Slice_'s with some _Cell_ references, the following words might be used:\n\n| Word | Stack | Description\n| :--- | :--- | :------------------------\n| **`\\|_`** | _`(s s' – s'')`_ | given two _Slice_'s `s` and `s'` , creates a new _Slice_ `s''`, which is obtained from `s` by appending a new reference to a _Cell_ containing `s'`.\n| **`\\|+`** | _`(s s' – s'')`_ | concatenates two _Slice_'s `s` and `s'` . This means that the data bits of the new _Slice_ `s''` are obtained by concatenating the data bits of `s` and `s'`, and the list of _Cell_ references of `s''` is constructed similarly by concatenating the corresponding lists for `s` and `s'`.\n\n### 5.2 Builder primitives\n\nThe following words can be used to manipulate _Builder_'s, which can later be used to construct new _Cell_'s:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`<b`** | _`( – b)`_ | creates a new empty _Builder_.\n| **`b>`** | _`(b – c)`_ | transforms a _Builder_ `b` into a new _Cell_ `c` containing the same data as `b`.\n| **`i,`** | _`(b x y – b' )`_ | appends the big-endian binary representation of a signed `y`-bit integer `x` to _Builder_ `b`, where $0 ≤ y ≤ 257$. If there is not enough room in `b` (i.e., if `b` already contains more than `1023 − y` data bits), or if _Integer_ `x` does not fit into `y` bits, an exception is thrown.\n| **`u,`** | _`(b x y – b' )`_ | appends the big-endian binary representation of an unsigned `y`-bit integer `x` to _Builder_ `b`, where $0 ≤ y ≤ 256$. If the operation is impossible, an exception is thrown.\n| **`ref,`** | _`(b c – b' )`_ | appends to _Builder_ `b` a reference to _Cell_ `c`. If `b` already contains four references, an exception is thrown.\n| **`s,`** | _`(b s – b' )`_ | appends data bits and references taken from _Slice_ `s` to _Builder_ `b`.\n| **`sr,`** | _`(b s – b' )`_ | constructs a new _Cell_ containing all data and references from _Slice_ `s`, and appends a reference to this cell to _Builder_ `b`. Equivalent to `<b swap s, b> ref,`.\n| **`$,`** | _`(b S – b' )`_ | appends _String_ `S` to _Builder_ `b`. The string is interpreted as a binary string of length `8 * n`, where `n` is the number of bytes in the UTF-8 representation of `S`.\n| **`B,`** | _`(b B – b' )`_ | appends _Bytes_ `B` to _Builder_ `b`.\n| **`b+`** | _`(b b' – b'')`_ | concatenates two _Builder_'s `b` and `b'`.\n| **`bbits`** | _`(b – x)`_ | returns the number of data bits already stored in _Builder_ `b`. The result `x` is an _Integer_ in the range `0...1023`.\n| **`brefs`** | _`(b – x)`_ | returns the number of references already stored in _Builder_ `b`. The result `x` is an _Integer_ in the range `0...4`.\n| **`bbitrefs`** | _`(b – x y)`_ | returns both the number of data bits `x` and the number of references `y` already stored in _Builder_ `b`.\n| **`brembits`** | _`(b – x)`_ | returns the maximum number of additional data bits that can be stored in _Builder_ `b`. Equivalent to `bbits 1023 swap -`.\n| **`bremrefs`** | _`(b – x)`_ | returns the maximum number of additional cell references that can be stored in _Builder_ `b`.\n| **`brembitrefs`** | _`(b – x y)`_ | returns both the maximum number of additional data bits $0 ≤ x ≤ 1023$ and the maximum number of additional cell references $0 ≤ y ≤ 4$ that can be stored in _Builder_ `b`.\n\nThe resulting _Builder_ may be inspected by means of the non-destructive stack dump primitive .s, or by the phrase `b> <s csr.`. For instance:\n\n```fift\n{ <b x{4A} s, rot 16 u, swap 32 i, .s b>  } : mkTest\n17239 -1000000001 mkTest\n<s csr.\n```\noutputs\n\n```\nBC{000e4a4357c46535ff}\n ok\nx{4A4357C46535FF}\n ok\n```\n\nOne can observe that `.s` dumps the internal representation of a _Builder_, with two tag bytes at the beginning (usually equal to the number of cell references already stored in the _Builder_, and to twice the number of complete bytes stored in the _Builder_, increased by one if an incomplete byte is present). On the other hand, `csr.` dumps a _Slice_ (constructed from a _Cell_ by `<s`) in a form similar to that used by `x{` to define _Slice_ literals.\n\nIncidentally, the word `mkTest` shown above (without the `.s` in its definition) corresponds to the TL-B constructor\n\n```tlb\ntest#4a first:uint16 second:int32 = Test;\n```\n\nand may be used to serialize values of this TL-B type.\n\n### 5.3 Slice primitives\n\nThe following words can be used to manipulate values of the type _Slice_, which represents a read-only view of a portion of a _Cell_. In this way data previously stored into a _Cell_ may be deserialized, by first transforming a _Cell_ into a _Slice_, and then extracting the required data from this _Slice_ step-by-step.\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`<s`** | _`(c – s)`_ | transforms a _Cell_ `c` into a _Slice_ `s` containing the same data. It usually marks the start of the deserialization of a cell.\n| **`s>`** | _`(s – )`_ | throws an exception if _Slice_ `s` is non-empty. It usually marks the end of the deserialization of a cell, checking whether there are any unprocessed data bits or references left.\n| **`i@`** | _`(s x – y)`_ | fetches a signed big-endian `x`-bit integer from the first `x` bits of _Slice_ `s`. If `s` contains less than `x` data bits, an exception is thrown.\n| **`i@+`** | _`(s x – y s' )`_ | fetches a signed big-endian `x`-bit integer from the first `x` bits of _Slice_ `s` similarly to `i@`, but returns the remainder of `s` as well.\n| **`i@?`** | _`(s x – y −1 or 0)`_ | fetches a signed integer from a _Slice_ similarly to `i@`, but pushes integer −1 afterwards on success. If there are less than `x` bits left in `s`, pushes integer 0 to indicate failure.\n| **`i@?+`** | _`(s x – y s' −1 or s')`_ | fetches a signed integer from _Slice_ `s` and computes the remainder of this _Slice_ similarly to `i@+`, but pushes −1 afterwards to indicate success. On failure, pushes the unchanged _Slice_ `s` and 0 to indicate failure.\n| **`u@, u@+, u@?, u@?+,`** | | counterparts of i@, i@+, i@?, i@?+ for deserializing unsigned integers.\n| **`B@`** | _`(s x – B)`_ | fetches first `x` bytes (i.e., $8 * x$ bits) from _Slice_ `s`, and returns them as a _Bytes_ value `B`. If there are not enough data bits in `s`, throws an exception.\n| **`B@+`** | _`(s x – B s' )`_ | similar to `B@`, but returns the remainder of _Slice_ `s` as well.\n| **`B@?`** | _`(s x – B −1 or 0)`_ | similar to `B@`, but uses a flag to indicate failure instead of throwing an exception.\n| **`B@?+`** | _`(s x – B s' −1 or s')`_ | similar to `B@+`, but uses a flag to indicate failure instead of throwing an exception.\n| **`$@, $@+, $@?, $@?+`** |  | counterparts of B@, B@+, B@?, B@?+, returning the result as a (UTF-8) _String_ instead of a _Bytes_ value. These primitives do not check whether the byte sequence read is a valid UTF-8 string.\n| **`ref@`** | _`(s – c)`_ | fetches the first reference from _Slice_ `s` and returns the _Cell_ `c` referred to. If there are no references left, throws an exception.\n| **`ref@+`** | _`(s – s' c)`_ | similar to `ref@`, but returns the remainder of `s` as well.\n| **`ref@?`** | _`(s – c −1 or 0)`_ | similar to `ref@`, but uses a flag to indicate failure instead of throwing an exception.\n| **`ref@?+`** | _`(s – s' c −1 or s')`_ | similar to `ref@+`, but uses a flag to indicate failure instead of throwing an exception.\n| **`empty?`** | _`(s – ?)`_ | checks whether a _Slice_ is empty (i.e., has no data bits and no references left)`_ | and returns −1 or 0 accordingly.\n| **`remaining`** | _`(s – x y)`_ | returns both the number of data bits `x` and the number of cell references `y` remaining in _Slice_ `s`.\n| **`sbits`** | _`(s – x)`_ | returns the number of data bits `x` remaining in _Slice_ `s`.\n| **`srefs`** | _`(s – x)`_ | returns the number of cell references `x` remaining in _Slice_ `s`.\n| **`sbitrefs`** | _`(s – x y)`_ | returns both the number of data bits `x` and the number of cell references `y` remaining in _Slice_ `s`. Equivalent to `remaining`.\n| **`$>s`** | _`(S – s)`_ | transforms _String_ `S` into a _Slice_. Equivalent to `<b swap $, b> <s`.\n| **`s>c`** | _`(s – c)`_ | creates a _Cell_ `c` directly from a _Slice_ `s`. Equivalent to `<b swap s, b>`.\n| **`csr.`** | _`(s – )`_ | recursively prints a _Slice_ `s`. On the first line, the data bits of `s` are displayed in hexadecimal form embedded into an `x{...}` construct similar to the one used for _Slice_ literals. On the next lines, the cells referred to by `s` are printed with larger indentation.\n\nFor instance, values of the TL-B type `Test` discussed in 5.2\n\n```tlb\ntest#4a first:uint16 second:int32 = Test;\n```\n\nmay be deserialized as follows:\n\n```fift\n{ <s 8 u@+ swap 0x4a <> abort\"constructor tag mismatch\"\n     16 u@+ 32 i@+ s> } : unpackTest\nx{4A4357C46535FF} s>c unpackTest swap . .\n```\n\nprints `\"17239 -1000000001 ok\"` as expected.\n\nOf course, if one needs to check constructor tags often, a helper word can be defined for this purpose:\n\n```fift\n{ dup remaining abort\"references in constructor tag\"\n  tuck u@ -rot u@+ -rot <> abort\"constructor tag mismatch\"\n} : tag?\n{ <s x{4a} tag? 16 u@+ 32 i@+ s> } : unpackTest\nx{4A4357C46535FF} s>c unpackTest swap . .\n```\n\nWe can do even better with the aid of active prefix words:\n\n```fift\n{ dup remaining abort\"references in constructor tag\"\n  dup 256 > abort\"constructor tag too long\"\n  tuck u@ 2 { -rot u@+ -rot <> abort\"constructor tag mismatch\" }\n} : (tagchk)\n{ [compile] x{ 2drop (tagchk) } ::_ ?x{\n{ [compile] b{ 2drop (tagchk) } ::_ ?b{\n{ <s ?x{4a} 16 u@+ 32 i@+ s> } : unpackTest\nx{4A4357C46535FF} s>c unpackTest swap . .\n```\n\nA shorter but less efficient solution would be to reuse the previously defined `tag?`:\n\n```fift\n{ [compile] x{ drop ' tag? } ::_ ?x{\n{ [compile] b{ drop ' tag? } ::_ ?b{\nx{11EF55AA} ?x{11E} dup csr.\n?b{110} csr.\n```\n\nfirst outputs `\"x{F55AA}\"`, and then throws an exception with the message \"constructor tag mismatch\".\n\n### 5.4 Cell hash operations\n\nThere are few words that operate on _Cell_'s directly. The most important of them computes the (sha256-based) representation hash of a given cell, which can be roughly described as the sha256 hash of the cell's data bits concatenated with recursively computed hashes of the cells referred to by this cell:\n\n| Word | Stack | Description\n| :--- | :--- | :------------------------\n| **`hash`** | _`(c – B)`_ | computes the sha256-based representation hash of _Cell_ `c`, which unambiguously defines `c` and all its descendants (provided there are no collisions for sha256). The result is returned as a _Bytes_ value consisting of exactly 32 bytes.\n| **`shash`** | _`(s – B)`_ | computes the sha256-based representation hash of a _Slice_ by first transforming it into a cell. Equivalent to `s>c hashB`.\n\n### 5.5 Bag-of-cells operations\n\nA _bag of cells_ is a collection of one or more cells along with all their descendants. It can usually be serialized into a sequence of bytes (represented by a _Bytes_ value in Fift) and then saved into a file or transferred by network. Afterwards, it can be deserialized to recover the original cells. The TON Blockchain systematically represents different data structures (including the TON Blockchain blocks) as a tree of cells according to a certain TL-B scheme, and then these trees of cells are routinely imported into bags of cells and serialized into binary files.\n\nFift words for manipulating bags of cells include:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`B>boc`** | _`(B – c)`_ | deserializes a \"standard\" _bag of cells_ (i.e., a _bag of cells_ with exactly one root cell) represented by _Bytes_ `B`, and returns the root _Cell_ `c`.\n| **`boc+>B`** | _`(c x – B)`_ | creates and serializes a \"standard\" _bag of cells_, containing one root _Cell_ `c` along with all its descendants. An _Integer_ parameter `0 ≤ x ≤ 31` is used to pass flags indicating the additional options for bag-of-cells serialization, with individual bits having the following effect:<br/><br/>  – **`+1`** enables bag-of-cells index creation (useful for lazy deserialization of large bags of cells).<br/>  – **`+2`** includes the CRC32-C of all data into the serialization (useful for checking data integrity).<br/>  – **`+4`** explicitly stores the hash of the root cell into the serialization (so that it can be quickly recovered afterwards without a complete deserialization).<br/>  – **`+8`** stores hashes of some intermediate (non-leaf) cells (useful for lazy deserialization of large bags of cells).<br/>  – **`+16`** stores cell cache bits to control caching of deserialized cells.<br/><br/>Typical values of `x` are `x = 0` or `x = 2` for very small bags of cells (e.g., TON Blockchain external messages) and `x = 31` for large bags of cells (e.g., TON Blockchain blocks).\n| **`boc>B`** | _`(c – B)`_ | serializes a small \"standard\" _bag of cells_ with root _Cell_ `c` and all its descendants. Equivalent to `0 boc+>B`.\n\nFor instance, the cell created in 5.2 with a value of TL-B `Test` type may be serialized as follows:\n\n```fift\n{ <b x{4A} s, rot 16 u, swap 32 i, b> } : mkTest\n17239 -1000000001 mkTest boc>B Bx.\n```\n\noutputs `\"B5EE9C7201040101000000000900000E4A4357C46535FF ok\"`. Here `Bx.` is the word that prints the hexadecimal representation of a _Bytes_ value.\n\n### 5.6 Binary file I/O and Bytes manipulation\n\nThe following words can be used to manipulate values of type _Bytes_ (arbitrary byte sequences) and to read them from or write them into binary files:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`B{hex-digits}`** | _`( – B)`_ | pushes a _Bytes_ literal containing data represented by an even number of hexadecimal digits.\n| **`Bx.`** | _`(B – )`_ | prints the hexadecimal representation of a _Bytes_ value. Each byte is represented by exactly two uppercase hexadecimal digits.\n| **`file>B`** | _`(S – B)`_ | reads the (binary) file with the name specified in _String_ `S` and returns its contents as a _Bytes_ value. If the file does not exist, an exception is thrown.\n| **`B>file`** | _`(B S – )`_ | creates a new (binary) file with the name specified in _String_ `S` and writes data from _Bytes_ `B` into the new file. If the specified file already exists, it is overwritten.\n| **`file-exists?`** | _`(S – ?)`_ | checks whether the file with the name specified in _String_ `S` exists.\n\nFor instance, the _bag of cells_ created in the example in 5.5 can be saved to disk as sample.boc as follows:\n\n```fift\n{ <b x{4A} s, rot 16 u, swap 32 i, b> } : mkTest\n17239 -1000000001 mkTest boc>B \"sample.boc\" B>file\n```\n\nIt can be loaded and deserialized afterwards (even in another Fift session) by means of `file>B` and `B>boc`:\n\n```fift\n{ <s 8 u@+ swap 0x4a <> abort\"constructor tag mismatch\" 16 u@+ 32 i@+ s> } : unpackTest\n\"sample.boc\" file>B B>boc unpackTest swap . .\n```\n\nprints `\"17239 -1000000001 ok\"`.\n\nAdditionally, there are several words for directly packing (serializing) data into _Bytes_ values, and unpacking (deserializing) them afterwards. They can be combined with `B>file` and `file>B` to save data directly into binary files, and load them afterwards.\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`Blen`** | _`(B – x)`_ | returns the length of a _Bytes_ value `B` in bytes.\n| **`Bhash`** | _`(B – B' )`_ | computes the sha256 hash of a _Bytes_ value. The hash is returned as a 32-byte _Bytes_ value.\n| **`B=`** | _`(B B' – ?)`_ | checks whether two _Bytes_ sequences are equal.\n| **`Bcmp`** | _`(B B' – x)`_ | lexicographically compares two _Bytes_ sequences, and returns `−1`, `0`, or `1`, depending on the comparison result.\n| **`B>i@`** | _`(B x – y)`_ | deserializes the first `x/8` bytes of a _Bytes_ value `B` as a signed big-endian `x`-bit _Integer_ `y`.\n| **`B>i@+`** | _`(B x – B' y)`_ | deserializes the first `x/8` bytes of `B` as a signed big-endian `x`-bit _Integer_ `y` similarly to `B>i@`, but also returns the remaining bytes of `B`.\n| **`B>u@`**, **`B>u@+`** | | variants of `B>i@` and `B>i@+` deserializing unsigned integers.\n| **`B>Li@`**, **`B>Li@+`**, **`B>Lu`**, **`B>Lu@+`** | | little-endian variants of `B>i@`, `B>i@+`, `B>u@`, `B>u@+`.\n| **`B\\|`** | _`(B x – B' B'')`_ | cuts the first `x` bytes from a _Bytes_ value `B`, and returns both the first `x` bytes (`B'`) and the remainder (`B''`) as new _Bytes_ values.\n| **`i>B`** | _`(x y – B)`_ | stores a signed big-endian `y`-bit _Integer_ `x` into a _Bytes_ value `B` consisting of exactly `y/8` bytes. _Integer_ `y` must be a multiple of eight in the range `0 ... 256`.\n| **`u>B`** | _`(x y – B)`_ | stores an unsigned big-endian `y`-bit _Integer_ `x` into a _Bytes_ value `B` consisting of exactly y/8 bytes, similarly to `i>B`.\n| **`Li>B, Lu>B`** | | little-endian variants of `i>B` and `u>B`.\n| **`B+`** | _`(B' B'' – B)`_ | concatenates two _Bytes_ sequences.\n\n## 6 TON-specific operations\n\nThis chapter describes the TON-specific Fift words, with the exception of the words used for _Cell_ manipulation, already discussed in the previous chapter.\n\n### 6.1 Ed25519 cryptography\n\nFift offers an interface to the same Ed25519 elliptic curve cryptography used by TVM, described in Appendix A:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`now`** | _`( – x)`_ | returns the current Unixtime as an _Integer_.\n| **`newkeypair`** | _`( – B B' )`_ | generates a new Ed25519 private/public key pair, and returns both the private key `B` and the public key `B'` as 32-byte _Bytes_ values. The quality of the keys is good enough for testing purposes. Real applications must feed enough entropy into OpenSSL PRNG before generating Ed25519 key pairs.\n| **`priv>pub`** | _`(B – B' )`_ | computes the public key corresponding to a private Ed25519 key. Both the public key `B'` and the private key `B` are represented by 32-byte _Bytes_ values.\n| **`ed25519_sign`** | _`(B B' – B'')`_ | signs data `B` with the Ed25519 private key `B'` (a 32-byte _Bytes_ value) and returns the signature as a 64-byte _Bytes_ value `B''` .\n| **`ed25519_sign_uint`** | _`(x B' – B'')`_ | converts a big-endian unsigned 256-bit integer `x` into a 32-byte sequence and signs it using the Ed25519 private key `B'` similarly to `ed25519_sign`. Equivalent to `swap 256 u>B swap ed25519_sign`. The integer `x` to be signed is typically computed as the hash of some data.\n| **`ed25519_chksign`** | _`(B B' B'' – ?)`_ | checks whether `B'` is a valid Ed25519 signature of data `B` with the public key `B''` .\n\n### 6.2 Smart-contract address parser\n\nTwo special words can be used to parse TON smart-contract addresses in human-readable (base64 or base64url) forms:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`smca>$`** | _`(x y z – S)`_ | packs a standard TON smart-contract address with workchain `x` (a signed 32-bit _Integer_) and in-workchain address `y` (an unsigned 256-bit _Integer_) into a 48-character string `S` (the human-readable representation of the address) according to flags `z`. Possible individual flags in `z` are: `+1` for non-bounceable addresses, `+2` for testnet-only addresses, and `+4` for base64url output instead of base64.\n| **`$>smca`** | _`(S – x y z −1 or 0)`_ | unpacks a standard TON smart-contract address from its human-readable string representation `S`. On success, returns the signed 32-bit workchain `x`, the unsigned 256-bit workchain address `y`, the flags `z` (where `+1` means that the address is non-bounceable, `+2` that the address is testnet-only), and `−1`. On failure, pushes `0`.\n\nA sample human-readable smart-contract address could be deserialized and displayed as follows:\n\n```fift\n\"Ef9Tj6fMJP-OqhAdhKXxq36DL-HYSzCc3-9O6UNzqsgPfYFX\"\n$>smca 0= abort\"bad address\"\nrot . swap x. . cr\n```\n\noutputs `\"-1 538fa7...0f7d 0\"`, meaning that the specified address is in workchain `−1` (the masterchain of the TON Blockchain), and that the 256-bit address inside workchain `−1` is `0x538... f7d`.\n\n### 6.3 Dictionary manipulation\n\nFift has several words for hashmap or (TVM) dictionary manipulation, corresponding to values of TL-B type `HashmapE n X` as described in [4, 3.3]. These (TVM) dictionaries are not to be confused with the Fift dictionary, which is a completely different thing. A dictionary of TL-B type `HashmapE n X` is essentially a key-value collection with distinct `n`-bit keys (where `0 ≤ n ≤ 1023`) and values of an arbitrary TL-B type `X`. Dictionaries are represented by trees of cells (the complete layout may be found in [4, 3.3]) and stored as values of type _Cell_ or _Slice_ in the Fift stack.\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`dictnew`** | _`( – D)`_ | pushes the _Null_ that represents a new empty dictionary. Equivalent to `null`.\n| **`idict!`** | _`(v x D n – D' −1 or D 0)`_ | adds a new value `v` (represented by a _Slice_) with key given by signed big-endian `n`-bit integer `x` into dictionary `D` with `n`-bit keys, and returns the new dictionary `D'` and −1 on success. Otherwise the unchanged dictionary `D` and 0 are returned.\n| **`idict!+`** | _`(v x D n – D' −1 or D 0)`_ | adds a new key-value pair `(x, v)` into dictionary `D` similarly to `idict!`, but fails if the key already exists by returning the unchanged dictionary `D` and 0.\n| **`b>idict!, b>idict!+`** | | variants of `idict!` and `idict!+` accepting the new value `v` in a _Builder_ instead of a _Slice_.\n| **`udict!, udict!+, b>udict!, b>udict!+`** | | variants of `idict!`, `idict!+`, `b>idict!`, `b>idict!+`, but with an unsigned `n`-bit integer `x` used as a key.\n| **`idict@`** | _`(x s n – v −1 or 0)`_ | looks up the key represented by signed big-endian `n`-bit _Integer_ `x` in the dictionary represented by _Slice_ `s`. If the key is found, returns the corresponding value as a _Slice_ `v` and `−1`. Otherwise returns `0`.\n| **`udict@`** | _`(x s n – v −1 or 0)`_ | similar to `idict@`, but with an unsigned big-endian `n`-bit _Integer_ `x` used as a key.\n| **`dictmap`** | _`(s n e – s')`_ | applies execution token `e` (i.e., an anonymous function) to each of the key-value pairs stored in a dictionary `s` with `n`-bit keys. The execution token is executed once for each key-value pair, with a _Builder_ `b` and a _Slice_ `v` (containing the value) pushed into the stack before executing `e`. After the execution `e` must leave in the stack either a modified _Builder_ `b'` (containing all data from `b` along with the new value `v 0` ) and `−1`, or `0` indicating failure. In the latter case, the corresponding key is omitted from the new dictionary.\n| **`dictmerge`** | _`(s s' n e – s'')`_ | combines two dictionaries `s` and `s'` with `n`-bit keys into one dictionary `s''` with the same keys. If a key is present in only one of the dictionaries `s` and `s'`, this key and the corresponding value are copied verbatim to the new dictionary `s'`. Otherwise the execution token (anonymous function) `e` is invoked to merge the two values `v` and `v 0` corresponding to the same key `k` in `s` and `s 0` , respectively. Before `e` is invoked, a _Builder_ `b` and two _Slice_'s `v` and `v 0` representing the two values to be merged are pushed. After the execution `e` leaves either a modified _Builder_ `b 0` (containing the original data from `b` along with the combined value) and `−1`, or `0` on failure. In the latter case, the corresponding key is omitted from the new dictionary.\n\nFift also offers some support for prefix dictionaries:\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`pfxdict!`** | _`(v k s n – s 0 −1 or s 0)`_ | adds key-value pair `(k, v)`, both represented by _Slice_'s, into a prefix dictionary `s` with keys of length at most `n`. On success, returns the modified dictionary `s 0` and `−1`. On failure, returns the original dictionary `s` and `0`.\n| **`pfxdict!+`** | _`(v k s n – s 0 −1 or s 0)`_ | adds key-value pair `(k, v)` into prefix dictionary `s` similarly to `pfxdict!`, but fails if the key already exists.\n| **`pfxdict@`** | _`(k s n – v −1 or 0)`_ | looks up key `k` (represented by a _Slice_) in the prefix dictionary `s` with the length of keys limited by `n` bits. On success, returns the value found `v` and `−1`. On failure, returns `0`.\n\n### 6.4 Invoking TVM from Fift\n\nTVM can be linked with the Fift interpreter. In this case, several Fift primitives become available that can be used to invoke TVM with arguments provided from Fift. The arguments can be prepared in the Fift stack, which is passed in its entirety to the new instance of TVM. The resulting stack and the exit code are passed back to Fift and can be examined afterwards.\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`runvmcode`** | _`(... s – ... x)`_ | invokes a new instance of TVM with the current continuation `cc` initialized from _Slice_ `s`, thus executing code `s` in TVM. The original Fift stack (without `s`) is passed in its entirety as the initial stack of TVM. When TVM terminates, its resulting stack is used as the new Fift stack, with the exit code `x` pushed at its top. If `x` is non-zero, indicating that TVM has been terminated by an unhandled exception, the next stack entry from the top contains the parameter of this exception, and `x` is the exception code. All other entries are removed from the stack in this case.\n| **`runvmdict`** | _`(... s – ... x)`_ | invokes a new instance of TVM with the current continuation `cc` initialized from _Slice_ `s` similarly to `runvmcode`, but also initializes the special register `c3` with the same value, and pushes a zero into the initial TVM stack before the TVM execution begins. In a typical application _Slice_ `s` consists of a subroutine selection code that uses the top-of-stack _Integer_ to select the subroutine to be executed, thus enabling the definition and execution of several mutually-recursive subroutines. The selector equal to zero corresponds to the `main()` subroutine in a large TVM program.\n| **`runvm`** | _`(... s c – ... x c0 )`_ | invokes a new instance of TVM with both the current continuation `cc` and the special register `c3` initialized from _Slice_ `s`, and pushes a zero into the initial TVM stack similarly to `runvmdict`, but also initializes special register `c4` (the \"root of persistent data\") with _Cell_ `c`. The final value of `c4` is returned at the top of the final Fift stack as another _Cell_ `c 0` . In this way one can emulate the execution of smart contracts that inspect or modify their persistent storage.\n| **`gasrunvmcode`** | _`(... s z – ... x z0 )`_ | a gas-aware version of `runvmcode` that accepts an extra _Integer_ argument `z` (the original gas limit) at the top of the stack, and returns the gas consumed by this TVM run as a new top-of-stack _Integer_ value `z 0`.\n| **`gasrunvmdict`** | _`(... s z – ... x z0 )`_ | a gas-aware version of `runvmdict`.\n| **`gasrunvm`** | _`(... s c z – ... x c0 z 0 )`_ | a gas-aware version of `runvm`.\n\nFor example, one can create an instance of TVM running some simple code as follows:\n\n```fift\n2 3 9 x{1221} runvmcode .s\n```\n\nThe TVM stack is initialized by three integers 2, 3, and 9 (in this order; 9 is the topmost entry), and then the _Slice_ `x{1221}` containing 16 data bits and no references is transformed into a TVM continuation and executed. By consulting the [TVM instructions table](/tvm/instructions), we see that `x{12}` is the code of the TVM instruction `XCHG s1 s2`, and that `x{21}` is the code of the TVM instruction `OVER`. The latter is not to be confused with the Fift primitive `over`, which incidentally has the same effect on the stack, but applies to the Fift stack, not the TVM one.\n\nThe result of the above execution is:\n\n```fift\nexecute XCHG s1,s2\nexecute OVER\nexecute implicit RET\n3 2 9 2 0\n ok\n```\n\nHere 0 is the exit code (indicating successful TVM termination), and 3 2 9 2 is the final TVM stack state.\nIf an unhandled exception is generated during the TVM execution, the code of this exception is returned as the exit code:\n\n```fift\n2 3 9 x{122} runvmcode .s\n```\n\nproduces\n\n```fift\nexecute XCHG s1,s2\nhandling exception code 6: invalid or too short opcode\ndefault exception handler, terminating vm with exit code 6\n0 6\n ok\n```\n\nNotice that TVM is executed with internal logging enabled, and its log is displayed in the standard output.\n\nSimple TVM programs may be represented by _Slice_ literals with the aid of the `x{...}` construct similarly to the above examples. More sophisticated programs are usually created with the aid of the Fift assembler as explained in the next chapter.\n\n## 7 Using the Fift assembler\n\nThe _Fift assembler_ is a short program (currently less than 30KiB) written completely in Fift that transforms human-readable mnemonics of TVM instructions into their binary representation. For instance, one could write `<{ s1 s2 XCHG OVER }>s` instead of `x{1221}` in the example discussed in 6.4, provided the Fift assembler has been loaded beforehand (usually by the phrase \"Asm.fif\" include).\n\n### 7.1 Loading the Fift assembler\n\nThe Fift assembler is usually located in file `Asm.fif` in the Fift library directory (which usually contains standard Fift library files such as Fift.fif). It is typically loaded by putting the phrase \"Asm.fif\" include at the very beginning of a program that needs to use Fift assembler:\n\n| Word | Stack | Description\n| :--- | :--- | :------------------------\n| **`include`** | _`(S – )`_ | loads and interprets a Fift source file from the path given by _String_ `S`. If the filename `S` does not begin with a slash, the Fift include search path, typically taken from the `FIFTPATH` environment variable or the `-I` command-line argument of the Fift interpreter (and equal to `/usr/lib/fift` if both are absent), is used to locate `S`.\n\nThe current implementation of the Fift assembler makes heavy use of custom defining words; its source can be studied as a good example of how defining words might be used to write very compact Fift programs.\n\nIn the future, almost all of the words defined by the Fift assembler will be moved to a separate vocabulary (namespace). Currently they are defined in the global namespace, because Fift does not support namespaces yet.\n\n### 7.2 Fift assembler basics\n\nThe Fift assembler inherits from Fift its postfix operation notation, i.e., the arguments or parameters are written before the corresponding instructions. For instance, the TVM assembler instruction represented as `XCHG s1,s2` is represented in the Fift assembler as `s1 s2 XCHG`.\n\nFift assembler code is usually opened by a special opening word, such as `<{`, and terminated by a closing word, such as `}>` or `}>s`. For instance,\n\n```fift\n\"Asm.fif\" include\n<{ s1 s2 XCHG OVER }>s\ncsr.\n```\n\ncompiles two TVM instructions `XCHG s1,s2` and OVER, and returns the result as a _Slice_ (because `}>s` is used). The resulting _Slice_ is displayed by `csr.`, yielding\n\n```fift\nx{1221}\n```\n\nOne can use Appendix A and verify that `x{12}` is indeed the (codepage zero) code of the TVM instruction `XCHG s1,s2`, and that `x{21}` is the code of the TVM instruction `OVER` (not to be confused with Fift primitive `over`).\n\nIn the future, we will assume that the Fift assembler is already loaded and omit the phrase `\"Asm.fif\" include` from our examples.\n\nThe Fift assembler uses the Fift stack in a straightforward fashion, using the top several stack entries to hold a _Builder_ with the code being assembled,\nand the arguments to TVM instructions. For example:\n\n| Word | Stack | Description\n| :--- | :--- | :------------------------\n| **`<{`** | _`( – b)`_ | begins a portion of Fift assembler code by pushing an empty _Builder_ into the Fift stack (and potentially switching the namespace to the one containing all Fift assembler-specific words). Approximately equivalent to `<b`.\n| **`}>`** | _`(b – b')`_ | terminates a portion of Fift assembler code and returns the assembled portion as a _Builder_ (and potentially recovers the original namespace). Approximately equivalent to `nop` in most situations.\n| **`}>c`** | _`(b – c)`_ | terminates a portion of Fift assembler code and returns the assembled portion as a _Cell_ (and potentially recovers the original namespace). Approximately equivalent to `b>`.\n| **`}>s`** | _`(b – s)`_ | terminates a portion of Fift assembler code similarly to `}>`, but returns the assembled portion as a _Slice_. Equivalent to `}>c <s`.\n| **`OVER`** | _`(b – b')`_ | assembles the code of the TVM instruction `OVER` by appending it to the _Builder_ at the top of the stack. Approximately equivalent to `x{21} s,`.\n| **`s1`** | _`( – s)`_ | pushes a special _Slice_ used by the Fift assembler to represent the \"stack register\" s1 of TVM.\n| **`s0... s15`** | _`( – s)`_ | words similar to `s1`, but pushing the _Slice_ representing other \"stack registers\" of TVM. Notice that `s16... s255` must be accessed using the word `s()`.\n| **`s()`** | _`(x – s)`_ | takes an _Integer_ argument `0 ≤ x ≤ 255` and returns a special _Slice_ used by the Fift assembler to represent \"stack register\" `s(x)`.\n| **`XCHG`** | _`(b s s0 – b0)`_ | takes two special Slices representing two \"stack registers\" `s(i)` and `s(j)` from the stack, and appends to _Builder_ `b` the code for the TVM instruction `XCHG s(i),s(j)`.\n\nIn particular, note that the word `OVER` defined by the Fift assembler has a completely different effect from Fift primitive over.\n\nThe actual action of `OVER` and other Fift assembler words is somewhat more complicated than that of `x{21} s,`. If the new instruction code does not fit into the _Builder_ `b` (i.e., if `b` would contain more than 1023 data bits after adding the new instruction code), then this and all subsequent instructions are assembled into a new _Builder_ `˜b`, and the old _Builder_ `b` is augmented by a reference to the _Cell_ obtained from `˜b` once the generation of `˜b` is finished. In this way long stretches of TVM code are automatically split into chains of valid Cells containing at most 1023 bits each. Because TVM interprets a lonely cell reference at the end of a continuation as an implicit `JMPREF`, this partitioning of TVM code into cells has almost no effect on the execution.\n\n### 7.3 Pushing integer constants\n\nThe TVM instruction `PUSHINT x`, pushing an _Integer_ constant `x` when invoked, can be assembled with the aid of Fift assembler words `INT` or `PUSHINT`:\n\n| Word | Stack | Description\n| :--- | :--- | :------------------------\n| **`PUSHINT`** | _`(b x – b0)`_ | assembles TVM instruction `PUSHINT x` into a _Builder_.\n| **`INT`** | _`(b x – b0)`_ | equivalent to `PUSHINT`.\n\nNotice that the argument to `PUSHINT` is an _Integer_ value taken from the Fift stack and is not necessarily a literal. For instance, `<{ 239 17 * INT }>s` is a valid way to assemble a `PUSHINT 4063` instruction, because `239·17 = 4063`. Notice that the multiplication is performed by Fift during assemble time, not during the TVM runtime. The latter computation might be performed by means of `<{ 239 INT 17 INT MUL }>s`:\n\n```fift\n<{ 239 17 * INT }>s dup csr. runvmcode .s 2drop\n<{ 239 INT 17 INT MUL }>s dup csr. runvmcode .s 2drop\n```\n\nproduces\n\n```fift\nx{810FDF}\nexecute PUSHINT 4063\nexecute implicit RET\n4063 0\n ok\nx{8100EF8011A8}\nexecute PUSHINT 239\nexecute PUSHINT 17\nexecute MUL\nexecute implicit RET\n4063 0\n ok\n```\n\nNotice that the Fift assembler chooses the shortest encoding of the `PUSHINT x` instruction depending on its argument `x`.\n\n### 7.4 Immediate arguments\n\nSome TVM instructions (such as PUSHINT) accept immediate arguments. These arguments are usually passed to the Fift word assembling the corresponding instruction in the Fift stack. _Integer_ immediate arguments are usually represented by _Integer_'s, cells by _Cell_'s, continuations by _Builder_'s and _Cell_'s, and cell slices by _Slice_'s. For instance, `17 ADDCONST` assembles TVM instruction `ADDCONST 17`, and `x{ABCD_} PUSHSLICE` assembles `PUSHSLICE xABCD_`:\n\n```fift\n239 <{ 17 ADDCONST x{ABCD_} PUSHSLICE }>s dup csr.\nrunvmcode . swap . csr.\n```\n\nproduces\n\n```fift\nx{A6118B2ABCD0}\nexecute ADDINT 17\nexecute PUSHSLICE xABCD_\nexecute implicit RET\n0 256 x{ABCD_}\n```\n\nOn some occasions, the Fift assembler pretends to be able to accept immediate arguments that are out of range for the corresponding TVM instruction. For instance, `ADDCONST x` is defined only for `−128 ≤ x < 128`, but the Fift assembler accepts `239 ADDCONST`:\n\n```fift\n17 <{ 239 ADDCONST }>s dup csr. runvmcode .s\n```\n\nproduces\n\n```fift\nx{8100EFA0}\nexecute PUSHINT 239\nexecute ADD\nexecute implicit RET\n256 0\n```\n\nWe can see that `\"ADDCONST 239\"` has been tacitly replaced by `PUSHINT 239` and `ADD`. This feature is convenient when the immediate argument to `ADDCONST` is itself a result of a Fift computation, and it is difficult to estimate whether it will always fit into the required range.\n\nIn some cases, there are several versions of the same TVM instructions, one accepting an immediate argument and another without any arguments. For instance, there are both `LSHIFT n` and `LSHIFT` instructions. In the Fift assembler, such variants are assigned distinct mnemonics. In particular, `LSHIFT n` is represented by `n LSHIFT#`, and `LSHIFT` is represented by itself.\n\n### 7.5 Immediate continuations\n\nWhen an immediate argument is a continuation, it is convenient to create the corresponding _Builder_ in the Fift stack by means of a nested `<{ ... }>` construct. For instance, TVM assembler instructions\n\n```fift\nPUSHINT 1\nSWAP\nPUSHCONT {\n    MULCONST 10\n}\nREPEAT\n```\n\ncan be assembled and executed by\n\n```fift\n7\n<{ 1 INT SWAP <{ 10 MULCONST }> PUSHCONT REPEAT }>s dup csr.\nrunvmcode drop .\n```\n\nproducing\n\n```fift\nx{710192A70AE4}\nexecute PUSHINT 1\nexecute SWAP\nexecute PUSHCONT xA70A\nexecute REPEAT\nrepeat 7 more times\nexecute MULINT 10\nexecute implicit RET\nrepeat 6 more times\n...\nrepeat 1 more times\nexecute MULINT 10\nexecute implicit RET\nrepeat 0 more times\nexecute implicit RET\n10000000\n```\n\nMore convenient ways to use literal continuations created by means of the Fift assembler exist. For instance, the above example can be also assembled by\n\n```fift\n<{ 1 INT SWAP CONT:<{ 10 MULCONST }> REPEAT }>s csr.\n```\n\nor even\n\n```fift\n<{ 1 INT SWAP REPEAT:<{ 10 MULCONST }> }>s csr.\n```\n\nboth producing `\"x{710192A70AE4} ok\"`.\n\nIncidentally, a better way of implementing the above loop is by means of `REPEATEND`:\n\n```fift\n7 <{ 1 INT SWAP REPEATEND 10 MULCONST }>s dup csr.\nrunvmcode drop .\n```\n\nor\n\n```fift\n7 <{ 1 INT SWAP REPEAT: 10 MULCONST }>s dup csr.\nrunvmcode drop .\n```\n\nboth produce `\"x{7101E7A70A}\"` and output `\"10000000\"` after seven iterations of the loop.\n\nNotice that several TVM instructions that store a continuation in a separate cell reference (such as JMPREF) accept their argument in a _Cell_, not in a _Builder_. In such situations, the `<{ ... }>c` construct can be used to produce this immediate argument.\n\n### 7.6 Control flow: loops and conditionals\n\nAlmost all TVM control flow instructions—such as `IF`, `IFNOT`, `IFRET`, `IFNOTRET`, `IFELSE`, `WHILE`, `WHILEEND`, `REPEAT`, `REPEATEND`, `UNTIL`, and `UNTILEND` — can be assembled similarly to `REPEAT` and `REPEATEND` in the examples of 7.5 when applied to literal continuations. For instance, TVM assembler code\n\n```fift\nDUP\nPUSHINT 1\nAND\nPUSHCONT {\n    MULCONST 3\n    INC\n}\nPUSHCONT {\n    RSHIFT 1\n}\nIFELSE\n```\n\nwhich computes `3n + 1` or `n/2` depending on whether its argument `n` is odd or even, can be assembled and applied to `n = 7` by\n\n```fift\n<{ DUP 1 INT AND\n   IF:<{ 3 MULCONST INC }>ELSE<{ 1 RSHIFT# }>\n}>s dup csr.\n7 swap runvmcode drop .\n```\n\nproducing\n\n```fift\nx{2071B093A703A492AB00E2}\n ok\nexecute DUP\nexecute PUSHINT 1\nexecute AND\nexecute PUSHCONT xA703A4\nexecute PUSHCONT xAB00\nexecute IFELSE\nexecute MULINT 3\nexecute INC\nexecute implicit RET\nexecute implicit RET\n22 ok\n```\n\nOf course, a more compact and efficient way to implement this conditional expression would be\n\n```fift\n<{ DUP 1 INT AND\n   IF:<{ 3 MULCONST INC }>ELSE: 1 RSHIFT#\n}>s dup csr.\n```\n\nor\n\n```fift\n<{ DUP 1 INT AND\n   CONT:<{ 3 MULCONST INC }> IFJMP\n   1 RSHIFT#\n}>s dup csr.\n```\n\nboth producing the same code `\"x{2071B093A703A4DCAB00}\"`.\n\nFift assembler words that can be used to produce such \"high-level\" conditionals and loops include `IF:<{`, `IFNOT:<{`, `IFJMP:<{`, `}>ELSE<{`, `}>ELSE:`,\n`}>IF`, `REPEAT:<{`, `UNTIL:<{`, `WHILE:<{`, `}>DO<{`, `}>DO:`, `AGAIN:<{`, `}>AGAIN`, `}>REPEAT`, and `}>UNTIL`. Their complete list can be found in the source file `Asm.fif`. For instance, an `UNTIL` loop can be created by `UNTIL:<{ ... }>` or `<{ ... }>UNTIL`, and a `WHILE` loop by `WHILE:<{ ... }>DO<{ ... }>`.\n\nIf we choose to keep a conditional branch in a separate cell, we can use the `<{ ... }>c` construct along with instructions such as `IFJMPREF`:\n\n```fift\n<{ DUP 1 INT AND\n   <{ 3 MULCONST INC }>c IFJMPREF\n   1 RSHIFT#\n}>s dup csr.\n3 swap runvmcode .s\n```\n\nhas the same effect as the code from the previous example when executed, but it is contained in two separate cells:\n\n```fift\nx{2071B0E302AB00}\n x{A703A4}\nexecute DUP\nexecute PUSHINT 1\nexecute AND\nexecute IFJMPREF (2946....A1DD)\nexecute MULINT 3\nexecute INC\nexecute implicit RET\n10 0\n```\n\n### 7.7 Macro definitions\n\nBecause TVM instructions are implemented in the Fift assembler using Fift words that have a predictable effect on the Fift stack, the Fift assembler is automatically a macro assembler, supporting macro definitions. For instance, suppose that we wish to define a macro definition `RANGE x y`, which checks whether the TVM top-of-stack value is between integer literals `x` and `y` (inclusive). This macro definition can be implemented as follows:\n\n```fift\n{ 2dup > ' swap if\n  rot DUP rot GEQINT SWAP swap LEQINT AND\n} : RANGE\n<{ DUP 17 239 RANGE IFNOT: DROP ZERO }>s dup csr.\n66 swap runvmcode drop .\n```\n\nwhich produces\n\n```fift\nx{2020C210018100F0B9B0DC3070}\nexecute DUP\nexecute DUP\nexecute GTINT 16\nexecute SWAP\nexecute PUSHINT 240\nexecute LESS\nexecute AND\nexecute IFRET\n66\n```\n\nNotice that `GEQINT` and `LEQINT` are themselves macro definitions defined in `Asm.fif`, because they do not correspond directly to TVM instructions. For instance, `x GEQINT` corresponds to the TVM instruction `GTINT x − 1`.\n\nIncidentally, the above code can be shortened by two bytes by replacing `IFNOT: DROP ZERO` with `AND`.\n\n### 7.8 Larger programs and subroutines\n\nLarger TVM programs, such as TON Blockchain smart contracts, typically consist of several mutually recursive subroutines, with one or several of them selected as top-level subroutines (called `main()` or `recv_internal()`). The execution starts from one of the top-level subroutines, which is free to call any of the other defined subroutines, which in turn can call whatever other subroutines they need.\n\nSuch TVM programs are implemented by means of a selector function, which accepts an extra integer argument in the TVM stack; this integer selects the actual subroutine to be invoked. Before execution, the code of this selector function is loaded both into special register c3 and into the current continuation cc. The selector of the main function (usually zero) is pushed into the initial stack, and the TVM execution is started. Afterwards a subroutine can be invoked by means of a suitable TVM instruction, such as `CALLDICT n`, where `n` is the (integer) selector of the subroutine to be called.\n\nThe Fift assembler offers several words facilitating the implementation of such large TVM programs. In particular, subroutines can be defined separately and assigned symbolic names (instead of numeric selectors), which can be used to call them afterwards. The Fift assembler automatically creates a selector function from these separate subroutines and returns it as the top-level assembly result.\n\nHere is a simple example of such a program consisting of several subroutines. This program computes the complex number $$(5 + i)^4 * (239 − i)$:\n\n```fift\n\"Asm.fif\" include\n\nPROGRAM{\n\nNEWPROC add\nNEWPROC sub\nNEWPROC mul\n\nsub <{ s3 s3 XCHG2 SUB s2 XCHG0 SUB }>s PROC\n\n// compute (5+i)^4 * (239-i)\nmain PROC:<{\n  5 INT 1 INT // 5+i\n  2DUP\n  mul CALL\n  2DUP\n  mul CALL\n  239 INT -1 INT\n  mul JMP\n}>\n\nadd PROC:<{\n  s1 s2 XCHG\n  ADD -ROT ADD SWAP\n}>\n\n// a b c d -- ac-bd ad+bc : complex number multiplication\nmul PROC:<{\n  s3 s1 PUSH2 // a b c d a c\n  MUL         // a b c d ac\n  s3 s1 PUSH2 // a b c d ac b d\n  MUL         // a b c d ac bd\n  SUB         // a b c d ac-bd\n  s4 s4 XCHG2 // ac-bd b c a d\n  MUL         // ac-bd b c ad\n  -ROT MUL ADD\n}>\n\n}END>s\ndup csr.\nrunvmdict .s\n```\n\nThis program produces:\n\n```fift\nx{FF00F4A40EF4A0F20B}\n x{D9_}\n  x{2_}\n   x{1D5C573C00D73C00E0403BDFFC5000E_}\n   x{04A81668006_}\n  x{2_}\n   x{140CE840A86_}\n   x{14CC6A14CC6A2854112A166A282_}\nimplicit PUSH 0 at start\nexecute SETCP 0\nexecute DICTPUSHCONST 14 (xC_,1)\nexecute DICTIGETJMP\nexecute PUSHINT 5\nexecute PUSHINT 1\nexecute 2DUP\nexecute CALLDICT 3\nexecute SETCP 0\nexecute DICTPUSHCONST 14 (xC_,1)\nexecute DICTIGETJMP\nexecute PUSH2 s3,s1\nexecute MUL\n...\nexecute ROTREV\nexecute MUL\nexecute ADD\nexecute implicit RET\n114244 114244 0\n```\n\nSome observations and comments based on the previous example follow:\n\n- A TVM program is opened by `PROGRAM{` and closed by either `}END>c`, which returns the assembled program as a _Cell_, or `}END>s`, which returns a _Slice_.\n- A new subroutine is declared by means of the phrase `NEWPROC <name>`. This declaration assigns the next positive integer as a selector for the newly-declared subroutine, and stores this integer into the constant `<name>`. For instance, the above declarations define `add`, `sub`, and `mul` as integer constants equal to 1, 2, and 3, respectively.\n- Some subroutines are pre-declared and do not need to be declared again by `NEWPROC`. For instance, main is a subroutine identifier bound to the integer constant (selector) 0.\n- Other predefined subroutine selectors such as `recv_internal` (equal to 0) or `recv_external` (equal to −1), useful for implementing TON Blockchain smart contracts, can be declared by means of constant (e.g., `-1 constant recv_external`).\n- A subroutine can be defined either with the aid of the word `PROC`, which accepts the integer selector of the subroutine and the _Slice_ containing the code for this subroutine, or with the aid of the construct selector `PROC:<{ ... }>`, convenient for defining larger subroutines.\n- `CALLDICT` and `JMPDICT` instructions may be assembled with the aid of the words `CALL` and `JMP`, which accept the integer selector of the subroutine to be called as an immediate argument passed in the Fift stack.\n- The current implementation of the Fift assembler collects all subroutines into a dictionary with 14-bit signed integer keys. Therefore, all subroutine selectors must be in the range $−2^{13} ... 2^{13 − 1}$.\n- If a subroutine with an unknown selector is called during runtime, an exception with code 11 is thrown by the code automatically inserted by the Fift assembler. This code also automatically selects codepage zero for instruction encoding by means of a `SETCP0` instruction.\n- The Fift assembler checks that all subroutines declared by `NEWPROC` are actually defined by `PROC` or `PROC:<{` before the end of the program. It also checks that a subroutine is not redefined.\n\nOne should bear in mind that very simple programs (including the simplest smart contracts) may be made more compact by eliminating this general subroutine selection machinery in favor of custom subroutine selection code and removing unused subroutines. For instance, the above example can be transformed into\n\n```fift\n<{ 11 THROWIF\n   CONT:<{ s3 s1 PUSH2 MUL s3 s1 PUSH2 MUL SUB\n           s4 s4 XCHG2 MUL -ROT MUL ADD }>\n   5 INT 1 INT 2DUP s4 PUSH CALLX\n   2DUP s4 PUSH CALLX\n   ROT 239 INT -1 INT ROT JMPX\n}>s\ndup csr.\nrunvmdict .s\n```\n\nwhich produces\n\n```fift\nx{F24B9D5331A85331A8A15044A859A8A075715C24D85C24D8588100EF7F58D9}\nimplicit PUSH 0 at start\nexecute THROWIF 11\nexecute PUSHCONT x5331A85331A8A15044A859A8A0\nexecute PUSHINT 5\nexecute PUSHINT 1\nexecute 2DUP\nexecute PUSH s4\nexecute EXECUTE\nexecute PUSH2 s3,s1\nexecute MUL\n// ...\nexecute XCHG2 s4,s4\nexecute MUL\nexecute ROTREV\nexecute MUL\nexecute ADD\nexecute implicit RET\n114244 114244 0\n```\n\n## References\n\n- L. Brodie, Starting Forth: Introduction to the FORTH Language and Operating System for Beginners and Professionals, 2nd edition, Prentice Hall, 1987. Available at https://www.forth.com/starting-forth/.\n- L. Brodie, Thinking Forth: A language and philosophy for solving problems, Prentice Hall, 1984. Available at http://thinking-forth.sourceforge.net/.\n- N. Durov, Telegram Open Network, 2017.\n- N. Durov, Telegram Open Network Virtual Machine, 2018.\n- N. Durov, Telegram Open Network Blockchain, 2018.\n\n## Appendix A: List of Fift words\n\nThis Appendix provides an alphabetic list of almost all Fift words—including primitives and definitions from the standard library `Fift.fif`, but excluding Fift assembler words defined in `Asm.fif` (because the Fift assembler is simply an application from the perspective of Fift). Some experimental words have been omitted from this list. Other words may have been added to or removed from Fift after this text was written. The list of all words available in your Fift interpreter may be inspected by executing `words`.\n\nEach word is described by its name, followed by its _stack notation_ in parentheses, indicating several values near the top of the Fift stack before and after the execution of the word; all deeper stack entries are usually assumed to be left intact. After that, a text description of the word's effect is provided. If the word has been discussed in a previous section of this document, a reference to this section is included.\n\nActive words and active prefix words that parse a portion of the input stream immediately after their occurrence are listed here in a modified way.\n\nFirstly, these words are listed alongside the portion of the input that they parse; the segment of each entry that is actually an emphasized Fift word.\n\nSecondly, their stack effect is usually described from the user's perspective, and reflects the actions performed during the execution phase of the encompassing blocks and word definitions.\n\nFor example, the active prefix word `B{`, used for defining _Bytes_ literals, is listed as `B{<hex-digits>}`, and its stack effect is shown as `( – B)` instead of `( – B 1 e)`, even though the real effect of the execution of the active word `B{` during the compilation phase of an encompassing block or word definition is the latter one.\n\n<Aside>\n\n  If the column contents of the table do not fit the screen, **scroll horizontally**.\n\n</Aside>\n\n| Word | Stack | Description\n| :--- | :---- | :----------\n| **`!`** | _`(x p – )`_ | stores new value `x` into _Box_ `p`.\n| **`\"string\"`** | _`( – S)`_ | pushes a _String_ literal into the stack.\n| **`#`** | _`(x S – x' S')`_ | performs one step of the conversion of _Integer_ `x` into its decimal representation by appending to _String_ `S` one decimal digit representing `x mod 10`. The quotient $x' := \\lfloor \\frac{x}{10} \\rfloor$ is returned as well.\n| **`#>`** | _`(S – S')`_ | finishes the conversion of an _Integer_ into its human-readable representation (decimal or otherwise) started with `<#` by reversing _String_ `S`. Equivalent to `$reverse`.\n| **`#s`** | _`(x S – x' S')`_ | performs `#` one or more times until the quotient `x'` becomes non-positive. Equivalent to `{ # over 0<= } until`.\n| **`$#`** | _`( – x)`_ | pushes the total number of command-line arguments passed to the Fift program. Defined only when the Fift interpreter is invoked in script mode (with the -s command line argument).\n| **`$(<string>)`** | _`( – ... )`_ | looks up the word `$<string>` during execution time and executes its current definition. Typically used to access the current values of command-line arguments, e.g., `$(2)` is essentially equivalent to `@' $2`.\n| **`$()`** | _`(x – S)`_ | pushes the `x`-th command-line argument similarly to `$n`, but with _Integer_ `x` ≥ 0 taken from the stack. Defined only when the Fift interpreter is invoked in script mode (with the -s command line argument).\n| **`$+`** | _`(S S0 – S.S0 )`_ | concatenates two strings.\n| **`$,`** | _`(b S – b 0 )`_ | appends _String_ `S` to _Builder_ `b`. The string is interpreted as a binary string of length $8 * n$, where `n` is the number of bytes in the UTF-8 representation of `S`.\n| **`$n`** | _`( – S)`_ | pushes the `n`-th command-line argument as a _String_ `S`. For instance, `$0` pushes the name of the script being executed, `$1` the first command line argument, and so on. Defined only when the Fift interpreter is invoked in script mode (with the -s command line argument).\n| **`$=`** | _`(S S' – ?)`_ | returns −1 if strings `S` and `S'` are equal, 0 otherwise. Equivalent to `$cmp 0=`.\n| **`$>s`** | _`(S – s)`_ | transforms the _String_ `S` into a _Slice_. Equivalent to `<b swap $, b> <s`.\n| **`$>smca`** | _`(S – x y z −1 or 0)`_ | unpacks a standard TON smart-contract address from its human-readable string representation `S`. On success, returns the signed 32-bit workchain `x`, the unsigned 256-bit in-workchain address `y`, the flags `z` (where +1 means that the address is non-bounceable, +2 that the address is testnet-only), and −1. On failure, pushes 0.\n| **`$@`** | _`(s x – S)`_ | fetches the first `x` bytes (i.e., 8x bits) from _Slice_ `s`, and returns them as a UTF-8 _String_ `S`. If there are not enough data bits in `s`, throws an exception.\n| **`$@+`** | _`(s x – S s0 )`_ | similar to `$@`, but returns the remainder of _Slice_ `s` as well.\n| **`$@?`** | _`(s x – S −1 or 0)`_ | similar to `$@`, but uses a flag to indicate failure instead of throwing an exception.\n| **`$@?+`** | _`(s x – S s0 −1 or s 0)`_ | similar to `$@+`, but uses a flag to indicate failure instead of throwing an exception.\n| **`$cmp`** | _`(S S0 – x)`_ | returns 0 if strings `S` and S0 are equal, −1 if `S` is lexicographically less than S0, and 1 if `S` is lexicographically greater than S0.\n| **`$len`** | _`(S – x)`_ | computes the byte length (not the UTF-8 character length!) of a string.\n| **`$reverse`** | _`(S – S 0 )`_ | reverses the order of UTF-8 characters in _String_ `S`. If `S` is not a valid UTF-8 string, the return value is undefined and may be also invalid.\n| **`%1<<`** | _`(x y – z)`_ | computes $z := x mod 2^y = x&(2^y − 1)$ for two _Integer_'s `x` and $0 ≤ y ≤ 256$.\n| **`' <word-name>`** | _`( – e)`_ | returns the execution token equal to the current (compile-time) definition of `<word-name>`. If the specified word is not found, throws an exception.\n| **`'nop`** | _`( – e)`_ | pushes the default definition of nop—an execution token that does nothing when executed.\n| **`(') <word-name>`** | _`( – e)`_ | similar to `'`, but returns the definition of the specified word at execution time, performing a dictionary lookup each time it is invoked. May be used to recover the current values of constants inside word definitions and other blocks by using the phrase `(') <word-name> execute`.\n| **`(-trailing)`** | _`(S x – S 0 )`_ | removes from _String_ `S` all trailing characters with UTF-8 codepoint `x`.\n| **`(.)`** | _`(x – S)`_ | returns the _String_ with the decimal representation of _Integer_ `x`. Equivalent to `dup abs <# #s rot sign #> nip`.\n| **`(atom)`** | _`(S x – a −1 or 0)`_ | returns the only _Atom_ `a` with the name given by _String_ `S`. If there is no such _Atom_ yet, either creates it (if _Integer_ `x` is non-zero) or returns a single zero to indicate failure (if `x` is zero).\n| **`(b.)`** | _`(x – S)`_ | returns the _String_ with the binary representation of _Integer_ `x`.\n| **`(compile)`** | _`(l x1 ... xn n e – l 0 )`_ | extends _WordList_ `l` so that it would push `0 ≤ n ≤ 255` values `x1, ... , xn` into the stack and execute the execution token `e` when invoked, where `0 ≤ n ≤ 255` is an _Integer_. If `e` is equal to the special value `'nop`, the last step is omitted.\n| **`(create)`** | _`(e S x – )`_ | creates a new word with the name equal to _String_ `S` and definition equal to _WordDef_ `e`, using flags passed in _Integer_ `0 ≤ x ≤ 3`. If bit +1 is set in `x`, creates an active word; if bit +2 is set in `x`, creates a prefix word.\n| **`(def?)`** | _`(S – ?)`_ | checks whether the word `S` is defined.\n| **`(dump)`** | _`(x – S)`_ | returns a _String_ with a dump of the topmost stack value `x`, in the same format as employed by `.dump`.\n| **`(execute)`** | _`(x1 ... xn n e – ...)`_ | executes execution token `e`, but first checks that there are at least `0 ≤ n ≤ 255` values in the stack apart from `n` and `e` themselves. It is a counterpart of `(compile)` that may be used to immediately \"execute\" (perform the intended runtime action of) an active word after its immediate execution.\n| **`(forget)`** | _`(S – )`_ | forgets the word with the name specified in _String_ `S`. If the word is not found, throws an exception.\n| **`(number)`** | _`(S – 0 or x 1 or x y 2)`_ | attempts to parse the _String_ `S` as an integer or fractional literal. On failure, returns a single 0. On success, returns `x 1` if `S` is a valid integer literal with value `x`, or `x y 2` if `S` is a valid fractional literal with value x/y.\n| **`(x.)`** | _`(x – S)`_ | returns the _String_ with the hexadecimal representation of _Integer_ `x`.\n| **`({)`** | _`( – l)`_ | pushes an empty _WordList_ into the stack.\n| **`(})`** | _`(l – e)`_ | transforms a _WordList_ into an execution token (_WordDef_), making all further modifications impossible.\n| **`*`** | _`(x y – xy)`_ | computes the product `xy` of two _Integer_'s `x` and `y`.\n| **`*/`** | _`(x y z – floor(xy/z))`_ | \"multiply-then-divide\": multiplies two integers `x` and `y` producing a 513-bit intermediate result, then divides the product by `z`.\n| **`*/c`** | _`(x y z – ceil(xy/z))`_ | \"multiply-then-divide\" with ceiling rounding: multiplies two integers `x` and `y` producing a 513-bit intermediate result, then divides the product by `z`.\n| **`*/cmod`** | _`(x y z – q r)`_ | similar to `*/c`, but computes both the quotient $q := \\lceil \\frac{xy}{z} \\rceil$ and the remainder $r := xy − qz$.\n| **`*/mod`** | _`(x y z – q r)`_ | similar to `*/`, but computes both the quotient $q := \\lfloor \\frac{xy}{z} \\rfloor$ and the remainder $r := xy − qz$.\n| **`*/r`** | _`(x y z – q := floor(xy/z + 1/2))`_ | \"multiply-then-divide\" with nearest-integer rounding: multiplies two integers `x` and `y` with 513-bit intermediate result, then divides the product by `z`.\n| **`*/rmod`** | _`(x y z – q r)`_ | similar to `*/r`, but computes both the quotient $q := \\lfloor \\frac{xy}{z} + 1/2 \\rfloor$ and the remainder $r := xy − qz$.\n| **`*>>`** | _`(x y z – q)`_ | similar to `*/`, but with division replaced with a right shift. Computes $q := \\lfloor \\frac{xy}{2^z} \\rfloor$ for $0 ≤ z ≤ 256$. Equivalent to `1<< */`.\n| **`*>>c`** | _`(x y z – q)`_ | similar to `*/c`, but with division replaced with a right shift. Computes $q := \\lceil \\frac{xy}{2^z} \\rceil$ for $0 ≤ z ≤ 256$. Equivalent to `1<< */c`.\n| **`*>>r`** | _`(x y z – q)`_ | similar to `*/r`, but with division replaced with a right shift. Computes $q := \\lfloor \\frac{xy}{2^z} + 1/2 \\rfloor$ for $0 ≤ z ≤ 256$. Equivalent to `1<< */r`.\n| **`*mod`** | _`(x y z – r)`_ | similar to `*/mod`, but computes only the remainder $r := xy − qz$, where $q := \\lfloor \\frac{xy}{z} \\rfloor$. Equivalent to `*/mod nip`.\n| **`+`** | _`(x y – x+y)`_ | computes the sum x+y of two _Integer_'s `x` and `y`.\n| **`+!`** | _`(x p – )`_ | increases the integer value stored in _Box_ `p` by _Integer_ `x`. Equivalent to `tuck @ + swap !`.\n| **`+\"string\"`** | _`(S – S0)`_ | concatenates _String_ `S` with a string literal. Equivalent to `\"string\" $+`.\n| **`,`** | _`(t x – t')`_ | appends `x` to the end of _Tuple_ `t`, and returns the resulting _Tuple_ `t'`.\n| **`-`** | _`(x y – x − y)`_ | computes the difference `x − y` of two _Integer_'s `x` and `y`.\n| **`-!`** | _`(x p – )`_ | decreases the integer value stored in _Box_ `p` by _Integer_ `x`. Equivalent to `swap negate swap +!`.\n| **`-1`** | _`( – −1)`_ | pushes _Integer_ −1.\n| **`-1<<`** | _`(x – −2 x )`_ | computes $−2^x$ for $0 ≤ x ≤ 256$. Approximately equivalent to `1<< negate` or `-1 swap <<`, but works for $x = 256$ as well.\n| **`-roll`** | _`(xn ... x0 n – x0 xn ... x1)`_ | rotates the top `n` stack entries in the opposite direction, where `n ≥ 0` is also passed in the stack. In particular, `1 -roll` is equivalent to `swap`, and `2 -roll` to `-rot`.\n| **`-rot`** | _`(x y z – z x y)`_ | rotates the three topmost stack entries in the opposite direction. Equivalent to `rot rot`.\n| **`-trailing`** | _`(S – S 0 )`_ | removes from _String_ `S` all trailing spaces. Equivalent to `bl (-trailing)`.\n| **`-trailing0`** | _`(S – S 0 )`_ | removes from _String_ `S` all trailing `0` characters. Equivalent to `char 0 (-trailing)`.\n| **`.`** | _`(x – )`_ | prints the decimal representation of _Integer_ `x`, followed by a single space. Equivalent to `._ space`.\n| **`.\"string\"`** | _`( – )`_ | prints a constant string into the standard output.\n| **`._`** | _`(x – )`_ | prints the decimal representation of _Integer_ `x` without any spaces. Equivalent to `(.) type`.\n| **`.dump`** | _`(x – )`_ | dumps the topmost stack entry in the same way as .s dumps all stack elements. Equivalent to `(dump) type space`.\n| **`.l`** | _`(l – )`_ | prints a Lisp-style list `l`.\n| **`.s`** | _`( – )`_ | dumps all stack entries starting from the deepest, leaving them intact. Human-readable representations of stack entries are output separated by spaces, followed by an end-of-line character.\n| **`.sl`** | _`( – )`_ | dumps all stack entries leaving them intact similarly to `.s`, but showing each entry as a List-style list `l` as `.l` does.\n| **`.tc`** | _`( – )`_ | outputs the total number of allocated cells into the standard error stream.\n| **`/`** | _`(x y – q := bx/yc)`_ | computes the floor-rounded quotient bx/yc of two _Integer_'s.\n| **`/* multiline-comment */`** | _`( – )`_ | skips a multi-line comment delimited by word \"*/\" (followed by a blank or an end-of-line character).\n| **`// comment-to-eol`** | _`( – )`_ | skips a single-line comment until the end of the current line.\n| **`/c`** | _`(x y – q := ceil(x/y))`_ | computes the ceiling-rounded quotient $\\lceil x/y \\rceil$ of two _Integer_'s.\n| **`/cmod`** | _`(x y – q r)`_ | computes both the ceiling-rounded quotient $q := \\lceil x/y \\rceil$ and the remainder $r := x − qy$.\n| **`/mod`** | _`(x y – q r)`_ | computes both the floor-rounded quotient $q := \\lfloor x/y \\rfloor$ and the remainder $r := x − qy$.\n| **`/r`** | _`(x y – q)`_ | computes the nearest-integer-rounded quotient $\\lfloor x/y + 1/2 \\rfloor$ of two _Integer_'s.\n| **`/rmod`** | _`(x y – q r)`_ | computes both the nearest-integer-rounded quotient $\\lfloor x/y + 1/2 \\rfloor$ and the remainder $r := x − qy$.\n| **`0`** | _`( – 0)`_ | pushes _Integer_ `0`.\n| **`0!`** | _`(p – )`_ | stores _Integer_ `0` into _Box_ `p`. Equivalent to `0 swap !`.\n| **`0<`** | _`(x – ?)`_ | checks whether $x < 0$ (i.e., pushes −1 if `x` is negative, 0 otherwise). Equivalent to `0 <`.\n| **`0<=`** | _`(x – ?)`_ | checks whether $x ≤ 0$ (i.e., pushes −1 if `x` is non-positive, 0 otherwise). Equivalent to `0 <=`.\n| **`0<>`** | _`(x – ?)`_ | checks whether $x ≠ 0$ (i.e., pushes −1 if `x` is non-zero, 0 otherwise). Equivalent to `0 <>`.\n| **`0=`** | _`(x – ?)`_ | checks whether $x = 0$ (i.e., pushes −1 if `x` is zero, 0 otherwise). Equivalent to `0 =`.\n| **`0>`** | _`(x – ?)`_ | checks whether $x > 0$ (i.e., pushes −1 if `x` is positive, 0 otherwise). Equivalent to `0 >`.\n| **`0>=`** | _`(x – ?)`_ | checks whether $x ≥ 0$ (i.e., pushes −1 if `x` is non-negative, 0 otherwise). Equivalent to `0 >=`.\n| **`1`** | _`( – 1)`_ | pushes _Integer_ 1.\n| **`1+`** | _`(x – x + 1)`_ | computes $x + 1$. Equivalent to `1 +`.\n| **`1+!`** | _`(p – )`_ | increases the integer value stored in _Box_ `p` by one. Equivalent to `1 swap +!`.\n| **`1-`** | _`(x – x − 1)`_ | computes $x − 1$. Equivalent to `1 -`.\n| **`1-!`** | _`(p – )`_ | decreases the integer value stored in _Box_ `p` by one. Equivalent to `-1 swap +!`.\n| **`1<<`** | _`(x – 2 x )`_ | computes $2^x$ for $0 ≤ x ≤ 255$. Equivalent to `1 swap <<`.\n| **`1<<1-`** | _`(x – 2 x−1)`_ | computes $2^{x}−1$ for $0 ≤ x ≤ 256$. Almost equivalent to `1<< 1-`, but works for $x = 256$.\n| **`2`** | _`( – 2)`_ | pushes _Integer_ 2.\n| **`2*`** | _`(x – 2x)`_ | computes $2x$. Equivalent to `2 *`.\n| **`2+`** | _`(x – x + 2)`_ | computes $x + 2$. Equivalent to `2 +`.\n| **`2-`** | _`(x – x − 2)`_ | computes $x − 2$. Equivalent to `2 -`.\n| **`2/`** | _`(x – floor(x/2))`_ | computes $\\lfloor \\frac{x}{2} \\rfloor$. Equivalent to `2 /` or to `1 >>`.\n| **`2=: <word-name>`** | _`(x y – )`_ | an active variant of 2constant: defines a new ordinary word `<word-name>` that would push the given values `x` and `y` when invoked.\n| **`2constant`** | _`(x y – )`_ | scans a blank-delimited word name `S` from the remainder of the input, and defines a new ordinary word `S` as a double constant, which will push the given values `x` and `y` (of arbitrary types) when invoked.\n| **`2drop`** | _`(x y – )`_ | removes the two topmost stack entries. Equivalent to `drop drop`.\n| **`2dup`** | _`(x y – x y x y)`_ | duplicates the topmost pair of stack entries. Equivalent to `over over`.\n| **`2over`** | _`(x y z w – x y z w x y)`_ | duplicates the second topmost pair of stack entries.\n| **`2swap`** | _`(a b c d – c d a b)`_ | interchanges the two topmost pairs of stack entries.\n| **`: <word-name>`** | _`(e – )`_ | defines a new ordinary word `<word-name>` in the dictionary using _WordDef_ e as its definition. If the specified word is already present in the dictionary, it is tacitly redefined.\n| **`:: <word-name>`** | _`(e – )`_ | defines a new active word `<word-name>` in the dictionary using _WordDef_ e as its definition. If the specified word is already present in the dictionary, it is tacitly redefined.\n| **`::_ <word-name>`** | _`(e – )`_ | defines a new active prefix word `<word-name>` in the dictionary using _WordDef_ `e` as its definition. If the specified word is already present in the dictionary, it is tacitly redefined.\n| **`:_ <word-name>`** | _`(e – )`_ | defines a new ordinary prefix word `<word-name>` in the dictionary using _WordDef_ `e` as its definition. If the specified word is already present in the dictionary, it is tacitly redefined.\n| **`<`** | _`(x y – ?)`_ | checks whether $x < y$ (i.e., pushes −1 if _Integer_ `x` is less than _Integer_ `y`, 0 otherwise).\n| **`<#`** | _`( – S)`_ | pushes an empty _String_. Typically used for starting the conversion of an _Integer_ into its human-readable representation, decimal or in another base. Equivalent to `\"\"`.\n| **`<<`** | _`(x y – x · 2^y)`_ | computes an arithmetic left shift of binary number `x` by `y ≥ 0` positions, yielding $x * 2^y$.\n| **`<</`** | _`(x y z – q)`_ | computes $q := \\lfloor \\frac{2^{z}*x}{y} \\rfloor$ for $0 ≤ z ≤ 256$ producing a 513-bit intermediate result, similarly to `*/`. Equivalent to `1<< swap */`\n| **`<</c`** | _`(x y z – q)`_ | computes $q := \\lceil \\frac{2^{z}*x}{y} \\rceil$ for $0 ≤ z ≤ 256$ producing a 513-bit intermediate result, similarly to `*/c`. Equivalent to `1<< swap */c`\n| **`<</r`** | _`(x y z – q)`_ | computes $q := \\lfloor \\frac{2^{z}*x}{y} + 1/2 \\rfloor$ for $0 ≤ z ≤ 256$ producing a 513-bit intermediate result, similarly to `*/`. Equivalent to `1<< swap */r`\n| **`<`** | _`(x y – ?)`_ | checks whether $x <= y$ (i.e., pushes −1 if Integers `x` and `y` are not equal, 0 otherwise).\n| **`>`** | _`(x y – ?)`_ | checks whether $x > y$ (i.e., pushes −1 if _Integer_ `x` is greater than _Integer_ `y`, 0 otherwise).\n| **`<>`** | _`(x y – ?)`_ | checks whether $x ≠ y$ (i.e., pushes −1 if Integers `x` and `y` are not equal, 0 otherwise).\n| **`>=`** | _`(x y – ?)`_ | checks whether $x ≥ y$ (i.e., pushes −1 if _Integer_ `x` is greater than or equal to _Integer_ `y`, 0 otherwise).\n| **`>>`** | _`(x y – q := bx · 2 −y c)`_ | computes an arithmetic right shift of binary number `x` by 0 ≤ y ≤ 256 positions. Equivalent to `1<< /`.\n| **`>>c`** | _`(x y – q := dx · 2 −y e)`_ | computes the ceiling-rounded quotient `q` of `x` by $2^y$ for $0 ≤ y ≤ 256$. Equivalent to `1<< /c`.\n| **`>>r`** | _`(x y – q := bx · 2 −y + 1/2c)`_ | computes the nearest-integer-rounded quotient `q` of `x` by $2^y$ for $0 ≤ y ≤ 256$. Equivalent to `1<< /r`.\n| **`?dup`** | _`(x – x x or 0)`_ | duplicates an _Integer_ `x`, but only if it is non-zero. Otherwise leaves it intact.\n| **`@`** | _`(p – x)`_ | fetches the value currently stored in _Box_ `p`.\n| **`@' <word-name>`** | _`( – e)`_ | recovers the definition of the specified word at execution time, performing a dictionary lookup each time it is invoked, and then executes this definition. May be used to recover current values of constants inside word definitions and other blocks by using the phrase `@' <word-name>`, equivalent to `(') <word-name> execute`.\n| **`B+`** | _`(B' B'' – B)`_ | concatenates two _Bytes_ values.\n| **`B,`** | _`(b B – b')`_ | appends _Bytes_ `B` to _Builder_ `b`. If there is no room in `b` for `B`, throws an exception.\n| **`B=`** | _`(B B0 – ?)`_ | checks whether two _Bytes_ sequences are equal, and returns −1 or 0 depending on the comparison outcome.\n| **`B>Li@`** | _`(B x – y)`_ | deserializes the first `x / 8` bytes of a _Bytes_ value `B` as a signed little-endian `x`-bit _Integer_ `y`.\n| **`B>Li@+`** | _`(B x – B' y)`_ | deserializes the first `x / 8` bytes of `B` as a signed little-endian `x`-bit _Integer_ `y` similarly to `B>Li@`, but also returns the remaining bytes of `B`.\n| **`B>Lu@`** | _`(B x – y)`_ | deserializes the first `x / 8` bytes of a _Bytes_ value `B` as an unsigned little-endian `x`-bit _Integer_ `y`.\n| **`B>Lu@+`** | _`(B x – B' y)`_ | deserializes the first `x / 8` bytes of `B` as an unsigned little-endian `x`-bit _Integer_ `y` similarly to `B>Lu@`, but also returns the remaining bytes of `B`.\n| **`B>boc`** | _`(B – c)`_ | deserializes a \"standard\" _bag of cells_ (i.e., a _bag of cells_ with exactly one root cell) represented by _Bytes_ `B`, and returns the root _Cell_ `c`.\n| **`B>file`** | _`(B S – )`_ | creates a new (binary) file with the name specified in _String_ `S` and writes data from _Bytes_ `B` into the new file. If the specified file already exists, it is overwritten.\n| **`B>i@`** | _`(B x – y)`_ | deserializes the first `x / 8` bytes of a _Bytes_ value `B` as a signed big-endian `x`-bit _Integer_ `y`.\n| **`B>i@+`** | _`(B x – B' y)`_ | deserializes the first `x / 8` bytes of `B` as a signed big-endian `x`-bit _Integer_ `y` similarly to `B>i@`, but also returns the remaining bytes of `B`.\n| **`B>u@`** | _`(B x – y)`_ | deserializes the first `x / 8` bytes of a _Bytes_ value `B` as an unsigned big-endian `x`-bit _Integer_ `y`.\n| **`B>u@+`** | _`(B x – B' y)`_ | deserializes the first `x / 8` bytes of `B` as an unsigned big-endian `x`-bit _Integer_ `y` similarly to `B>u@`, but also returns the remaining bytes of `B`.\n| **`B@`** | _`(s x – B)`_ | fetches the first `x` bytes (i.e., $8 * x$ bits) from _Slice_ `s`, and returns them as a _Bytes_ value `B`. If there are not enough data bits in `s`, throws an exception.\n| **`B@+`** | _`(s x – B s0 )`_ | similar to `B@`, but returns the remainder of _Slice_ `s` as well.\n| **`B@?`** | _`(s x – B −1 or 0)`_ | similar to `B@`, but uses a flag to indicate failure instead of throwing an exception.\n| **`B@?+`** | _`(s x – B s0 −1 or s 0)`_ | similar to `B@+`, but uses a flag to indicate failure instead of throwing an exception.\n| **`Bcmp`** | _`(B B' – x)`_ | lexicographically compares two _Bytes_ sequences, and returns −1, 0, or 1, depending on the comparison result.\n| **`Bhash`** | _`(B – B')`_ | computes the sha256 hash of a _Bytes_ value. The hash is returned as a 32-byte _Bytes_ value.\n| **`Blen`** | _`(B – x)`_ | returns the length of a _Bytes_ value `B` in bytes.\n| **`Bx.`** | _`(B – )`_ | prints the hexadecimal representation of a _Bytes_ value. Each byte is represented by exactly two uppercase hexadecimal digits.\n| **`B{hex-digits}`** | _`( – B)`_ | pushes a _Bytes_ literal containing data represented by an even number of hexadecimal digits.\n| **`B\\|`** | _`(B x – B' B'')`_ | cuts the first `x` bytes from a _Bytes_ value `B`, and returns both the first `x` bytes (`B'`) and the remainder (`B''`) as new _Bytes_ values.\n| **`Li>B`** | _`(x y – B)`_ | stores a signed little-endian `y`-bit _Integer_ `x` into a _Bytes_ value `B` consisting of exactly `y / 8` bytes. _Integer_ `y` must be a multiple of eight in the range $0 ... 256$.\n| **`Lu>B`** | _`(x y – B)`_ | stores an unsigned little-endian `y`-bit _Integer_ `x` into a _Bytes_ value `B` consisting of exactly `y / 8` bytes. _Integer_ `y` must be a multiple of eight in the range $0 ... 256$.\n| **`[`** | _`( – )`_ | opens an internal interpreter session even if state is greater than zero, i.e., all subsequent words are executed immediately instead of being compiled.\n| **`[]`** | _`(t i – x)`_ | returns the ($i + 1$)-st component $t_{i+1}$ of _Tuple_ `t`, where $0 ≤ i < \\|t\\|$.\n| **`[compile] <word-name>`** | _`( – )`_ | compiles `<word-name>` as if it were an ordinary word, even if it is active. Essentially equivalent to `' <word-name> execute`.\n| **`]`** | _`(x1 ... xn n – )`_ | closes an internal interpreter session opened by [ and invokes (compile) or (execute) afterwards depending on whether state is greater than zero. For instance, `{ [ 2 3 + 1 ] * }` is equivalent to `{ 5 * }`.\n| **`'<word>`** | _`( – a)`_ | introduces an _Atom_ literal, equal to the only _Atom_ with the name equal to `<word>`. Equivalent to `\"<word>\"` atom.\n| **`abort`** | _`(S – )`_ | throws an exception with an error message taken from _String_ `S`.\n| **`abort\"<message>\"`** | _`(x – )`_ | throws an exception with the error message `\"<message>\"` if the _Integer_ `x` is non-zero.\n| **`abs`** | _`(x – \\|x\\|)`_ | computes the absolute value `\\|x\\| = max(x, −x)` of _Integer_ `x`. Equivalent to `dup negate max`.\n| **`allot`** | _`(n – t)`_ | creates a new array, i.e., a _Tuple_ that consists of `n` new empty _Box_'es. Equivalent to `\\| { hole , } rot times`.\n| **`and`** | _`(x y – x&y)`_ | computes the bitwise AND of two _Integer_'s.\n| **`anon`** | _`( – a)`_ | creates a new unique anonymous _Atom_.\n| **`atom`** | _`(S – a)`_ | returns the only _Atom_ `a` with the name `S`, creating such an atom if necessary. Equivalent to `true (atom) drop`.\n| **`atom?`** | _`(u – ?)`_ | checks whether `u` is an _Atom_.\n| **`b+`** | _`(b b' – b'')`_ | concatenates two _Builder_'s `b` and `b'`.\n| **`b.`** | _`(x – )`_ | prints the binary representation of an _Integer_ `x`, followed by a single space. Equivalent to `b._ space`.\n| **`b._`** | _`(x – )`_ | prints the binary representation of an _Integer_ `x` without any spaces. Equivalent to `(b.) type`.\n| **`b>`** | _`(b – c)`_ | transforms a _Builder_ `b` into a new _Cell_ `c` containing the same data as `b`.\n| **`b>idict!`** | _`(v x s n – s' −1 or s 0)`_ | adds a new value `v` (represented by a _Builder_) with key given by signed big-endian `n`-bit integer `x` into dictionary `s` with `n`-bit keys, and returns the new dictionary `s'` and −1 on success. Otherwise the unchanged dictionary `s` and 0 are returned.\n| **`b>idict!+`** | _`(v x s n – s' −1 or s 0)`_ | adds a new key-value pair `(x, v)` into dictionary `s` similarly to `b>idict!`, but fails if the key already exists by returning the unchanged dictionary `s` and 0.\n| **`b>udict!`** | _`(v x s n – s' −1 or s 0)`_ | adds a new value `v` (represented by a _Builder_) with key given by unsigned big-endian `n`-bit integer `x` into dictionary `s` with `n`-bit keys, and returns the new dictionary `s'` and −1 on success. Otherwise the unchanged dictionary `s` and 0 are returned.\n| **`b>udict!+`** | _`(v x s n – s' −1 or s 0)`_ | adds a new key-value pair `(x, v)` into dictionary `s` similarly to `b>udict!`, but fails if the key already exists by returning the unchanged dictionary `s` and `0`.\n| **`bbitrefs`** | _`(b – x y)`_ | returns both the number of data bits `x` and the number of references `y` already stored in _Builder_ `b`.\n| **`bbits`** | _`(b – x)`_ | returns the number of data bits already stored in _Builder_ `b`. The result `x` is an _Integer_ in the range $0 ... 1023$.\n| **`bl`** | _`( – x)`_ | pushes the Unicode codepoint of a space, i.e., 32.\n| **`boc+>B`** | _`(c x – B)`_ | creates and serializes a standard _bag of cells_, containing one root _Cell_ `c` along with all its descendants. An _Integer_ parameter `0 ≤ x ≤ 31` is used to pass flags indicating the additional options for bag-of-cells serialization, with individual bits having the following effect:<br/><br/>  – **`+1`** enables bag-of-cells index creation (useful for lazy deserialization of large bags of cells).<br/>  – **`+2`** includes the CRC32-C of all data into the serialization (useful for checking data integrity).<br/>  – **`+4`** explicitly stores the hash of the root cell into the serialization (so that it can be quickly recovered afterwards without a complete deserialization).<br/>  – **`+8`** stores hashes of some intermediate (non-leaf) cells (useful for lazy deserialization of large bags of cells).<br/>  – **`+16`** stores cell cache bits to control caching of deserialized cells.<br/><br/>Typical values of `x` are `x = 0` or `x = 2` for very small bags of cells (e.g., TON Blockchain external messages) and `x = 31` for large bags of cells (e.g., TON Blockchain blocks).\n| **`boc>B`** | _`(c – B)`_ | serializes a small \"standard\" _bag of cells_ with root _Cell_ `c` and all its descendants. Equivalent to `0 boc+>B`.\n| **`box`** | _`(x – p)`_ | creates a new _Box_ containing specified value `x`. Equivalent to `hole tuck !`.\n| **`brefs`** | _`(b – x)`_ | returns the number of references already stored in _Builder_ `b`. The result `x` is an _Integer_ in the range $0 ... 4$.\n| **`brembitrefs`** | _`(b – x y)`_ | returns both the maximum number of additional data bits `0 ≤ x ≤ 1023` and the maximum number of additional cell references `0 ≤ y ≤ 4` that can be stored in _Builder_ `b`.\n| **`brembits`** | _`(b – x)`_ | returns the maximum number of additional data bits that can be stored in _Builder_ `b`. Equivalent to `bbits 1023 swap -`.\n| **`bremrefs`** | _`(b – x)`_ | returns the maximum number of additional cell references that can be stored in _Builder_ `b`.\n| **`bye`** | _`( – )`_ | quits the Fift interpreter to the operating system with a zero exit code. Equivalent to `0 halt`.\n| **`b{<binary-data>}`** | _`( – s)`_ | creates a _Slice_ `s` that contains no references and up to 1023 data bits specified in `<binary-data>`, which must be a string consisting only of the characters '0' and '1'.\n| **`caddr`** | _`(l – h'')`_ | returns the third element of a list. Equivalent to `cddr car`.\n| **`cadr`** | _`(l – h')`_ | returns the second element of a list. Equivalent to `cdr car`.\n| **`car`** | _`(l – h)`_ | returns the head of a list. Equivalent to `first`.\n| **`cddr`** | _`(l – t')`_ | returns the tail of the tail of a list. Equivalent to `cdr cdr`.\n| **`cdr`** | _`(l – t)`_ | returns the tail of a list. Equivalent to `second`.\n| **`char <string>`** | _`( – x)`_ | pushes an _Integer_ with the Unicode codepoint of the first character of `<string>`. For instance, `char *` is equivalent to `42`.\n| **`chr`** | _`(x – S)`_ | returns a new _String_ `S` consisting of one UTF-8 encoded character with Unicode codepoint `x`.\n| **`cmp`** | _`(x y – z)`_ | compares two _Integer_'s `x` and `y`, and pushes 1 if $x > y$, −1 if $x < y$, and 0 if $x = y$. Approximately equivalent to `- sgn`.\n| **`cond`** | _`(x e e' – )`_ | if _Integer_ `x` is non-zero, executes `e`, otherwise executes `e'`.\n| **`cons`** | _`(h t – l)`_ | constructs a list from its head (first element) `h` and its tail (the list consisting of all remaining elements) `t`. Equivalent to `pair`.\n| **`constant`** | _`(x – )`_ | scans a blank-delimited word name `S` from the remainder of the input, and defines a new ordinary word `S` as a constant, which will push the given value `x` (of arbitrary type) when invoked.\n| **`count`** | _`(t – n)`_ | returns the length $n = \\|t\\|$ of _Tuple_ `t`.\n| **`cr`** | _`( – )`_ | outputs a carriage return (or a newline character) into the standard output.\n| **`create`** | _`(e – )`_ | defines a new ordinary word with the name equal to the next word scanned from the input, using _WordDef_ `e` as its definition. If the word already exists, it is tacitly redefined.\n| **`csr.`** | _`(s – )`_ | recursively prints a _Slice_ `s`. On the first line,  he data bits of `s` are displayed in hexadecimal form embedded into an `x{...}` construct similar to the one used for _Slice_ literals. On the next lines, the cells referred to by `s` are printed with larger indentation.\n| **`def? <word-name>`** | _`( – ?)`_ | checks whether the word `<word-name>` is defined at execution time, and returns −1 or 0 accordingly.\n| **`depth`** | _`( – n)`_ | returns the current depth (the total number of entries)  `f` the Fift stack as an _Integer_ `n ≥ 0`.\n| **`dictmap`** | _`(s n e – s')`_ | applies execution token `e` (i.e., an anonymous function) to each of the key-value pairs stored in a dictionary `s` with `n`-bit keys. The execution token is executed once for each key-value pair, with a _Builder_ `b` and a _Slice_ `v` (containing the value) pushed into the stack before executing `e`. After the execution `e` must leave in the stack either a modified _Builder_ `b'` (containing all data from `b` along with the new value `v'`) and −1, or 0 indicating failure. In the latter case, the corresponding key is omitted from the new dictionary.\n| **`dictmerge`** | _`(s s' n e – s'')`_ | combines two dictionaries `s` and `s'` with `n`-bit keys into one dictionary `s''` with the same keys. If a key is present in only one of the dictionaries `s` and `s'`, this key and the corresponding value are copied verbatim to the new dictionary `s''`. Otherwise the execution token (anonymous function) `e` is invoked to merge the two values `v` and `v'` corresponding to the same key `k` in `s` and `s'`, respectively. Before `e` is invoked, a _Builder_ `b` and two _Slice_'s `v` and `v` representing the two values to be merged are pushed. After the execution `e` leaves either a modified _Builder_ `b'` (containing the original data from `b` along with the combined value) and −1, or 0 on failure. In the latter case, the corresponding key is omitted from the new dictionary\n| **`dictnew`** | _`( – D)`_ | pushes the _Null_ that represents a new empty dictionary. Equivalent to `null`.\n| **`does`** | _`(x1 ... xn n e – e')`_ | creates a new execution token `e'` that would push n values `x1, ... , xn` into the stack and then execute `e` when invoked. It is roughly equivalent to a combination of `({)`,  `(compile)`, and `(})`.\n| **`drop`** | _`(x – )`_ | removes the top-of-stack entry.\n| **`dup`** | _`(x – x x)`_ | duplicates the top-of-stack entry. If the stack is empty, throws an exception.\n| **`ed25519_chksign`** | _`(B B' B'' – ?)`_ | checks whether `B'` is a valid Ed25519-signature of data `B` with the public key `B''`.\n| **`ed25519_sign`** | _`(B B' – B'')`_ | signs data `B` with the Ed25519 private key `B'` (a 32-byte _Bytes_ value) and returns the signature as a 64-byte _Bytes_ value `B''`.\n| **`ed25519_sign_uint`** | _`(x B' – B'')`_ | converts a big-endian unsigned 256-bit integer `x` into a 32-byte sequence and signs it using the Ed25519 private key `B'` similarly to `ed25519_sign`. Equivalent to `swap 256 u>B swap ed25519_sign`. The integer `x` to be signed is typically computed as the hash of some data.\n| **`emit`** | _`(x – )`_ | prints a UTF-8 encoded character with Unicode codepoint given by _Integer_ `x` into the standard output. For instance, `42 emit` prints an asterisk `\"*\"`, and `916 emit` prints a Greek Delta `\"∆\"`. Equivalent to `chr type`.\n| **`empty?`** | _`(s – ?)`_ | checks whether a _Slice_ is empty (i.e., has no data bits and no references left), and returns −1 or 0 accordingly.\n| **`eq?`** | _`(u v – ?)`_ | checks whether `u` and `v` are equal _Integer_ `s`, _Atom_'s, or _Null_'s. If they are not equal, or if they are of different types, or not of one of the types listed, returns zero.\n| **`exch`** | _`(xn ... x0 n – x0 ... xn)`_ | interchanges the top of the stack with the `n`-th stack entry from the top, where `n ≥ 0` is also taken from the stack. In particular, `1 exch` is equivalent to `swap`, and `2 exch` to `swap rot`.\n| **`exch2`** | _`(... n m – ... )`_ | interchanges the `n`-th stack entry from the top with the `m`-th stack entry from the top, where `n ≥ 0`, `m ≥ 0` are taken from the stack.\n| **`execute`** | _`(e – ... )`_ | executes the execution token (_WordDef_) `e`.\n| **`explode`** | _`(t – x1 ... xn n)`_ | unpacks a _Tuple_ `t = (x1, ... , xn)` of unknown length `n`, and returns that length.\n| **`false`** | _`( – 0)`_ | pushes 0 into the stack. Equivalent to `0`.\n| **`file-exists?`** | _`(S – ?)`_ | checks whether the file with the name specified in _String_ `S` exists.\n| **`file>B`** | _`(S – B)`_ | reads the (binary) file with the name specified in _String_ `S` and returns its contents as a _Bytes_ value. If the file does not exist, an exception is thrown.\n| **`find`** | _`(S – e −1 or e 1 or 0)`_ | looks up _String_ `S` in the dictionary and returns its definition as a _WordDef_ `e` if found, followed by −1 for ordinary words or 1 for active words. Otherwise pushes 0.\n| **`first`** | _`(t – x)`_ | returns the first component of a _Tuple_. Equivalent to `0 []`.\n| **`fits`** | _`(x y – ?)`_ | checks whether _Integer_ `x` is a signed `y`-bit integer (i.e., whether $−2^{y−1} ≤ x < 2^{y−1}$ for 0 ≤ y ≤ 1023), and returns −1 or 0 accordingly\n| **`forget`** | _`( – )`_ | forgets (removes from the dictionary) the definition of the next word scanned from the input.\n| **`gasrunvm`** | _`(... s c z – ... x c' z' )`_ | a gas-aware version of `runvm`, which invokes a new instance of TVM with both the current continuation `cc` and the special register `c3` initialized from _Slice_ `s`, and pushes a zero into the initial TVM stack similarly to `runvmdict`, but also initializes special register `c4` (the \"root of persistent data\") with _Cell_ `c`. Then starts the new TVM instance with the gas limit set to `z`. The actually consumed gas `z'` is returned at the top of the final Fift stack, and the final value of `c4` is returned immediately below the top of the final Fift stack as another _Cell_ `c'`.\n| **`gasrunvmcode`** | _`(... s z – ... x z')`_ | a gas-aware version of `runvmcode`: invokes a new instance of TVM with the current continuation `cc` initialized from _Slice_ `s` and with the gas limit set to `z`, thus executing code `s` in TVM. The original Fift stack (without s) is passed in its entirety as the initial stack of the new TVM instance. When TVM terminates, its resulting stack is used as the new Fift stack, with the exit code `x` and the actually consumed gas `z'` pushed at its top. If `x` is non-zero, indicating that TVM has been terminated by an unhandled exception, the next stack entry from the top contains the parameter of this exception, and `x` is the exception code. All other entries are removed from the stack in this case\n| **`gasrunvmdict`** | _`(... s z – ... x z')`_ | a gas-aware version of `runvmdict`: invokes a new instance of TVM with the current continuation `cc` initialized from _Slice_ `s` and sets the gas limit to `z` similarly to `gasrunvmcode`, but also initializes the special register `c3` with the same value, and pushes a zero into the initial TVM stack before the TVM execution begins. The actually consumed gas is returned as an _Integer_ `z'`. In a typical application _Slice_ `s` consists of a subroutine selection code that uses the top-of-stack _Integer_ to select the subroutine to be executed, thus enabling the definition and execution of several mutually-recursive subroutines. The selector equal to zero corresponds to the `main()` subroutine in a large TVM program.\n| **`halt`** | _`(x – )`_ | quits to the operating system similarly to `bye`, but uses _Integer_ `x` as the exit code.\n| **`hash`** | _`(c – B)`_ | computes the sha256-based representation hash of _Cell_ `c`, which unambiguously defines `c` and all its descendants (provided there are no collisions for sha256). The result is returned as a _Bytes_ value consisting of exactly 32 bytes.\n| **`hold`** | _`(S x – S')`_ | appends to _String_ `S` one UTF-8 encoded character with Unicode codepoint `x`. Equivalent to `chr $+`.\n| **`hole`** | _`( – p)`_ | creates a new _Box_ `p` that does not hold any value. Equivalent to `null box`.\n| **`i,`** | _`(b x y – b')`_ | appends the big-endian binary representation of a signed `y`-bit integer `x` to _Builder_ `b`, where `0 ≤ y ≤ 257`. If there is not enough room in `b` (i.e., if `b` already contains more than $1023 − y$ data bits), or if _Integer_ `x` does not fit into `y` bits, an exception is thrown.\n| **`i>B`** | _`(x y – B)`_ | stores a signed big-endian `y`-bit _Integer_ `x` into a _Bytes_ value `B` consisting of exactly `y / 8` bytes. _Integer_ `y` must be a multiple of eight in the range $0 ... 256$.\n| **`i@`** | _`(s x – y)`_ | fetches a signed big-endian `x`-bit integer from the first `x` bits of _Slice_ `s`. If `s` contains less than `x` data bits, an exception is thrown.\n| **`i@+`** | _`(s x – y s')`_ | fetches a signed big-endian `x`-bit integer from the first `x` bits of _Slice_ `s` similarly to `i@`, but returns the remainder of `s` as well.\n| **`i@?`** | _`(s x – y −1 or 0)`_ | fetches a signed big-endian integer from a _Slice_ similarly to `i@`, but pushes integer −1 afterwards on success. If there are less than `x` bits left in `s`, pushes integer 0 to indicate failure.\n| **`i@?+`** | _`(s x – y s' −1 or s 0)`_ | fetches a signed big-endian integer from _Slice_ `s` and computes the remainder of this _Slice_ similarly to `i@+`, but pushes −1 afterwards to indicate success. On failure, pushes the unchanged _Slice_ `s` and 0 to indicate failure.\n| **`idict!`** | _`(v x D n – D' −1 or D 0)`_ | adds a new value `v` (represented by a _Slice_) with key given by signed big-endian `n`-bit integer `x` into dictionary `D` with `n`-bit keys, and returns the new dictionary `D'` and −1 on success. Otherwise the unchanged dictionary `D` and 0 are returned.\n| **`idict!+`** | _`(v x D n – D' −1 or D 0)`_ | adds a new key-value pair `(x, v)` into dictionary `D` similarly to `idict!`, but fails if the key already exists by returning the unchanged dictionary `D` and 0.\n| **`idict@`** | _`(x D n – v −1 or 0)`_ | looks up key represented by signed big-endian `n`-bit _Integer_ `x` in the dictionary represented by _Slice_ `D`. If the key is found, returns the corresponding value as a _Slice_ `v` and −1. Otherwise returns 0.\n| **`if`** | _`(x e – )`_ | executes execution token (i.e., a _WordDef_ ) `e`, but only if _Integer_ `x` is non-zero.\n| **`ifnot`** | _`(x e – )`_ | executes execution token `e`, but only if _Integer_ `x` is zero.\n| **`include`** | _`(S – )`_ | loads and interprets a Fift source file from the path given by _String_ `S`. If the filename `S` does not begin with a slash, the Fift include search path, typically taken from the `FIFTPATH` environment variable or the `-I` command-line argument of the Fift interpreter (and equal to `/usr/lib/fift` if both are absent), is used to locate `S`.\n| **`list`** | _`(x1 ... xn n – l)`_ | constructs a list `l` of length `n` with elements `x1, ... , xn`, in that order. Equivalent to `null ' cons rot times`.\n| **`max`** | _`(x y – z)`_ | computes the maximum `z := max(x, y)` of two _Integer_'s `x` and `y`. Equivalent to `minmax nip`.\n| **`min`** | _`(x y – z)`_ | computes the minimum `z := min(x, y)` of two _Integer_'s `x` and `y`. Equivalent to `minmax drop`.\n| **`minmax`** | _`(x y – z t)`_ | computes both the minimum `z := min(x, y)` and the maximum `t := max(x, y)` of two _Integer_'s `x` and `y`.\n| **`mod`** | _`(x y – r := x mod y)`_ | computes the remainder `x mod y = x − y * ⌊x/y⌋` of division of `x` by `y`.\n| **`negate`** | _`(x – −x)`_ | changes the sign of an _Integer_.\n| **`newkeypair`** | _`( – B B')`_ | generates a new Ed25519 private/public key pair, and returns both the private key `B` and the public key `B'` as 32-byte _Bytes_ values. The quality of the keys is good enough for testing purposes. Real applications must feed enough entropy into OpenSSL PRNG before generating Ed25519 key pairs.\n| **`nil`** | _`( – t)`_ | pushes the empty _Tuple_ `t` = (). Equivalent to `0 tuple`.\n| **`nip`** | _`(x y – y)`_ | removes the second stack entry from the top. Equivalent to `swap drop`.\n| **`nop`** | _`( – )`_ | does nothing.\n| **`not`** | _`(x – −1 − x)`_ | computes the bitwise complement of an _Integer_.\n| **`now`** | _`( – x)`_ | returns the current Unix time as an _Integer_.\n| **`null`** | _`( – ⊥)`_ | pushes the _Null_ value.\n| **`null!`** | _`(p – )`_ | stores a _Null_ value into _Box_ `p`. Equivalent to `null swap !`.\n| **`null?`** | _`(x – ?)`_ | checks whether `x` is _Null_.\n| **`or`** | _`(x y – x\\|y)`_ | computes the bitwise OR of two _Integer_'s.\n| **`over`** | _`(x y – x y x)`_ | creates a copy of the second stack entry from the top over the top-of-stack entry.\n| **`pair`** | _`(x y – t)`_ | creates new pair `t = (x, y)`. Equivalent to `2 tuple` or to `\\| rot , swap ,`.\n| **`pfxdict!`** | _`(v k s n – s' −1 or s 0)`_ | adds key-value pair `(k, v)`, both represented by _Slice_'s, into a prefix dictionary `s` with keys of length at most `n`. On success, returns the modified dictionary `s'` and −1. On failure, returns the original dictionary `s` and 0.\n| **`pfxdict!+`** | _`(v k s n – s' −1 or s 0)`_ | adds key-value pair `(k, v)` into prefix dictionary `s` similarly to `pfxdict!`, but fails if the key already exists.\n| **`pfxdict@`** | _`(k s n – v −1 or 0)`_ | looks up key `k` (represented by a _Slice_) in the prefix dictionary `s` with the length of keys limited by `n` bits. On success, returns the value found as a _Slice_ `v` and −1. On failure, returns 0.\n| **`pick`** | _`(xn ... x0 n – xn ... x0 xn)`_ | creates a copy of the `n`-th entry from the top of the stack, where `n ≥ 0` is also passed in the stack. In particular, `0 pick` is equivalent to `dup`, and `1 pick` to `over`.\n| **`priv>pub`** | _`(B – B')`_ | computes the public key corresponding to a private Ed25519 key. Both the public key `B'` and the private key `B` are represented by 32-byte _Bytes_ values.\n| **`quit`** | _`(... – )`_ | exits to the topmost level of the Fift interpreter (without printing an ok in interactive mode) and clears the stack.\n| **`ref,`** | _`(b c – b 0 )`_ | appends to _Builder_ `b` a reference to _Cell_ `c`. If `b` already contains four references, an exception is thrown.\n| **`ref@`** | _`(s – c)`_ | fetches the first reference from the _Slice_ `s` and returns the _Cell_ `c` referred to. If there are no references left, throws an exception.\n| **`ref@+`** | _`(s – s' c)`_ | fetches the first reference from the _Slice_ `s` similarly to `ref@`, but returns the remainder of `s` as well.\n| **`ref@?`** | _`(s – c −1 or 0)`_ | fetches the first reference from the _Slice_ `s` similarly to `ref@`, but uses a flag to indicate failure instead of throwing an exception.\n| **`ref@?+`** | _`(s – s' c −1 or s 0)`_ | similar to `ref@+`, but uses a flag to indicate failure instead of throwing an exception.\n| **`remaining`** | _`(s – x y)`_ | returns both the number of data bits `x` and the number of cell references `y` remaining in the _Slice_ `s`.\n| **`reverse`** | _`(x1 ... xn y1 ... ym n m – xn ... x1 y1 ... ym)`_ | reverses the order of `n` stack entries located immediately below the topmost `m` elements,  here both `0 ≤ m`, `n ≤ 255` are passed in the stack.\n| **`roll`** | _`(xn ... x0 n – xn−1 ... x0 xn)`_ | rotates the top `n` stack entries,  here `n ≥ 0` is also passed in the stack. In particular, `1 roll` is equivalent to `swap`, and `2 roll` to `rot`.\n| **`rot`** | _`(x y z – y z x)`_ | rotates the three topmost stack entries.\n| **`runvmcode`** | _`(... s – ... x)`_ | invokes a new instance of TVM with the current continuation cc initialized from _Slice_ `s`, thus executing code `s` in TVM. The original Fift stack (without `s`) is passed in its entirety as the initial stack of the new TVM instance. When TVM terminates, its resulting stack is used as the new Fift stack, with the exit code `x` pushed at its top. If `x` is non-zero, indicating that TVM has been terminated by an unhandled exception, the next stack entry from the top contains the parameter of this exception, and `x` is the exception code. All other entries are removed from the stack in this case.\n| **`runvmdict`** | _`(... s – ... x)`_ | invokes a new instance of TVM with the current continuation cc initialized from _Slice_ `s` similarly to `runvmcode`,  ut also initializes the special register `c3` with the same value, and pushes a zero into the initial TVM stack before start. In a typical application _Slice_ `s` consists of a subroutine selection code that uses the top-of-stack _Integer_ to select the subroutine to be executed, thus enabling the definition and execution of several mutually-recursive subroutines. The selector equal to zero corresponds to the `main()` subroutine in a large TVM program.\n| **`runvm`** | _`(... s c – ... x c')`_ | invokes a new instance of TVM with both the current continuation cc and the special register `c3` initialized from _Slice_ `s`, and pushes a zero into the initial TVM stack similarly to `runvmdict`, but also initializes special register `c4` (the \"root of persistent data\") with _Cell_ `c`. The final value of `c4` is returned at the top of the final Fift stack as another _Cell_ `c'`. In this way one can emulate the execution of smart contracts that inspect or modify their persistent storage.\n| **`s,`** | _`(b s – b')`_ | appends data bits and references taken from _Slice_ `s` to _Builder_ `b`.\n| **`s>`** | _`(s – )`_ | throws an exception if _Slice_ `s` is non-empty. It usually marks the end of the deserialization of a cell, checking whether there are any unprocessed data bits or references left.\n| **`s>c`** | _`(s – c)`_ | creates a _Cell_ `c` directly from a _Slice_ `s`. Equivalent to `<b swap s, b>`.\n| **`sbitrefs`** | _`(s – x y)`_ | returns both the number of data bits `x` and the number of cell references `y` remaining in _Slice_ `s`. Equivalent to `remaining`.\n| **`sbits`** | _`(s – x)`_ | returns the number of data bits `x` remaining in _Slice_ `s`.\n| **`second`** | _`(t – x)`_ | returns the second component of a _Tuple_. Equivalent to `1 []`.\n| **`sgn`** | _`(x – y)`_ | computes the sign of an _Integer_ `x` (i.e., pushes 1 if $x > 0$, -1 if $x < 0$, and 0 if $x = 0$). Equivalent to `0 cmp`.\n| **`shash`** | _`(s – B)`_ | computes the SHA256-based representation hash of a _Slice_ by first transforming it into a cell. Equivalent to `s>c hashB`.\n| **`sign`** | _`(S x – S')`_ | appends a minus sign `-` to _String_ `S` if _Integer_ `x` is negative. Otherwise leaves `S` intact.\n| **`single`** | _`(x – t)`_ | creates new singleton `t = (x)`, i.e., a one-element _Tuple_. Equivalent to `1 tuple`.\n| **`skipspc`** | _`( – )`_ | skips blank characters from the current input line until a non-blank or an end-of-line character is found.\n| **`smca>$`** | _`(x y z – S)`_ | packs a standard TON smart-contract address with workchain `x` (a signed 32-bit _Integer_ ) and in-workchain address `y` (an unsigned 256-bit _Integer_ ) into a 48-character string `S` (the human-readable representation of the address) according to flags `z`. Possible individual flags in `z` are: +1 for non-bounceable addresses, 2 for testnet-only addresses, and +4 for base64url output instead of base64\n| **`space`** | _`( – )`_ | outputs a single space. Equivalent to `bl emit` or to `.\" \"`.\n| **`sr,`** | _`(b s – b')`_ | constructs a new _Cell_ containing all data and references from _Slice_ `s`, and appends a reference to this cell to _Builder_ `b`. Equivalent to `s>c ref,`.\n| **`srefs`** | _`(s – x)`_ | returns the number of cell references `x` remaining in _Slice_ `s`.\n| **`swap`** | _`(x y – y x)`_ | interchanges the two topmost stack entries.\n| **`ten`** | _`( – 10)`_ | pushes _Integer_ constant 10.\n| **`third`** | _`(t – x)`_ | returns the third component of a _Tuple_. Equivalent to `2 []`.\n| **`times`** | _`(e n – )`_ | executes execution token (_WordDef_ ) `e` exactly `n` times, if `n ≥ 0`. If n is negative, throws an exception.\n| **`triple`** | _`(x y z – t)`_ | creates new triple `t = (x, y, z)`. Equivalent to `3 tuple`.\n| **`true`** | _`( – −1)`_ | pushes −1 into the stack. Equivalent to `-1`.\n| **`tuck`** | _`(x y – y x y)`_ | equivalent to `swap over`.\n| **`tuple`** | _`(x1 ... xn n – t)`_ | creates new _Tuple_ `t = (x1, ..., xn)` from `n ≥ 0` topmost stack values. Equivalent to `dup 1 reverse \\| { swap , } rot times`, but more efficient.\n| **`tuple?`** | _`(t – ?)`_ | checks whether `t` is a _Tuple_, and returns −1 or 0 accordingly.\n| **`type`** | _`(s – )`_ | prints a _String_ `s` taken from the top of the stack into the standard output.\n| **`u,`** | _`(b x y – b')`_ | appends the big-endian binary representation of an unsigned `y`-bit integer `x` to _Builder_ `b`, where `0 ≤ y ≤ 256`. If the operation is impossible, an exception is thrown.\n| **`u>B`** | _`(x y – B)`_ | stores an unsigned big-endian `y`-bit _Integer_ `x` into a _Bytes_ value `B` consisting of exactly `y / 8` bytes. _Integer_ `y` must be a multiple of eight in the range `0 ... 256`.\n| **`u@`** | _`(s x – y)`_ | fetches an unsigned big-endian `x`-bit integer from the first `x` bits of _Slice_ `s`. If `s` contains less than `x` data bits, an exception is thrown.\n| **`u@+`** | _`(s x – y s')`_ | fetches an unsigned big-endian `x`-bit integer from the first `x` bits of _Slice_ `s` similarly to `u@`, but returns the remainder of `s` as well.\n| **`u@?`** | _`(s x – y −1 or 0)`_ | fetches an unsigned big-endian integer from a _Slice_ similarly to `u@`, but pushes integer −1 afterwards on success. If there are less than `x` bits left in `s`, pushes integer 0 to indicate failure\n| **`u@?+`** | _`(s x – y s' −1 or s 0)`_ | fetches an unsigned big-endian integer from _Slice_ `s` and computes the remainder of this _Slice_ similarly to `u@+`, but pushes −1 afterwards to indicate success. On failure, pushes the unchanged _Slice_ `s` and 0 to indicate failure.\n| **`udict!`** | _`(v x D n – D' −1 or D 0)`_ | adds a new value `v` (represented by a _Slice_) with key given by big-endian unsigned `n`-bit integer `x` into dictionary `D` with `n`-bit keys, and returns the new dictionary `D'` and −1 on success. Otherwise the unchanged dictionary `D` and 0 are returned.\n| **`udict!+`** | _`(v x D n – D' −1 or D 0)`_ | adds a new key-value pair `(x, v)` into dictionary `D` similarly to `udict!`, but fails if the key already exists by returning the unchanged dictionary `D` and 0.\n| **`udict@`** | _`(x s n – v −1 or 0)`_ | looks up key represented by unsigned big-endian n-bit _Integer_ `x` in the dictionary represented by _Slice_ `s`. If the key is found, returns the corresponding value as a _Slice_ `v` and −1. Otherwise returns 0.\n| **`ufits`** | _`(x y – ?)`_ | checks whether _Integer_ `x` is an unsigned `y`-bit integer (i.e., whether $0 ≤ x < 2^y$ for $0 ≤ y ≤ 1023$), and returns −1 or 0 accordingly.\n| **`uncons`** | _`(l – h t)`_ | decomposes a non-empty list into its head and its tail. Equivalent to `unpair`.\n| **`undef? <word-name>`** | _`( – ?)`_ | checks whether the word `<word-name>` is undefined at execution time, and returns −1 or 0 accordingly.\n| **`unpair`** | _`(t – x y)`_ | unpacks a pair `t = (x, y)`. Equivalent to `2 untuple`.\n| **`unsingle`** | _`(t – x)`_ | unpacks a singleton `t = (x)`. Equivalent to `1 untuple`.\n| **`until`** | _`(e – )`_ | an until loop: executes _WordDef_ `e`, then removes the top-of-stack integer and checks whether it is zero. If it is, then begins a new iteration of the loop by executing `e`. Otherwise exits the loop.\n| **`untriple`** | _`(t – x y z)`_ | unpacks a triple `t = (x, y, z)`. Equivalent to `3 untuple`.\n| **`untuple`** | _`(t n – x1 ... xn)`_ | returns all components of a _Tuple_ `t = x1, ..., xn)`, but only if its length is equal to `n`. Otherwise throws an exception.\n| **`variable`** | _`( – )`_ | scans a blank-delimited word name S from the remainder of the input, allocates an empty _Box_, and defines a new ordinary word `S` as a constant, which will push the new _Box_ when invoked. Equivalent to `hole constant`.\n| **`while`** | _`(e e' – )`_ | a while loop: executes _WordDef_ `e`, then removes and checks the top-of-stack integer. If it is zero, exits the loop. Otherwise executes _WordDef_ `e'`, then begins a new loop iteration by executing `e` and checking the exit condition afterwards.\n| **`word`** | _`(x – S)`_ | parses a word delimited by the character with the Unicode codepoint `x` from the remainder of the current input line and pushes the result as a _String_. For instance, `bl word abracadabra` type will print the string `\"abracadabra\"`. If $x = 0$, skips leading spaces, and then scans until the end of the current input line. If $x = 32$, skips leading spaces before parsing the next word.\n| **`words`** | _`( – )`_ | prints the names of all words currently defined in the dictionary.\n| **`x.`** | _`(x – )`_ | prints the hexadecimal representation (without the 0x prefix) if an _Integer_ `x`, followed by a single space. Equivalent to `x._ space`.\n| **`x._`** | _`(x – )`_ | prints the hexadecimal representation (without the 0x prefix) of an _Integer_ `x` without any spaces. Equivalent to `(x.) type`.\n| **`xor`** | _`(x y – x ⊕ y)`_ | computes the bitwise exclusive OR (XOR) of two _Integer_'s.\n| **`x{<hex-data>}`** | _`( – s)`_ | creates a _Slice_ `s` that contains no references and up to 1023 data bits specified in `<hex-data>`. More precisely, each hex digit from `<hex-data>` is transformed into four binary digits in the usual fashion. After that, if the last character of `<hex-data>` is an underscore `_`, then all trailing binary zeroes and the binary one immediately preceding them are removed from the resulting binary string. For instance, `x{6C_}` is equivalent to `b{01101}`.\n| **`{`** | _`( – l)`_ | an active word that increases internal variable state by one and pushes a new empty _WordList_ into the stack.\n| **`\\|`** | _`( – t)`_ | creates an empty _Tuple_ `t = ()`. Equivalent to `nil` and to `0 tuple`.\n| **`\\|+`** | _`(s s' – s'')`_ | concatenates two _Slice_'s `s` and `s`. This means that the data bits of the new _Slice_ `s''` are obtained by concatenating the data bits of `s` and `s'` , and the list of _Cell_ references of `s''` is constructed similarly by concatenating the corresponding lists for `s` and `s'` . Equivalent to `<b rot s, swap s, b> <s`.\n| **`\\|_`** | _`(s s' – s'')`_ | given two _Slice_'s `s` and `s'`, creates a new _Slice_ `s''`, which is obtained from `s` by appending a new reference to a _Cell_ containing `s'`. Equivalent to `<b rot s, swap s>s ref, b> <s`.\n| **`}`** | _`(l – e)`_ | an active word that transforms a _WordList_ `l` into a _WordDef_ (an execution token) `e`, thus making all further modifications of `l` impossible, and decreases internal variable `state` by one; then pushes the integer 1, followed by a `'nop`. The net effect is to transform the constructed _WordList_ into an execution token and push this execution token into the stack, either immediately or during the execution of an outer block.\n"
  },
  {
    "path": "languages/func/asm-functions.mdx",
    "content": "---\ntitle: \"Assembler functions\"\nsidebarTitle: \"Assembler functions\"\nnoindex: \"true\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n## Assembler function definition\n\nIn FunC, functions can be defined directly using assembler code. This is done by declaring the function body using the `asm` keyword, followed by one or more assembler commands written inside double quotes `\"`, and finalizing with the symbol `;`. For example, the following function increments an integer and then negates it:\n\n```func\nint inc_then_negate(int x) asm \"INC\" \"NEGATE\";\n```\n\nCalls to `inc_then_negate` are translated to 2 assembler commands `INC` and `NEGATE`.\n\nAlternatively, the function can be written as:\n\n```func\nint inc_then_negate'(int x) asm \"INC NEGATE\";\n```\n\nHere, `INC NEGATE` is treated as a single assembler command by FunC, but the Fift assembler correctly interprets it as two separate commands.\n\n<Aside>\n  The list of assembler commands can be found here: [TVM instructions](/tvm/instructions).\n</Aside>\n\n### Multi-line asms\n\nMulti-line assembler commands, including Fift code snippets, can be defined using triple-quoted strings `\"\"\"`.\n\nFor instance:\n\n```func\nslice hello_world() asm \"\"\"\n  \"Hello\"\n  \" \"\n  \"World\"\n  $+ $+ $>s\n  PUSHSLICE\n\"\"\";\n```\n\n## Stack calling conventions\n\nThe syntax for arguments and returns is the same as for standard functions, but there is one caveat - argument values are pushed onto the stack before the function body is executed, and the return type is what is captured from the stack afterward.\n\n### Arguments\n\nWhen calling an asm function, the first argument is pushed onto the stack first, the second one second, and so on, so that the first argument is at the bottom of the stack and the last one at the top.\n\n```func\nbuilder storeCoins(builder b, int value) asm \"STVARUINT16\";\n    ;;                     |        |\n    ;;                     |        Pushed last, sits on top of the stack\n    ;;                     |\n    ;;                     Pushed first, sits at the bottom of the stack\n\n    ;; The instruction \"STVARUINT16\" stores\n    ;; integer \"value\" into builder \"b\",\n    ;; by taking the builder from the bottom of the stack\n    ;; and the integer from the top of the stack,\n    ;; producing a new builder at the top of the stack.\n```\n\n### Returns\n\nAn assembler function's return type attempts to grab relevant values from the resulting stack after the function execution and any [result rearrangements](#rearranging-stack-entries).\n\nSpecifying an [atomic type](/languages/func/types#atomic-types), such as an `int`, `cell`, or `builder`, will make the assembler function capture the top value from the stack.\n\nFor example, in the following function:\n\n```func\nbuilder storeCoins(builder b, int value) asm \"STVARUINT16\";\n```\n\nthe instruction `STVARUINT16` produces a final builder at the top of the stack, which is returned by the `storeCoins` function.\n\nSpecifying a [tensor type](/languages/func/types#tensor-types) as a return type, such as `(int, int)`, will cause the assembler function to take as many elements from the stack as the number of components in the tensor type. If the tensor type has nested tensor types, like `((int, int), int)`, it is interpreted as if it was the flattened tensor type `(int, int, int)`.\n\nFor example, this function duplicates its input, so that if the input is `5`, it returns the tensor `(5, 5)`:\n\n```func\n(int, int) duplicate(int a) asm \"DUP\";\n;;\n;; DUP reads the value at the top of the stack\n;; and pushes a copy.\n;;\n;; Since the return type is (int, int),\n;; the function takes the first two values in the stack\n;; and returns them.\n```\n\n# Stack registers\n\nThe so-called _stack registers_ are a way of referring to the values at the top of the stack. In total, there are 256 stack registers, i.e., values held on the stack at any given time.\n\nRegister `s0` is the value at the top of the stack, register `s1` is the value immediately after it, and so on, until we reach the bottom of the stack, represented by `s255`, i.e., the 256th stack register. When a value `x` is pushed onto the stack, it becomes the new `s0`. At the same time, the old `s0` becomes the new `s1`, the old `s1` becomes the new `s2`, and so on.\n\n```func\nint takeSecond(int a, int b) asm \"SWAP\" \"DROP\";\n;;                 ↑      ↑\n;;                 |      Pushed last, sits on top of the stack\n;;                 Pushed first, sits second from the top of the stack\n\n;; SWAP interchanges s0 (top of the stack) with s1 (second-to-top)\n;;\n;; Before │ After\n;; ───────┼───────\n;; s0 = b │ s0 = a\n;; s1 = a │ s1 = b\n\n;; Then, DROP pops the value from the top of the stack and throws it away\n;;\n;; Before │ After\n;; ───────┼───────\n;; s0 = a │ s0 = b\n;; s1 = b │ s1 is now either some value deeper or just blank\n\n;; At the end, we have only one value on the stack, which is b\n;; Thus, it is captured by the return type `int`:\nint showcase() {\n    return takeSecond(5, 10);   ;; 10, i.e., b\n}\n```\n\n## Rearranging stack entries\n\n<Aside>\n  When manually rearranging arguments, they are evaluated in the new order. To overwrite this behavior see [`#pragma compute-asm-ltr`](/languages/func/compiler-directives#%23pragma-compute-asm-ltr).\n</Aside>\n\nSometimes, the order in which function arguments are passed may not match the expected order of an assembler command. Similarly, the returned values may need to be arranged differently. While this can be done manually using stack manipulation primitives, FunC has special syntax to handle this.\n\nConsidering arrangements, the evaluation flow of the assembly function can be thought of in these 5 steps:\n\n1. The function takes arguments in the order specified by the parameters.\n1. If an argument arrangement is present, arguments are reordered before being pushed onto the stack.\n1. The function body is executed.\n1. If a result arrangement is present, resulting values are reordered on the stack.\n1. The resulting values are captured (partially or fully) by the return type of the function.\n\nThe argument arrangement has the syntax `asm(arg2 arg1)`, where `arg1` and `arg2` are some arguments of the function arranged in the order we want to push them\nonto the stack: `arg1` will be pushed first and placed at the bottom of the stack, while `arg2` will be pushed last and placed at the top of the stack.\n\nArrangements are not limited to two arguments and operate on all parameters of the function:\n\n```func\n;; Changing the order of arguments to match the STDICT signature:\n;; `c` will be pushed first and placed at the bottom of the stack,\n;; while `b` will be pushed last and placed at the top of the stack\nbuilder asmStoreDict(builder b, cell c) asm(c b) \"STDICT\";\n```\n\nThe return arrangement has the syntax `asm(-> 1 0)`, where 1 and 0 represent a left-to-right reordering of [stack registers](#stack-registers) `s1` and `s0`, respectively. The contents of `s1` will be at the top of the stack, followed by the contents of `s0`.\n\nArrangements are not limited to two return values and operate on captured values:\n\n```func\n;; Changing the order of return values of LDVARUINT16 instruction,\n;; since originally it would place the modified Slice on top of the stack\n(slice, int) asmLoadCoins(slice s) asm(-> 1 0) \"LDVARUINT16\";\n;;                                        ↑ ↑\n;;                                        | Value of the stack register 0,\n;;                                        | which is the topmost value on the stack\n;;                                        Value of the stack register 1,\n;;                                        which is the second-to-top value on the stack\n```\n\nBoth argument and return arrangement can be combined together and written as follows: `asm(arg2 arg1 -> 1 0)`.\n\n```func\n;; Changing the order of return values compared to the stack\n;; and switching the order of arguments as well\n(slice, int) asmLoadInt(int len, slice s) asm(s len -> 1 0) \"LDIX\";\n;;                                                     ↑ ↑\n;;                                                     | Value of the stack register 0,\n;;                                                     | which is the topmost value on the stack\n;;                                                     Value of the stack register 1,\n;;                                                     which is the second-to-top value on the stack\n```\n"
  },
  {
    "path": "languages/func/built-ins.mdx",
    "content": "---\ntitle: \"FunC reserved words and built-ins\"\nsidebarTitle: \"Reserved words and built-ins\"\nnoindex: \"true\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n## Reserved keywords\n\nFunC reserves the following symbols and words. These cannot be used as identifiers.\n\n### Symbols\n\n`+`   `-`   `*`   `/`\n\n`%`   `?`   `:`   `,`\n\n`;`   `(`   `)`   `[`\n\n`]`   `{`   `}`   `=`\n\n`_`   `<`   `>`   `&`\n\n`|`   `^`   `~`   `==`\n\n`!=`   `<=`   `>=`   `<=>`\n\n`<<`   `>>`   `~>>`   `^>>`\n\n`~/`   `^/`   `~%`   `^%`\n\n`/%`   `+=`   `-=`   `*=`\n\n`/=`   `~/=`   `^/=`   `%=`\n\n`~%=`   `^%=`   `<<=`   `>>=`\n\n`~>>=`   `^>>=`   `&=`   `|=`\n\n`^=`   `->`\n\n### Words\n\n`return`   `var`   `repeat`   `do`\n\n`while`   `until`   `try`   `catch`\n\n`if`   `ifnot`   `then`   `else`\n\n`elseif`   `elseifnot`   `int`   `cell`\n\n`slice`   `builder`   `cont`   `tuple`\n\n`type`   `forall`   `extern`   `global`\n\n`asm`   `impure`   `inline`   `inline_ref`\n\n`auto_apply`   `method_id`   `operator`   `infix`\n\n`infixl`   `infixr`   `const`   `#pragma`\n\n`#include`\n\n## Built-ins\n\nThis section covers extra language constructs that are not part of the core but are still important for functionality. Although they could be implemented in [stdlib.fc](/languages/func/stdlib), keeping them as built-in features allows the FunC optimizer to work more efficiently.\n\nIn addition, FunC does not allow the built-in names in this section to be used as identifiers. However, there is an exception: [built-ins with non-symbolic names](#built-ins-with-non-symbolic-names) _can_ be used as identifiers for local variables.\n\n### Built-ins with symbolic names\n\n`_+_`   `_-_`   `-_`   `_*_`\n\n`_/_`   `_~/_`   `_^/_`   `_%_`\n\n`_~%_`   `_^%_`   `_/%_`   `_<<_`\n\n`_>>_`   `_~>>_`   `_^>>_`   `_&_`\n\n`_|_`   `_^_`   `~_`   `^_+=_`\n\n`^_-=_`   `^_*=_`   `^_/=_`   `^_~/=_`\n\n`^_^/=_`   `^_%=_`   `^_~%=_`   `^_^%=_`\n\n`^_<<=_`   `^_>>=_`   `^_~>>=_`   `^_^>>=_`\n\n`^_&=_`   `^_|=_`   `^_^=_`   `_==_`\n\n`_!=_`   `_<_`   `_>_`   `_<=_`\n\n`_>=_`   `_<=>_`\n\nEach one of the above names is a function wrapping the corresponding operator.\n\nFor example, `_+_` can be understood as wrapping the [`+` operator](/languages/func/operators#addition%2C-%2B):\n\n```func\nint _+_(int a, int b) { return a + b; }\n```\n\nThese functions are useful when operators need to be passed as arguments to functions, or assigned to variables.\n\nFor example, in the following snippet, function `apply` receives as argument a function `f` of type `(int, int) -> int`\nand applies it on the arguments `2` and `3`:\n\n```func\nint apply(((int, int) -> int) f) {\n    return f(2, 3);\n}\n```\n\nThen, it is possible to invoke `apply` by passing `_+_`:\n\n```func\napply(_+_);   ;; Returns 5\n```\n\nAttempting to pass the operator `+` directly does not compile:\n\n```func\napply(+);   ;; DOES NOT COMPILE\n```\n\n### Built-ins with non-symbolic names\n\n[`divmod`](#divmod)   [`~divmod`](#divmod-2)   [`moddiv`](#moddiv)   [`~moddiv`](#moddiv-2)\n\n[`muldiv`](#muldiv)   [`muldivr`](#muldivr)   [`muldivc`](#muldivc)   [`muldivmod`](#muldivmod)\n\n[`true`](#true)   [`false`](#false)   [`nil`](#nil)   [`Nil`](#nil-2)\n\n[`null?`](#null%3F)   [`throw`](#throw)   [`throw_if`](#throw-if)   [`throw_unless`](#throw-unless)\n\n[`throw_arg`](#throw-arg)   [`throw_arg_if`](#throw-arg-if)   [`throw_arg_unless`](#throw-arg-unless)   [`load_int`](#load-int)\n\n[`load_uint`](#load-uint)   [`preload_int`](#preload-int)   [`preload_uint`](#preload-uint)   [`store_int`](#store-int)\n\n[`store_uint`](#store-uint)   [`~store_int`](#store-int-2)   [`~store_uint`](#store-uint-2)   [`load_bits`](#load-bits)\n\n[`preload_bits`](#preload-bits)   [`int_at`](#int-at)   [`cell_at`](#cell-at)   [`slice_at`](#slice-at)\n\n[`tuple_at`](#tuple-at)   [`at`](#at)   [`touch`](#touch)   [`~touch`](#touch-2)\n\n[`touch2`](#touch2)   [`~touch2`](#touch2-2)   [`~dump`](#dump)   [`~strdump`](#strdump)\n\n[`run_method0`](#run-method0)   [`run_method1`](#run-method1)   [`run_method2`](#run-method2)   [`run_method3`](#run-method3)\n\n#### `divmod`\n\n```func\n(int, int) divmod(int dividend, int divisor)\n```\n\n`divmod` takes two integers as input and returns the quotient and remainder of their division `dividend / divisor`.\n\n#### `~divmod`\n\nSame as [`divmod`](#divmod), but allows using [modifying notation](/languages/func/expressions#modifying-notation).\n\nExample:\n\n```func\nint a = 10;\nint b = 2;\n\n;; \"mod\" stores the modulo 10 % 2\n;; and \"a\" gets updated with the quotient of 10 / 2\nint mod = a~divmod(b);\n\n;; Here, a has value 5\n;; mod has value 0\n;; b has value 2\n```\n\n#### `moddiv`\n\n```func\n(int, int) moddiv(int dividend, int divisor)\n```\n\n`moddiv` takes two integers as input and returns the remainder and quotient of their division `dividend / divisor`.\n\n#### `~moddiv`\n\nSame as [`moddiv`](#moddiv), but allows using [modifying notation](/languages/func/expressions#modifying-notation).\n\nExample:\n\n```func\nint a = 10;\nint b = 2;\n\n;; \"div\" stores the quotient of 10 / 2\n;; and \"a\" gets updated with the modulo 10 % 2\nint div = a~moddiv(b);\n\n;; Here, a has value 0\n;; div has value 5\n;; b has value 2\n```\n\n#### `muldiv`\n\n```func\nint muldiv(int factor1, int factor2, int divisor)\n```\n\n`muldiv` performs a multiply-then-divide operation `(factor1 * factor2) / divisor`, where `/` is the [division operator](/languages/func/operators#division%2C-%2F).\nIt uses a 513-bit intermediate result to prevent overflow if the final result fits within 257 bits.\n\n#### `muldivr`\n\n```func\nint muldivr(int factor1, int factor2, int divisor)\n```\n\n`muldivr` performs a multiply-then-divide operation `(factor1 * factor2) ~/ divisor`, where `~/` is the [rounding division operator](/languages/func/operators#rounding-division%2C-%2F).\nIt uses a 513-bit intermediate result to prevent overflow if the final result fits within 257 bits.\n\n#### `muldivc`\n\n```func\nint muldivc(int factor1, int factor2, int divisor)\n```\n\n`muldivc` performs a multiply-then-divide operation `(factor1 * factor2) ^/ divisor`, where `^/` is the [ceiling division operator](/languages/func/operators#ceiling-division%2C-%5E%2F).\nIt uses a 513-bit intermediate result to prevent overflow if the final result fits within 257 bits.\n\n#### `muldivmod`\n\n```func\n(int, int) muldivmod(int factor1, int factor2, int divisor)\n```\n\n`muldivmod` performs a multiply-then-divide operation `(factor1 * factor2) / divisor`, where `/` is the [division operator](/languages/func/operators#division%2C-%2F),\nand returns the quotient and remainder of such division. It uses a 513-bit intermediate result to prevent overflow if the final result fits within 257 bits.\n\n#### `true`\n\n`true` is an alias for `-1`.\n\n#### `false`\n\n`false` is an alias for `0`.\n\n#### `nil`\n\n`nil` is an alias for the `null` value.\n\n#### `Nil`\n\n`Nil` is an alias for the empty tuple `[]`.\n\n#### `null?`\n\n```func\nforall X -> int null?(X val)\n```\n\n`null?` checks if the given argument is `null`. Returns `0` if the argument is not `null`, and `-1` otherwise.\n\nFor more info, see [null values](/languages/func/types#null-values).\n\n#### `throw`\n\n```func\n() throw(int error)\n```\n\nTriggers an exception, which interrupts the execution flow.\n`throw` takes only one argument, the error code. See [TVM error codes](/tvm/exit-codes) for details about error codes.\n\n#### `throw_if`\n\n```func\n() throw_if(int error, int condition)\n```\n\nTriggers an exception only if the provided condition is true, i.e., if the condition is `-1`.\nIt receives two arguments: the error code, which defines the exception type, and the condition.\nSee [TVM error codes](/tvm/exit-codes) for details about error codes.\n\n#### `throw_unless`\n\n```func\n() throw_unless(int error, int condition)\n```\n\nTriggers an exception only if the provided condition is false, i.e., if the condition is `0`.\nIt receives two arguments: the error code, which defines the exception type, and the condition.\nSee [TVM error codes](/tvm/exit-codes) for details about error codes.\n\n#### `throw_arg`\n\n```func\nforall X -> () throw_arg(X arg, int error)\n```\n\nTriggers an exception, which interrupts the execution flow.\n\nThe first argument can be of any type, and it is used to pass extra information about the error. This extra information can be\nprocessed in [`try..catch` statements](/languages/func/statements#try-catch-statement).\nRefer to the `try..catch` statement page for an example on how to use the first argument.\nThe second argument is the error code. See [TVM error codes](/tvm/exit-codes) for details about error codes.\n\n#### `throw_arg_if`\n\n```func\nforall X -> () throw_arg_if(X arg, int error, int condition)\n```\n\nTriggers an exception only if the provided condition is true, i.e., if the condition is `-1`.\n\nSimilarly to [`throw_arg`](#throw-arg), the first argument can be of any type, and it is used to pass extra information about the error. This extra information can be\nprocessed in [`try..catch` statements](/languages/func/statements#try-catch-statement), in the same way as with [`throw_arg`](#throw-arg).\nThe second argument is the error code. See [TVM error codes](/tvm/exit-codes) for details about error codes.\nThe third argument is the condition to check.\n\n#### `throw_arg_unless`\n\n```func\nforall X -> () throw_arg_unless(X arg, int error, int condition)\n```\n\nTriggers an exception only if the provided condition is false, i.e., if the condition is `0`.\n\nSimilarly to [`throw_arg`](#throw-arg), the first argument can be of any type, and it is used to pass extra information about the error. This extra information can be\nprocessed in [`try..catch` statements](/languages/func/statements#try-catch-statement), in the same way as with [`throw_arg`](#throw-arg).\nThe second argument is the error code. See [TVM error codes](/tvm/exit-codes) for details about error codes.\nThe third argument is the condition to check.\n\n#### `load_int`\n\n```func\n(slice, int) load_int(slice s, int len)\n```\n\nReads a signed `len`-bit integer from slice `s`. Returns the modified slice and the obtained integer.\n\n#### `load_uint`\n\n```func\n(slice, int) load_uint(slice s, int len)\n```\n\nReads an unsigned `len`-bit integer from slice `s`. Returns the modified slice and the obtained unsigned integer.\n\n#### `preload_int`\n\n```func\nint preload_int(slice s, int len)\n```\n\nReads a signed `len`-bit integer from slice `s`. Returns the obtained integer. This method does not modify slice `s`.\n\n#### `preload_uint`\n\n```func\nint preload_uint(slice s, int len)\n```\n\nReads an unsigned `len`-bit integer from slice `s`. Returns the obtained unsigned integer. This method does not modify slice `s`.\n\n#### `store_int`\n\n```func\nbuilder store_int(builder b, int x, int len)\n```\n\nStores a signed `len`-bit integer `x` in builder `b`. Returns the modified builder.\n\n#### `store_uint`\n\n```func\nbuilder store_uint(builder b, int x, int len)\n```\n\nStores an unsigned `len`-bit integer `x` in builder `b`. Returns the modified builder.\n\n#### `~store_int`\n\n```func\n(builder, ()) ~store_int(builder b, int x, int len)\n```\n\nSame as [`store_int`](#store-int), but adapted to use [modifying notation](/languages/func/expressions#modifying-notation).\n\n#### `~store_uint`\n\n```func\n(builder, ()) ~store_uint(builder b, int x, int len)\n```\n\nSame as [`store_uint`](#store-uint), but adapted to use [modifying notation](/languages/func/expressions#modifying-notation).\n\n#### `load_bits`\n\n```func\n(slice, slice) load_bits(slice s, int len)\n```\n\nLoads the first `len` bits from slice `s`. It returns the modified slice and a slice containing the loaded bits.\n\n#### `preload_bits`\n\n```func\nslice preload_bits(slice s, int len)\n```\n\nLoads the first `len` bits from slice `s`. It returns a slice containing the loaded bits. This method does not modify slice `s`.\n\n#### `int_at`\n\n```func\nint int_at(tuple t, int index)\n```\n\nReturns the element at index `index` in tuple `t`, casted as an integer.\n\n<Aside\n  type=\"danger\"\n>\n  It is responsibility of the programmer to check that the returned element is actually an integer.\n</Aside>\n\n#### `cell_at`\n\n```func\ncell cell_at(tuple t, int index)\n```\n\nReturns the element at index `index` in tuple `t`, casted as a cell.\n\n<Aside\n  type=\"danger\"\n>\n  It is responsibility of the programmer to check that the returned element is actually a cell.\n</Aside>\n\n#### `slice_at`\n\n```func\nslice slice_at(tuple t, int index)\n```\n\nReturns the element at index `index` in tuple `t`, casted as a slice.\n\n<Aside\n  type=\"danger\"\n>\n  It is responsibility of the programmer to check that the returned element is actually a slice.\n</Aside>\n\n#### `tuple_at`\n\n```func\ntuple tuple_at(tuple t, int index)\n```\n\nReturns the element at index `index` in tuple `t`, casted as a tuple.\n\n<Aside\n  type=\"danger\"\n>\n  It is responsibility of the programmer to check that the returned element is actually a tuple.\n</Aside>\n\n#### `at`\n\n```func\nforall X -> X at(tuple t, int index)\n```\n\nReturns the element at index `index` in tuple `t`. The returned element can be of any type.\n\n#### `touch`\n\n```func\nforall X -> X touch(X v)\n```\n\nMoves `v` to the top of the stack. It returns the argument `v`.\n\n#### `~touch`\n\n```func\nforall X -> (X, ()) ~touch(X v)\n```\n\n`~touch` is identical to [`touch`](#touch), but adapted to use [modifying notation](/languages/func/expressions#modifying-notation).\n\n#### `touch2`\n\n```func\nforall X, Y -> (X, Y) touch2((X, Y) t)\n```\n\nMoves the components of the tensor `t` to the top of the stack; first component with type `X` and then component with type `Y`. It returns the argument tensor `t`.\n\n#### `~touch2`\n\n```func\nforall X, Y -> ((X, Y), ()) ~touch2((X, Y) t)\n```\n\n`~touch2` is identical to [`touch2`](#touch2), but adapted to use [modifying notation](/languages/func/expressions#modifying-notation).\n\n#### `~dump`\n\n```func\nforall X -> (X, ()) ~dump(X value)\n```\n\nOutputs value `value` to the debug log. It returns the argument `value` and the unit value `()`.\n[Modifying notation](/languages/func/expressions#modifying-notation) can be used on this function.\n\nIn case `value` is a slice containing ASCII characters, it is preferable to use [`~strdump`](#strdump) if the intention is\nto print the ASCII string in the debug log. Otherwise, `~dump` will print the slice's contents as bits.\n\n#### `~strdump`\n\n```func\nforall X -> (X, ()) ~strdump(X s)\n```\n\nOutputs to the debug log the ASCII string encoded in slice `s`. It returns the argument `s` and the unit value `()`.\n[Modifying notation](/languages/func/expressions#modifying-notation) can be used on this function.\n\nIf the argument `s` is not a slice containing ASCII characters, the debug log will show an error.\n\n#### `run_method0`\n\n```func\n() run_method0 (int method_id)\n```\n\nExecutes the 0 argument function with [ID](/languages/func/functions#method-id-specifier) `method_id`. The function with ID `method_id` must have a signature of the form:\n\n```func\n() some_function()\n```\n\nwhich receives 0 arguments and returns nothing.\n\nThe `run_method0` is useful for dynamically executing methods at run-time.\nFor example, receiving the method ID to execute in the incoming internal message.\n\n<Aside>\n  Recall that method ids can be explicitly set when declaring functions using the [`method_id` specifier](/languages/func/functions#method-id-specifier):\n\n  ```func\n  () test() method_id(1234)\n  ```\n\n  So that later, it can be invoked as:\n\n  ```func\n  run_method0(1234);   ;; executes function test\n  ```\n</Aside>\n\n<Aside\n  type=\"danger\"\n>\n  The FunC compiler does not check that the function to execute in `run_method0` has the correct number of arguments and\n  that it returns `()`. This is responsibility of the programmer.\n</Aside>\n\n#### `run_method1`\n\n```func\nforall X -> () run_method1 (int method_id, X arg1)\n```\n\nExecutes the 1 argument function with [ID](/languages/func/functions#method-id-specifier) `method_id`, and passes `arg1` as argument to the function.\nThe function with ID `method_id` must have a signature of the form:\n\n```func\n() some_function(T a1)\n```\n\nwhich receives 1 argument and returns nothing. Type `T` must coincide with the type of the argument `arg1` provided in `run_method1`.\n\nFor example, under the assumption that `1234` is the ID of function `test`, invoking:\n\n```func\n;; The argument \"a\" is a slice containing the ASCII character 'a'\nrun_method1(1234, \"a\");\n```\n\nrequires that `test` has the signature:\n\n```func\n() test(slice s)\n```\n\nAs with [`run_method0`](#run-method0), function `run_method1` is useful for dynamically executing 1 argument methods at run-time.\n\n<Aside\n  type=\"danger\"\n>\n  The FunC compiler does not check that the function to execute in `run_method1` has the correct number of arguments,\n  that it returns `()`, and that the types of arguments in `run_method1` and the function to execute coincide. This is responsibility of the programmer.\n</Aside>\n\n#### `run_method2`\n\n```func\nforall X, Y -> () run_method2 (int method_id, X arg1, Y arg2)\n```\n\nExecutes the 2 argument function with [ID](/languages/func/functions#method-id-specifier) `method_id`. The function with ID `method_id` must have a signature of the form:\n\n```func\n() some_function(T1 a1, T2 a2)\n```\n\nwhich receives 2 arguments and returns nothing. Type `T1` must coincide with the type of the argument `arg1` provided in `run_method2`,\nand similarly for type `T2`.\n\nThe same observations and warnings apply as with [`run_method1`](#run-method1).\n\n#### `run_method3`\n\n```func\nforall X, Y, Z -> () run_method3 (int method_id, X arg1, Y arg2, Z arg3)\n```\n\nExecutes the 3 argument function with [ID](/languages/func/functions#method-id-specifier) `method_id`. The function with ID `method_id` must have a signature of the form:\n\n```func\n() some_function(T1 a1, T2 a2, T3 a3)\n```\n\nwhich receives 3 arguments and returns nothing. Type `T1` must coincide with the type of the argument `arg1` provided in `run_method3`,\nand similarly for types `T2` and `T3`.\n\nThe same observations and warnings apply as with [`run_method1`](#run-method1).\n"
  },
  {
    "path": "languages/func/changelog.mdx",
    "content": "---\ntitle: \"Changelog\"\nsidebarTitle: \"Changelog\"\nnoindex: \"true\"\n---\n\n## Version 0.4.6\n\nReleased in [Dec 2024](https://github.com/ton-blockchain/ton/releases/tag/v2024.12-1).\n\n**Fixes:**\n\n- `try/catch` handling.\n- Pure flag for functions stored in variables.\n\n## Version 0.4.5\n\nReleased in [Oct 2024](https://github.com/ton-blockchain/ton/releases/tag/v2024.10).\n\n**Fixes:**\n\n- Bug in optimization of [operator `<<`](/languages/func/operators#shift-left%2C-%3C%3C).\n\n## Version 0.4.4\n\nReleased in [May 2023](https://github.com/ton-blockchain/ton/releases/tag/v2023.05).\n\n**New features:**\n\n- Better error-handling.\n\n**Fixes:**\n\n- `catch` stack recovery.\n\n## Version 0.4.3\n\nReleased in [Apr 2023](https://github.com/ton-blockchain/ton/releases/tag/v2023.04).\n\n**New features:**\n\n- Improved optimization of int constants and unused variables.\n\n**Fixes:**\n\n- Better handling of incorrect inputs: fix UB and prevent crashes on some inputs.\n- Analysis of repeat loops.\n\n## Version 0.4.2\n\nReleased in [Mar 2023](https://github.com/ton-blockchain/ton/releases/tag/v2023.03).\n\n**New features:**\n\n- [FunC Mathlib](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/mathlib.fc/).\n\n**Fixes:**\n\n- Handling of incorrect integer literal values.\n\n## Version 0.4.1\n\nReleased in [Jan 2023](https://github.com/ton-blockchain/ton/releases/tag/v2023.01).\n\n**New features:**\n\n- Added pragmas for precise control of computation order: [`allow-post-modification`](/languages/func/compiler-directives#%23pragma-allow-post-modification) and [`compute-asm-ltr`](/languages/func/compiler-directives#%23pragma-compute-asm-ltr).\n- Added legacy tester, a collection of smart-contracts which is used to check whether a compiler update changes compilation results.\n\n**Fixes:**\n\n- Compiler crashes for some exotic inputs.\n\n## Version 0.4.0\n\nReleased in [Jan 2023](https://github.com/ton-blockchain/ton/releases/tag/v2022.12/).\n\n**New features:**\n\n- [`try/catch` statements](/languages/func/statements#try-catch-statement).\n- [`throw_arg`](/languages/func/built-ins#throw-arg), [`throw_arg_if`](/languages/func/built-ins#throw-arg-if), and [`throw_arg_unless`](/languages/func/built-ins#throw-arg-unless) functions.\n- Support for in-place modification and mass assignment of global variables, e.g., `a~inc()` and `(a, b) = (3, 5)`, where `a` is global.\n\n**Fixes:**\n\n- Disallowed ambiguous modification of local variables after their usage in the same expression. For example, `var x = (ds, ds~load_uint(32), ds~load_unit(64));` is forbidden, while `var x = (ds~load_uint(32), ds~load_unit(64), ds);` is allowed.\n- Allowed empty inline functions.\n- Fixed a rare optimization bug in `while` loops.\n\n## Version 0.3.0\n\nReleased in [Oct 2022](https://github.com/ton-blockchain/ton/releases/tag/v2022.10/).\n\n**New features:**\n\n- Support for [multiline `asm` statements](/languages/func/asm-functions#multi-line-asms).\n- Allow duplicate definitions of identical constants and `asm` statements.\n- Enable bitwise operations for constants.\n\n## Version 0.2.0\n\nReleased in [Aug 2022](https://github.com/ton-blockchain/ton/releases/tag/v2022.08/).\n\n**New features:**\n\n- Unbalanced `if/else` branches, where some branches return a value while others do not.\n\n**Fixes:**\n\n- FunC incorrectly handles `while(false)` loops [(#377)](https://github.com/ton-blockchain/ton/issues/377/).\n- FunC generates incorrect code for `if/else` branches [(#374)](https://github.com/ton-blockchain/ton/issues/374/).\n- FunC incorrectly returns from conditions in inline functions [(#370)](https://github.com/ton-blockchain/ton/issues/370/).\n- `Asm.fif`: splitting large function bodies incorrectly interferes with inline [(#375)](https://github.com/ton-blockchain/ton/issues/375/).\n\n## Version 0.1.0\n\nReleased in [May 2022](https://github.com/ton-blockchain/ton/releases/tag/v2022.05/).\n\n**New features:**\n\n- [Constants](/languages/func/literals#constants)\n- [Compile-time built-ins](/languages/func/literals#compile-time-built-ins)\n- [Semver pragmas](/languages/func/compiler-directives#%23pragma-version)\n- [Includes](/languages/func/compiler-directives#%23include)\n\n**Fixes:**\n\n- Resolved rare bugs in `Asm.fif`.\n\n## Initial version\n\nThe initial version of FunC was developed by Telegram, but active development stopped after May 2020.\nThe May 2020 release is referred to as the \"initial\" version.\n"
  },
  {
    "path": "languages/func/comments.mdx",
    "content": "---\ntitle: \"FunC comments\"\nsidebarTitle: \"Comments\"\nnoindex: \"true\"\n---\n\nFunC supports both single-line and multi-line comments.\n\n**Single-line** comments start with a double semicolon `;;`. For example:\n\n```func\nint x = 1; ;; assigns 1 to x\n```\n\n**Multi-line** comments begin with an opening curly brace and dash `{-` and end with a dash and closing curly brace `-}`.\nUnlike other languages, FunC allows **nested multi-line comments**.\n\nExample:\n\n```func\n{- This is a multi-line comment\n    {- This is a comment inside a comment -}\n-}\n```\n\nSingle-line comments `;;` can also appear inside multi-line comments. They take precedence over the multi-line comments `{- -}`.\n\nFor example, in the following snippet, `const a = 10;` is inside a multi-line comment and is effectively commented out:\n\n```func\n{-\n  Start of the comment\n\n;; This comment’s ending is itself commented out -> -}\n\nconst a = 10;\n\n;; This comment’s beginning is itself commented out -> {-\n\n  End of the comment\n-}\n```\n"
  },
  {
    "path": "languages/func/compiler-directives.mdx",
    "content": "---\ntitle: \"FunC compiler directives\"\nsidebarTitle: \"Compiler directives\"\nnoindex: \"true\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nCompiler directives are keywords that begin with `#`, instructing the compiler to perform specific actions, enforce checks, or modify parameters.\n\nThese directives can only be used at the outermost level of a source file and cannot be placed inside function definitions.\n\n## `#include`\n\nThe `#include` directive enables the inclusion of another FunC source file parsed in place of the directive.\n\n**Syntax:**\n\n```func\n#include \"<path_to_filename>\";\n```\n\nwhere `<path_to_filename>` is the path to the FunC source file to include.\n\nFiles are automatically checked for multiple inclusions.\nBy default, the compiler will ignore redundant inclusions if the same file is included more than once.\nThis also applies to inclusions along a path of nested inclusions.\nA warning will be issued if the verbosity level is 2 or higher.\n\nFor example, suppose that `main.fc` contains the `main` function. Suppose also that `main.fc` includes a file `A.fc`, which in turn includes a file `B.fc`,\nwhich in turn includes `main.fc`. When `main.fc` is compiled, the inclusion of `main.fc` in `B.fc` will be ignored.\n\nIf an error occurs while parsing an included file, the compiler displays an inclusion stack, showing the locations of each file in the inclusion chain.\n\n## `#pragma`\n\nThe `#pragma` directive provides additional information to the compiler beyond what the language conveys.\n\n### `#pragma` version\n\nThe `#pragma` version directive enforces using a specific FunC compiler version when compiling the file.\n\n**Syntax:**\n\n```func\n#pragma version <op><sem_version>;\n```\n\nwhere `<op>` is an optional [version operator](#operators) that allows to specify a constraint, and `<sem_version>` is specified\nin [**semantic versioning (semver)** format](https://en.wikipedia.org/wiki/Software_versioning): _a.b.c_, where:\n\n- _a_ is the major version\n- _b_ is the minor version\n- _c_ is the patch version\n\nExample:\n\n```func\n#pragma version 2.3.4;\n#pragma version >2.3.4;\n```\n\nThe first example does not use an operator and it means that the compiler must have exactly version `2.3.4`.\nThe second uses the greater than operator `>`, and it means that the compiler must have a version greater\nthan `2.3.4` (see [precedence](#equality-and-precedence) and [operators](#operators) below for details).\n\n#### Equality and precedence\n\nTwo versions are **equal** if their respective major, minor, and patch numbers are equal. Two versions are **not equal** if at least one of those numbers differ.\n\nExample:\n\n- _1.2.3_ is equal to _1.2.3_\n- _3.4.5_ is not equal to _3.1.5_\n\n**Precedence** of two versions _a.b.c_ and _d.e.f_ is determined the following way:\n\n- If _a_ is smaller than _d_, then _a.b.c_ precedes _d.e.f_\n- If _a_ is equal to _d_, and _b_ is smaller than _e_, then _a.b.c_ precedes _d.e.f_\n- If _a_ is equal to _d_, and _b_ is equal to _e_, and _c_ is smaller than _f_, then _a.b.c_ precedes _d.e.f_\n\nIf _a.b.c_ precedes _d.e.f_, then it is said that _a.b.c_ is smaller than _d.e.f_, or equivalently, that _d.e.f_ is greater than _a.b.c_.\n\nExample:\n\n- _1.0.0_ precedes _2.0.0_. Equivalently: _1.0.0_ is smaller than _2.0.0_ or _2.0.0_ is greater than _1.0.0_.\n- _2.0.0_ precedes _2.1.0_. Equivalently: _2.0.0_ is smaller than _2.1.0_ or _2.1.0_ is greater than _2.0.0_.\n- _2.1.0_ precedes _2.1.1_. Equivalently: _2.1.0_ is smaller than _2.1.1_ or _2.1.1_ is greater than _2.1.0_.\n\n#### Operators\n\nDevelopers can specify version constraints using the following operators:\n\n- _a.b.c_ or _=a.b.c_ - Requires **exactly** version _a.b.c_ of the compiler\n- _>a.b.c_ - Requires the compiler version to be **greater** than _a.b.c._\n- _>=a.b.c_ - Requires the compiler version to be **greater** than or **equal** to _a.b.c_\n- _\\<a.b.c_ - Requires the compiler version to be **less** than _a.b.c_\n- _\\<=a.b.c_ - Requires the compiler version to be **less** than or **equal** to _a.b.c_\n- _^a.b.c_ - Requires the major part of the compiler version to be **equal** to the _a_ part, the minor to be **equal** to the _b_ part, and the patch to be **no lower** than the _c_ part\n- _^a.b_ - Requires the major compiler version to be **equal** to the _a_ part and the minor to be **no lower** than the _b_ part\n- _^a_ - Requires the major compiler version to be **no lower** than the _a_ part\n\nFor the comparison operators _=_, _>_, _>=_, _\\<_, _\\<=_, omitted parts default to zero.\nFor example:\n\n- _>a.b_ is equivalent to _>a.b.0_\n- _\\<=a_ is equivalent to _\\<=a.0.0_\n\nFor the operator ^, omitted parts do **not** default to zero. For example:\n\n- _^a.b_ is not equivalent to _^a.b.0_\n- _^a_ is not equivalent to _^a.0.0_\n\nHere are some examples of constraints:\n\n- _^5.1.2_ matches compiler version _5.1.3_ because patch `3` is no lower than patch `2`.\n- _^5.1.2_ does not match compiler version _5.2.3_ because minor `2` does not equal minor `1`.\n- _^5.1.2_ does not match compiler version _5.1.1_ because patch `1` is lower than patch `2`.\n- _^5.1_ matches compiler version _5.1.3_ because minor `1` is no lower than minor `1`.\n- _^5.1_ matches compiler version _5.2.3_ because minor `2` is no lower than minor `1`.\n- _^5.1_ matches compiler version _5.1.0_ because minor `1` is no lower than minor `1`.\n- _^5.1_ does not match compiler version _5.0.2_ because minor `0` is lower than minor `1`.\n- _^5_ matches compiler version _5.1.0_ because major `5` is no lower than major `5`.\n- _^5_ does not match compiler version _4.1.0_ because major `4` is lower than major `5`.\n- _>5.1.2_ matches compiler version _5.1.3_ because patch `3` is bigger than patch `2`.\n- _>5.1.2_ matches compiler version _5.2.0_ because minor `2` is bigger than minor `1`.\n- _>5.1.2_ matches compiler version _6.0.0_ because major `6` is bigger than major `5`.\n- _=5.1.2_ does not match compiler version _5.2.2_ because minor `2` is not equal to minor `1`.\n\n<Aside>\n  The `#pragma` version directive can be used multiple times, and the compiler must satisfy all specified constraints.\n</Aside>\n\n### `#pragma not-version`\n\nThe `#pragma not-version` is similar to `#pragma version`, but it fails if the specified condition is met.\n\n**Syntax:**\n\n```func\n#pragma not-version <op><sem_version>;\n```\n\nwhere `<op>` is an optional [version operator](#operators) that allows to specify a constraint, and `<sem_version>` is identical as\nin [`#pragma version`](#%23pragma-version).\n\nThis directive is useful for blocking specific compiler versions known to have issues.\n\nHere are some examples:\n\n```func\n#pragma not-version >2.1.3;\n#pragma not-version ^3.4;\n#pragma not-version 1.2.3;\n```\n\nIn the first example, `not-version >2.1.3` matches any compiler version that is _not_ bigger than _2.1.3_, like _2.1.2_, _2.0.5_ and even _2.1.3_ itself.\n\nIn the second example, `not-version ^3.4` matches any compiler version that does _not_ match _^3.4_, like _3.3.1_, _4.4.0_, and _3.3.9_\n\nIn the third example, `not-version 1.2.3` matches any compiler version different from _1.2.3_.\n\n### `#pragma allow-post-modification`\n\n_Introduced in FunC v0.4.1_\n\nIn Func, using a variable before it is modified within the same [expression](/languages/func/expressions) is prohibited by default.\n\nFor example, the following code will **not** compile, because `ds` is used before it is modified in `ds~load_uint(8)`.\nSee [modifying notation](/languages/func/expressions#modifying-notation) for more details on using symbol `~`.\n\n```func\n(x, y) = (ds, ds~load_uint(8));\n```\n\nHowever, this version is **valid**, since `ds` is used after it is modified:\n\n```func\n(x, y) = (ds~load_uint(8), ds)\n```\n\nTo override this restriction, use `#pragma allow-post-modification`.\nThis allows variables to be modified after usage in mass assignments and function calls while sub-expressions are still computed **left to right**.\n\nIn the following example, `x` will contain the initial value of `ds`, while `y` the modified value of `ds`:\n\n```func\n#pragma allow-post-modification\n(x, y) = (ds, ds~load_bits(8));\n```\n\n<Aside>\n  `#pragma allow-post-modification` works only for code after the pragma.\n</Aside>\n\n### `#pragma compute-asm-ltr`\n\n_Introduced in FunC v0.4.1_\n\n`asm` declarations can override the order of argument evaluation. For example, in the following expression:\n\n```func\nidict_set_ref(ds~load_dict(), ds~load_uint(8), ds~load_uint(256), ds~load_ref())\n```\n\nThe evaluation order of the call arguments is:\n\n1. `load_ref()`\n1. `load_uint(256)`\n1. `load_dict()`\n1. `load_uint(8)`\n\nThis happens due to the corresponding `asm` declaration:\n\n```func\ncell idict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) \"DICTISETREF\";\n```\n\nHere, the `asm(value index dict key_len)` notation dictates a [rearrangement of arguments](/languages/func/asm-functions#rearranging-stack-entries).\n\nTo ensure strict left-to-right computation order of the arguments, use `#pragma compute-asm-ltr`.\nWith this directive enabled, the same function call:\n\n```func\n#pragma compute-asm-ltr\n;; ...\nidict_set_ref(ds~load_dict(), ds~load_uint(8), ds~load_uint(256), ds~load_ref());\n```\n\nwill evaluate its arguments in the following order:\n\n1. `load_dict()`\n1. `load_uint(8)`\n1. `load_uint(256)`\n1. `load_ref()`\n\nand only _after_ the evaluation of all these arguments, the `asm` rearrangement will occur.\n\n<Aside>\n  `#pragma compute-asm-ltr` works only for code after the pragma.\n</Aside>\n"
  },
  {
    "path": "languages/func/cookbook.mdx",
    "content": "---\ntitle: \"FunC cookbook\"\nsidebarTitle: \"Cookbook\"\nnoindex: \"true\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nThe FunC cookbook was created to consolidate all the knowledge and best practices from experienced FunC developers in one place.\nThe goal is to make it easier for future developers to build smart contracts efficiently.\n\nUnlike the rest of the official FunC documentation, this guide focuses on solving everyday challenges that FunC developers encounter\nduring smart contract development.\n\n## Statements\n\n### How to use flags in if statements\n\nTo check whether an event is relevant, use a flag variable of type integer.\nThe flag can either be `0`, representing `false`, or `-1`, representing `true`.\nSee [absence of boolean type](/languages/func/types#no-boolean-type).\n\nWhen checking the flag in [if..else statements](/languages/func/statements#if%E2%80%A6else-statement), it is unnecessary to use\nthe [`==` operator](/languages/func/operators#equality%2C-%3D%3D), since a `0` evaluates to `false`, and any nonzero value is\nconsidered to be `true` in `if..else` statements.\n\n```func\nint flag = 0;  ;; false\n\n;; ...\n;; ...\n\nif (flag) {    ;; No need to use flag == -1\n    ;; do something\n}\nelse {\n    ;; reject\n}\n```\n\n### How to write a repeat loop\n\nA [repeat loop](/languages/func/statements#repeat-loop) helps execute an action a fixed number of times. The example below computes\nexponentiation of `number` to the exponent `exponent`, and illustrates it with specific values `number = 2` and `exponent = 5`:\n\n```func\nint number = 2;\nint exponent = 5;\n\nint result = 1;      ;; Will store the final result: number^exponent\n\nrepeat(exponent) {   ;; The repeat multiplies variable \"number\",\n                     ;; exactly an \"exponent\" number of times\n    result *= number;\n}\n;; result holds value 32\n```\n\n### How to write a while loop\n\nA [while loop](/languages/func/statements#while-loop) is useful when the number of iterations is unknown.\nThe following example processes the references in the message [cell](/foundations/serialization/cells).\nEach cell can store up to four references to other cells:\n\n```func\ncell inner_cell = begin_cell() ;; Create a new empty builder\n        .store_uint(123, 16) ;; Store uint with value 123 and length 16 bits\n        .end_cell(); ;; Convert builder to a cell\n\n;; Create a cell, which will have two references to inner_cell\ncell message = begin_cell()\n        .store_ref(inner_cell) ;; Store cell as reference\n        .store_ref(inner_cell) ;; A second time\n        .end_cell();\n\nslice msg = message.begin_parse(); ;; Convert cell to slice\nwhile (msg.slice_refs_empty?() != -1) { ;; Iterate while there are refs to process\n                                        ;; Recall that -1 is true.\n\n    cell inner_cell = msg~load_ref(); ;; Load cell from slice msg\n    ;; do something\n}\n```\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [`begin_cell`](/languages/func/stdlib#begin-cell)\n- [`store_uint`](/languages/func/stdlib#store-uint)\n- [`end_cell`](/languages/func/stdlib#end-cell)\n- [`store_ref`](/languages/func/stdlib#store-ref)\n- [`begin_parse`](/languages/func/stdlib#begin-parse)\n- [`slice_refs_empty?`](/languages/func/stdlib#slice-refs-empty%3F)\n- [`load_ref`](/languages/func/stdlib#load-ref)\n\n### How to write a do until loop\n\nUse a [`do..until` loop](/languages/func/statements#until-loop) when the loop must execute at least once.\n\n```func\nint flag = 0;\n\ndo {\n    ;; iterate this as long as \"flag\" is false (0).\n    ;; It would execute at least once even if the flag\n    ;; were already true before entering the loop.\n} until (flag == -1); ;; Stop when \"flag\" becomes -1\n```\n\n## Cells and slices\n\n### How to determine if a slice is empty\n\nBefore working with a slice, checking whether it contains any data is essential to ensure proper processing.\nThe `slice_empty?` method can be used for this purpose. However, it returns `0` (`false`) if the slice contains at least one `bit` of data or one reference.\n\n```func\n;; Creating empty slice\nslice empty_slice = \"\";   ;; compile-time built-in \"\" produces a slice with no bits\n;; `slice_empty?()` returns `true` because the slice doesn't have any `bits` and `refs`.\nempty_slice.slice_empty?();\n\n;; Creating slice which contains bits only\nslice slice_with_bits_only = \"Hello, world!\";  ;; compile-time built-in produces a slice\n                                               ;; containing the ASCII binary code of the string\n;; `slice_empty?()` returns `false` because the slice has bits.\nslice_with_bits_only.slice_empty?();\n\n;; Create an empty dummy cell for use later\ncell dummy_cell = begin_cell().end_cell();\n\n;; Creating slice which contains refs only\nslice slice_with_refs_only = begin_cell()\n    .store_ref(dummy_cell)      ;; Add the dummy cell as a reference\n    .end_cell()                 ;; this creates the cell\n    .begin_parse();             ;; this creates a slice from the cell\n;; `slice_empty?()` returns `false` because the slice has cell references.\nslice_with_refs_only.slice_empty?();\n\n;; Creating slice which contains bits and refs\nslice slice_with_bits_and_refs = begin_cell()\n    .store_slice(\"Hello, world!\")   ;; Add bits from the slice computed\n                                    ;; using the compile-time built-in\n    .store_ref(dummy_cell)          ;; Add the dummy cell as a reference\n    .end_cell()\n    .begin_parse();\n;; `slice_empty?()` returns `false` because the slice has bits and references.\nslice_with_bits_and_refs.slice_empty?();\n```\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [`\"<ascii string>\"` compile-time builtin](/languages/func/literals#string-without-suffix), where `<ascii string>` is an ASCII string\n- [`slice_empty?`](/languages/func/stdlib#slice-empty%3F)\n- [`begin_cell`](/languages/func/stdlib#begin-cell)\n- [`end_cell`](/languages/func/stdlib#end-cell)\n- [`store_ref`](/languages/func/stdlib#store-ref)\n- [`begin_parse`](/languages/func/stdlib#begin-parse)\n- [`store_slice`](/languages/func/stdlib#store-slice)\n\n### How to determine if slice is empty (no bits, but may have refs)\n\nIf only the presence of bits matters and the cell references in the slice can be ignored, use the `slice_data_empty?` function.\n\n```func\n;; Creating empty slice\nslice empty_slice = \"\";   ;; compile-time built-in \"\" produces a slice with no bits\n;; `slice_data_empty?()` returns `true` because the slice doesn't have any bits.\nempty_slice.slice_data_empty?();\n\n;; Creating slice which contains bits only\nslice slice_with_bits_only = \"Hello, world!\";  ;; compile-time built-in produces a slice\n                                               ;; containing the ASCII binary code of the string\n;; `slice_data_empty?()` returns `false` because the slice has bits.\nslice_with_bits_only.slice_data_empty?();\n\n;; Create an empty dummy cell for use later\ncell dummy_cell = begin_cell().end_cell();\n\n;; Creating slice which contains refs only\nslice slice_with_refs_only = begin_cell()\n    .store_ref(dummy_cell)      ;; Add the dummy cell as a reference\n    .end_cell()                 ;; this creates the cell\n    .begin_parse();             ;; this creates a slice from the cell\n;; `slice_data_empty?()` returns `true` because the slice doesn't have any bits\nslice_with_refs_only.slice_data_empty?();\n\n;; Creating slice which contains bits and refs\nslice slice_with_bits_and_refs = begin_cell()\n    .store_slice(\"Hello, world!\")   ;; Add bits from the slice computed\n                                    ;; using the compile-time built-in\n    .store_ref(dummy_cell)          ;; Add the dummy cell as a reference\n    .end_cell()\n    .begin_parse();\n;; `slice_data_empty?()` returns `false` because the slice has bits.\nslice_with_bits_and_refs.slice_data_empty?();\n```\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [`\"<ascii string>\"` compile-time builtin](/languages/func/literals#string-without-suffix), where `<ascii string>` is an ASCII string.\n- [`slice_data_empty?`](/languages/func/stdlib#slice-data-empty%3F)\n- [`begin_cell`](/languages/func/stdlib#begin-cell)\n- [`end_cell`](/languages/func/stdlib#end-cell)\n- [`store_ref`](/languages/func/stdlib#store-ref)\n- [`begin_parse`](/languages/func/stdlib#begin-parse)\n- [`store_slice`](/languages/func/stdlib#store-slice)\n\n### How to determine if slice is empty (no refs, but may have bits)\n\nIf only cell references are of interest, their presence can be checked using the `slice_refs_empty?` function.\n\n```func\n;; Creating empty slice\nslice empty_slice = \"\";   ;; compile-time built-in \"\" produces a slice with no bits\n;; `slice_refs_empty?()` returns `true` because the slice doesn't have any cell references.\nempty_slice.slice_refs_empty?();\n\n;; Creating slice which contains bits only\nslice slice_with_bits_only = \"Hello, world!\";  ;; compile-time built-in produces a slice\n                                               ;; containing the ASCII binary code of the string\n;; `slice_refs_empty?()` returns `true` because the slice doesn't have any cell references.\nslice_with_bits_only.slice_refs_empty?();\n\n;; Create an empty dummy cell for use later\ncell dummy_cell = begin_cell().end_cell();\n\n;; Creating slice which contains refs only\nslice slice_with_refs_only = begin_cell()\n    .store_ref(dummy_cell)      ;; Add the dummy cell as a reference\n    .end_cell()                 ;; this creates the cell\n    .begin_parse();             ;; this creates a slice from the cell\n;; `slice_refs_empty?()` returns `false` because the slice has cell references.\nslice_with_refs_only.slice_refs_empty?();\n\n;; Creating slice which contains bits and refs\nslice slice_with_bits_and_refs = begin_cell()\n    .store_slice(\"Hello, world!\")   ;; Add bits from the slice computed\n                                    ;; using the compile-time built-in\n    .store_ref(dummy_cell)          ;; Add the dummy cell as a reference\n    .end_cell()\n    .begin_parse();\n;; `slice_refs_empty?()` returns `false` because the slice has cell references.\nslice_with_bits_and_refs.slice_refs_empty?();\n```\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [`\"<ascii string>\"` compile-time builtin](/languages/func/literals#string-without-suffix), where `<ascii string>` is an ASCII string.\n- [`slice_refs_empty?`](/languages/func/stdlib#slice-refs-empty%3F)\n- [`begin_cell`](/languages/func/stdlib#begin-cell)\n- [`end_cell`](/languages/func/stdlib#end-cell)\n- [`store_ref`](/languages/func/stdlib#store-ref)\n- [`begin_parse`](/languages/func/stdlib#begin-parse)\n- [`store_slice`](/languages/func/stdlib#store-slice)\n\n### How to determine if a cell is empty\n\nTo check whether a cell contains any data, it must first be converted into a slice.\n\n- If only the data bits matter, use `slice_data_empty?`.\n- If only cell references matter, use `slice_refs_empty?`.\n- If the presence of any data (bits or cell references) needs to be checked, use `slice_empty?`.\n\n```func\n;; Create an empty dummy cell for use later\ncell dummy_cell = begin_cell().end_cell();\n\ncell cell_with_bits_and_refs = begin_cell()\n    .store_uint(1337, 16)\n    .store_ref(dummy_cell)\n    .end_cell();\n\n;; To check that cell_with_bits_and_refs is empty,\n;; first obtain a slice\nslice cs = cell_with_bits_and_refs.begin_parse();\n\n;; Determine if the slice is empty.\nif (cs.slice_empty?()) {\n    ;; Cell is empty\n}\nelse {\n    ;; Cell is not empty\n}\n```\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [`begin_cell`](/languages/func/stdlib#begin-cell)\n- [`end_cell`](/languages/func/stdlib#end-cell)\n- [`store_ref`](/languages/func/stdlib#store-ref)\n- [`begin_parse`](/languages/func/stdlib#begin-parse)\n- [`slice_empty?`](/languages/func/stdlib#slice-empty%3F)\n- [`slice_data_empty?`](/languages/func/stdlib#slice-data-empty%3F)\n- [`slice_refs_empty?`](/languages/func/stdlib#slice-refs-empty%3F)\n\n### Determine if the data bits of slices are equal\n\nThere are three ways to check if the data bits of two slices are equal:\n\n1. Comparing their hashes.\n1. Using the SDEQ asm instruction.\n1. Using the `equal_slice_bits` function.\n\n```func\nint are_slices_equal_1? (slice a, slice b) {\n    return a.slice_hash() == b.slice_hash();\n}\n\nint are_slices_equal_2? (slice a, slice b) asm \"SDEQ\";\n\nint are_slices_equal_3? (slice a, slice b) {\n    return equal_slice_bits(a, b);\n}\n\n() main () {\n    slice s1 = \"Some text\";    ;; load a slice with the ASCII code of the string\n    slice s2 = \"Some text\";\n    ~dump(are_slices_equal_1?(s1, s2));  ;; -1 = true\n    ~dump(are_slices_equal_2?(s1, s2));  ;; -1 = true\n    ~dump(are_slices_equal_3?(s1, s2));  ;; -1 = true\n\n    s1 = \"Text\";\n    ;; load a slice with the address encoded in the provided string\n    s2 = \"EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPrHF\"a;\n    ~dump(are_slices_equal_1?(s1, s2));  ;; 0 = false\n    ~dump(are_slices_equal_2?(s1, s2));  ;; 0 = false\n    ~dump(are_slices_equal_3?(s1, s2));  ;; 0 = false\n}\n```\n\n<Aside\n  type=\"danger\"\n>\n  Ways 2 and 3 only check the data bits of the two slices, but way 1 **also** takes into account the cell references in the slices.\n  This means that if the two slices have the same data bits but different cell references, way 1 will answer `0` (`false`), but way 2 and 3 will answer `-1` (`true`).\n  For example, the following two slices have the same data bits, but different cell references.\n  Comparing their hashes would return `0` (`false`), but comparing them using `SDEQ` or `equal_slice_bits` would return `-1` (`true`).\n\n  ```func\n  ;; Create a dummy cell to add as a reference later\n  cell dummy = begin_cell().end_cell();\n\n  slice s1 = begin_cell()\n             .store_slice(\"Some text\")  ;; Add the slice data bits\n             .store_ref(dummy)          ;; Add a dummy reference\n             .end_cell()\n             .begin_parse();            ;; Transform the cell to slice\n\n  slice s2 = \"Some text\";      ;; This slice contains only data bits\n\n  ~dump(are_slices_equal_1?(s1, s2));  ;; 0 = false\n  ~dump(are_slices_equal_2?(s1, s2));  ;; -1 = true\n  ~dump(are_slices_equal_3?(s1, s2));  ;; -1 = true\n  ```\n</Aside>\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [`\"<ascii string>\"` compile-time builtin](/languages/func/literals#string-without-suffix), where `<ascii string>` is an ASCII string.\n- [`\"<address string>\"a` compile-time builtin](/languages/func/literals#string-with-suffix-a), where `<address string>` is a string encoding an address.\n- [`slice_hash`](/languages/func/stdlib#slice-hash)\n- [`SDEQ` asm instruction](/tvm/instructions#c705-sdeq)\n- `equal_slice_bits`\n\n### Determine if the cells are equal\n\nDetermine whether two cells are equal by comparing their hashes.\n\n```func\nint are_cells_equal? (cell a, cell b) {\n    return a.cell_hash() == b.cell_hash();\n}\n\n() main () {\n    cell a = begin_cell()\n            .store_uint(123, 16)\n            .end_cell();\n\n    cell b = begin_cell()\n            .store_uint(123, 16)\n            .end_cell();\n\n    ~dump(are_cells_equal?(a, b));   ;; -1 = true\n\n    cell dummy_cell = begin_cell().end_cell();\n\n    cell c = begin_cell()     ;; Like cell a, but it has an extra reference\n            .store_uint(123, 16)\n            .store_ref(dummy_cell)\n            .end_cell();\n\n    ~dump(are_cells_equal?(a, c));   ;; 0 = false\n}\n```\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [`cell_hash`](/languages/func/stdlib#cell-hash)\n- [`begin_cell`](/languages/func/stdlib#begin-cell)\n- [`end_cell`](/languages/func/stdlib#end-cell)\n- [`store_uint`](/languages/func/stdlib#store-uint)\n- [`store_ref`](/languages/func/stdlib#store-ref)\n\n### How to get only the data bits from a slice\n\nIf the cell references within a slice are not needed, the raw data bits can be extracted for further processing\nusing the function `preload_bits`:\n\n```func\n;; Define a slice with data bits and two cell references\nslice s = begin_cell()\n    .store_slice(\"Some data bits...\")\n    .store_ref(begin_cell().end_cell()) ;; some reference\n    .store_ref(begin_cell().end_cell()) ;; some reference\n    .end_cell()\n    .begin_parse();\n\n;; Extract the data bits as a new slice\nslice s_only_data = s.preload_bits(s.slice_bits());\n```\n\nFunction `preload_bits` requires as argument the amount of bits to extract.\n`s.slice_bits()` obtains the amount of data bits\nin the slice.\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [Builder primitives](/languages/func/stdlib#builder-primitives)\n- [Slice primitives](/languages/func/stdlib#slice-primitives)\n- [`preload_bits`](/languages/func/stdlib#preload-bits)\n- [`slice_bits`](/languages/func/stdlib#slice-bits)\n\n### How to build a `StateInit` cell\n\nThe code follows the TL-B for [`StateInit`](/foundations/messages/deploy):\n\n```\n_ split_depth:(Maybe (## 5)) special:(Maybe TickTock)\n  code:(Maybe ^Cell) data:(Maybe ^Cell)\n  library:(HashmapE 256 SimpleLib) = StateInit;\n```\n\nwhich states that `code` and `data` should be added as cell references.\nFields `split_depth` and `special` are usually set to `None` (i.e., `0`)\nin standard programming tasks. The `library` field usually set to `0` as well.\n\n```func\ncell build_stateinit(cell init_code, cell init_data) {\n  var state_init = begin_cell()\n    .store_uint(0, 1) ;; split_depth: Maybe (## 5), set to \"None\"\n    .store_uint(0, 1) ;; special: Maybe TickTock, set to \"None\"\n    .store_uint(1, 1) ;; code: Maybe ^Cell, set to \"Some cell\",\n                      ;; but the cell is provided later as a reference\n    .store_uint(1, 1) ;; data: Maybe ^Cell, set to \"Some cell\",\n                      ;; but the cell is provided later as a reference\n    .store_uint(0, 1) ;; library: HashmapE 256 SimpleLib, set to 0\n    .store_ref(init_code)  ;; the code as a cell reference\n    .store_ref(init_data)  ;; the data as a cell reference\n    .end_cell();\n    return state_int;\n}\n```\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [TL-B for `StateInit`](https://github.com/ton-blockchain/ton/blob/f58297f1b668c7b49e8b30b65062951ca7c18acc/crypto/block/block.tlb#L144-L146)\n- [Builder primitives](/languages/func/stdlib#builder-primitives)\n\n## Data structures\n\n### How to determine if a dict is empty\n\nThe `dict_empty?` function checks whether a dictionary contains any data.\nThis method is functionally equivalent to `cell_null?`, as a `null` cell typically represents an empty dictionary.\n\n```func\ncell d = new_dict();    ;; Create an empty dictionary\n\n;; Set value of key 0 to be a slice containing the ASCII string \"hello\"\nd~udict_set(256, 0, \"hello\");\n;; Set value of key 1 to be a slice containing the ASCII string \"world\"\nd~udict_set(256, 1, \"world\");\n\nif (d.dict_empty?()) { ;; Determine if the dict is empty\n    ;; dict is empty\n}\nelse {\n    ;; dict is not empty.\n    ;; For dictionary d, execution flow will enter this\n    ;; branch, since d has two elements.\n}\n```\n\nIn `d~udict_set(256, 0, \"hello\")`, the function expects unsigned 256-bit integers as keys; also,\n`d~udict_set(256, 0, \"hello\")` will mutate the dictionary `d`, since `udict_set` is called using\n[modifying notation with the symbol `~`](/languages/func/expressions#modifying-notation).\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [Modifying notation using \\~](/languages/func/expressions#modifying-notation)\n- [`\"<ascii string>\"` compile-time builtin](/languages/func/literals#string-without-suffix), where `<ascii string>` is an ASCII string.\n- [`new_dict`](/languages/func/stdlib#new-dict)\n- [`dict_set` primitives](/languages/func/stdlib#dict-set)\n- [`dict_empty?`](/languages/func/stdlib#dict-empty%3F)\n\n### How to store and load a dictionary in permanent storage\n\nThe logic for loading a dictionary from local storage is as follows:\n\n```func\n;; Obtain the contract's local persistent storage\nslice local_storage = get_data().begin_parse();\n\n;; This initial assignment ensures that if the condition below\n;; fails to find a dictionary already in local storage,\n;; `dictionary_cell` will remain with a new empty dictionary.\ncell dictionary_cell = new_dict();\n\nif (~ slice_empty?(local_storage)) {\n    ;; A dictionary is already in local storage, load it\n    dictionary_cell = local_storage~load_dict();\n}\n```\n\nStoring the dictionary in local storage is also simple:\n\n```func\nset_data(begin_cell().store_dict(dictionary_cell).end_cell());\n```\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [Modifying notation using \\~](/languages/func/expressions#modifying-notation)\n- [Slice primitives](/languages/func/stdlib#slice-primitives)\n- [`get_data`](/languages/func/stdlib#get-data)\n- [`set_data`](/languages/func/stdlib#set-data)\n- [Builder primitives](/languages/func/stdlib#builder-primitives)\n- [`new_dict`](/languages/func/stdlib#new-dict)\n- [`slice_empty?`](/languages/func/stdlib#slice-empty%3F)\n- [`load_dict`](/languages/func/stdlib#load-dict)\n\n### How to iterate dictionaries\n\nTo iterate a dictionary from the smallest to biggest key, first call a [`dict_get_min?` primitive](/languages/func/stdlib#dict-get-min%3F) to obtain the smallest key in the dictionary,\nand then call a [`dict_get_next?` primitive](/languages/func/stdlib#dict-get-next%3F) inside a loop while checking a flag for existence of further key-value pairs to process.\n\nSimilarly, to iterate a dictionary from the biggest to smallest key, first call a [`dict_get_max?` primitive](/languages/func/stdlib#dict-get-max%3F) to obtain the biggest key in the dictionary,\nand then call a [`dict_get_prev?` primitive](/languages/func/stdlib#dict-get-prev%3F) inside a loop while checking a flag for existence of further key-value pairs to process.\n\n```func\n;; Initialize an example dictionary.\n;; keys will be unsigned 256-bit integers. Values are slices.\n;; Since keys are unsigned,\n;; should use 'unsigned' versions of the\n;; dict_set, dict_get_min?, dict_get_max?,\n;; dict_get_next?, and dict_get_prev? primitives.\ncell d = new_dict();\nd~udict_set(256, 1, \"value 1\");   ;; Map key 1 to a slice containing string \"value 1\"\nd~udict_set(256, 5, \"value 2\");   ;; Map key 5 to a slice containing string \"value 2\"\nd~udict_set(256, 12, \"value 3\");  ;; Map key 12 to a slice containing string \"value 3\"\n\n;; First, iterate from smallest to biggest key:\n\n;; Obtain the smallest key.\n(int key, slice val, int flag) = d.udict_get_min?(256);\n\n;; Repeat while there are keys to iterate, indicated by \"flag\".\nwhile (flag) {\n    ;; do something with \"key\" and \"val\".\n\n    ;; Obtain the smallest key bigger than \"key\".\n    ;; i.e., the one next to \"key\" in numerical value.\n    ;; \"flag\" will indicate if such key exists.\n    (key, val, flag) = d.udict_get_next?(256, key);\n}\n\n;; Now, iterate from biggest to smallest key:\n\n;; Obtain the biggest key.\n(key, val, flag) = d.udict_get_max?(256);\n\n;; Repeat while there are keys to iterate, indicated by \"flag\".\nwhile (flag) {\n    ;; do something with \"key\" and \"val\".\n\n    ;; Obtain the biggest key smaller than \"key\",\n    ;; i.e., the one previous to \"key\" in numerical value.\n    ;; \"flag\" will indicate if there is a previous key.\n    (key, val, flag) = d.udict_get_prev?(256, key);\n}\n```\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [Modifying notation using \\~](/languages/func/expressions#modifying-notation)\n- [`\"<ascii string>\"` compile-time builtin](/languages/func/literals#string-without-suffix), where `<ascii string>` is an ASCII string.\n- [`new_dict`](/languages/func/stdlib#new-dict)\n- [`dict_set` primitives](/languages/func/stdlib#dict-set)\n- [`dict_get_min?` primitives](/languages/func/stdlib#dict-get-min%3F)\n- [`dict_get_max?` primitives](/languages/func/stdlib#dict-get-max%3F)\n- [`dict_get_next?` primitives](/languages/func/stdlib#dict-get-next%3F)\n- [`dict_get_prev?` primitives](/languages/func/stdlib#dict-get-prev%3F)\n\n### How to delete a value from a dictionary\n\nUse the [`dict_delete?` primitives](/languages/func/stdlib#dict-delete%3F) to delete keys in a dictionary.\n\n```func\n;; Initialize an example dictionary.\n;; keys will be unsigned 256-bit integers. Values are slices.\n;; Since keys are unsigned,\n;; should use 'unsigned' versions of the\n;; dict_set, dict_delete?, dict_get? primitives.\ncell names = new_dict();\nnames~udict_set(256, 27, \"Alice\");  ;; Map key 27 to a slice containing string \"Alice\"\nnames~udict_set(256, 25, \"Bob\");\n\n;; Delete key-value pair with key 27\n;; This mutates \"names\" dictionary, because\n;; udict_delete? is called using ~\nnames~udict_delete?(256, 27);\n\n;; Look up the key 27\n;; since it was deleted, the \"found\" flag returns 0\n(slice val, int found) = names.udict_get?(256, 27);\n~dump(found);   ;; 0, means that key was not found in the dictionary\n```\n\n**References:**\n\n- [`\"<ascii string>\"` compile-time builtin](/languages/func/literals#string-without-suffix), where `<ascii string>` is an ASCII string.\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [Modifying notation using \\~](/languages/func/expressions#modifying-notation)\n- [`new_dict`](/languages/func/stdlib#new-dict)\n- [`dict_set` primitives](/languages/func/stdlib#dict-set)\n- [`dict_delete?` primitives](/languages/func/stdlib#dict-delete%3F)\n- [`dict_get?` primitives](/languages/func/stdlib#dict-get%3F)\n\n### How to determine if a tuple is empty\n\nWhen working with `tuples`, checking for existing values before extracting them is crucial.\nExtracting a value from an empty tuple will result in an error: [\"not a tuple of valid size\" - `exit code 7`](/tvm/exit-codes#7).\n\n```func\n;; Declare the tlen assembler function because it's not present in stdlib\n;; tlen determines the length of a tuple\nint tlen (tuple t) asm \"TLEN\";\n\n() main () {\n    tuple t = empty_tuple();  ;; t is []\n    t~tpush(13);              ;; t is [13]\n    t~tpush(37);              ;; t is [13, 37]\n\n    if (t.tlen() == 0) {   ;; Evaluates to false\n        ;; tuple is empty\n    }\n    else {\n        ;; tuple is not empty\n    }\n}\n```\n\nThe `tlen` [assembler function](/languages/func/asm-functions) uses\nthe [TVM instruction `TLEN`](/tvm/instructions#6f88-tlen) to determine the number of elements in the tuple.\nThe `tpush` function appends an element to the tuple, so that it becomes the last element.\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [Modifying notation using \\~](/languages/func/expressions#modifying-notation)\n- [Assembler functions](/languages/func/asm-functions)\n- [`empty_tuple`](/languages/func/stdlib#empty-tuple)\n- [`tpush`](/languages/func/stdlib#tpush)\n- [TVM Exit codes](/tvm/exit-codes)\n- [TVM instructions](/tvm/instructions)\n\n### Basic operations with tuples\n\n```func\n;; tlen determines the length of a tuple\nint tlen (tuple t) asm \"TLEN\";\n\n;; tpop removes the last element in the tuple and\n;; returns the mutated tuple and the element.\n;; The type of the returned element is arbitrary.\nforall X -> (tuple, X) ~tpop (tuple t) asm \"TPOP\";\n\n() main () {\n    ;; creating an empty tuple\n    tuple names = empty_tuple();\n\n    ;; push new items\n    ;; Each element is a slice storing an ASCII string\n    names~tpush(\"Naito\");\n    names~tpush(\"Shiraki\");\n    names~tpush(\"Akamatsu\");\n    names~tpush(\"Takaki\");\n\n    ;; names is [\"Naito\", \"Shiraki\", \"Akamatsu\", \"Takaki\"]\n\n    ;; pop last item, \"Takaki\"\n    slice last_name = names~tpop();\n\n    ;; get first item, \"Naito\"\n    slice first_name = names.first();\n\n    ;; get an item by index, \"Akamatsu\"\n    ;; First element has index 0\n    slice best_name = names.at(2);\n\n    ;; getting the length of the tuple\n    ;; returns 3, because \"Takaki\" was popped\n    int number_names = names.tlen();\n}\n```\n\nThe `tlen` [assembler function](/languages/func/asm-functions) uses the [TVM instruction `TLEN`](/tvm/instructions#6f88-tlen) to determine the number of elements in the tuple.\n\nThe `tpop` assembler function uses the [TVM instruction `TPOP`](/tvm/instructions#6f8d-tpop) to detach the last element from the tuple, and\nit returns the mutated tuple and the detached element.\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [Modifying notation using \\~](/languages/func/expressions#modifying-notation)\n- [Assembler functions](/languages/func/asm-functions)\n- [Polymorphic functions](/languages/func/functions#forall-declarator)\n- [`empty_tuple`](/languages/func/stdlib#empty-tuple)\n- [`tpush`](/languages/func/stdlib#tpush)\n- [`first`](/languages/func/stdlib#first)\n- [`at`](/languages/func/built-ins/#at)\n- [TVM instructions](/tvm/instructions)\n\n### How to iterate tuples (both directions)\n\nWhen working with arrays or stacks in FunC, tuples are essential. The first step is learning how to iterate through tuple values for processing.\n\n```func\n;; tlen determines the length of a tuple\nint tlen (tuple t) asm \"TLEN\";\n\n;; Casts any type into a tuple\nforall X -> tuple to_tuple (X x) asm \"NOP\";\n\n() main () {\n    ;; Cast the fixed length tuple to an arbitrary length tuple.\n    ;; This is necessary, because in FunC, fixed-length tuples\n    ;; like [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] cannot be assigned\n    ;; directly to arbitrary length tuples.\n    ;; Hence, this does NOT compile:\n    ;; tuple t = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n    tuple t = to_tuple([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);\n    int len = t.tlen();   ;; 10\n\n    ;; Iterate tuple starting from index 0\n    ;; up to index 9\n\n    int i = 0;\n    while (i < len) {\n        int x = t.at(i);    ;; Obtain the i-th element\n        ;; do something with x\n        i = i + 1;\n    }\n\n    ;; Iterate tuple starting from index 9\n    ;; down to index 0\n\n    i = len - 1;   ;; 9\n    while (i >= 0) {\n        int x = t.at(i);    ;; Obtain the i-th element\n        ;; do something with x\n        i = i - 1;\n    }\n}\n```\n\nThe `tlen` [assembler function](/languages/func/asm-functions) uses the [TVM instruction `TLEN`](/tvm/instructions#6f88-tlen) to determine the number of elements in the tuple.\n\nThe `to_tuple` casts **any** type into an arbitrary length tuple, which leads to run-time errors if `to_tuple` is used to cast non-tuple types.\nBe careful to only cast fixed-length tuples, like `[1, 2]`. The `to_tuple` is essentially a dummy function that does nothing,\nbecause it uses the [No operation `NOP`](/tvm/instructions#00-nop) instruction. The only purpose of `to_tuple` is to tell the type-checker\nto accept the input to `to_tuple` as a `tuple`.\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [Assembler functions](/languages/func/asm-functions)\n- [Polymorphic functions](/languages/func/functions#forall-declarator)\n- [`at`](/languages/func/built-ins/#at)\n- [TVM instructions](/tvm/instructions)\n\n### Iterating n-nested tuples\n\nSometimes, while traversing the elements of a tuple, there is the need to iterate through nested tuples.\nThe following example iterates through a tuple starting from the last index,\nand finds the biggest number, irrespective if there are nested tuples.\n\nFor example, in the tuple `[[2,6],[1,[3,[3,5]]], 3]`, the example finds `6` as the biggest number.\n\n```func\n;; Determines the number of elements in a tuple.\nint tuple_length (tuple t) asm \"TLEN\";\n\n;; Removes the last element in the tuple and\n;; returns the mutated tuple and the element.\n;; The type of the returned element is arbitrary.\nforall X -> (tuple, X) ~tpop (tuple t) asm \"TPOP\";\n\n;; Checks if the given argument is a tuple\nforall X -> int is_tuple (X x) asm \"ISTUPLE\";\n\n;; Casts the given argument to an arbitrary length tuple.\nforall X -> tuple to_tuple (X x) asm \"NOP\";\n\n;; Casts the given argument to an int.\nforall X -> int to_int (X x) asm \"NOP\";\n\n;; Define a global variable.\n;; It will store the biggest number found.\nglobal int max_value;\n\n() iterate_tuple (tuple t) impure {\n    repeat (t.tuple_length()) {\n        ;; Remove the last element in the tuple.\n        var value = t~tpop();\n        if (is_tuple(value)) {\n            ;; If the element is a tuple, cast it to a tuple.\n            tuple tuple_value = to_tuple(value);\n            ;; And then, recursively iterate the element.\n            iterate_tuple(tuple_value);\n        } else {\n            ;; The element is not a tuple, so it must be an int.\n            ;; Cast it to an int.\n            int int_value = to_int(value);\n            if (int_value > max_value) {\n                ;; Remember the value in the global variable\n                ;; because it is the biggest so far.\n                max_value = int_value;\n            }\n        }\n    }\n}\n\n() main () {\n    ;; Create an example tuple\n    tuple t = to_tuple([[2,6], [1, [3, [3, 5]]], 3]);\n\n    ;; Determine the length of the tuple\n    int len = t.tuple_length();\n\n    ;; Set the maximum so far to 0\n    max_value = 0;\n\n    ;; Find the maximum value in the tuple\n    iterate_tuple(t);\n\n    ~dump(max_value);    ;; 6\n}\n```\n\nThe `tuple_length` [assembler function](/languages/func/asm-functions) uses the [TVM instruction `TLEN`](/tvm/instructions#6f88-tlen) to determine the number of elements in the tuple.\n\nThe `tpop` assembler function uses the [TVM instruction `TPOP`](/tvm/instructions#6f8d-tpop) to detach the last element from the tuple, and\nit returns the mutated tuple and the detached element.\n\nThe `is_tuple` assembler function uses the [TVM instruction `ISTUPLE`](/tvm/instructions#6f8a-istuple) to determine if the argument is a tuple or not.\n\nThe `to_tuple` and `to_int` cast **any** type into an arbitrary length tuple and integer, respectively. This leads to run-time errors if\n`to_tuple` and `to_int` are used to cast non-tuple and non-integer types, respectively. The `to_tuple` and `to_int` are essentially dummy functions that do nothing,\nbecause they use the [No operation `NOP`](/tvm/instructions#00-nop) instruction. The only purpose of `to_tuple` and `to_int` is to tell the type-checker\nto accept the input to `to_tuple` as a `tuple`, and the input to `to_int` as an `int`.\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [Modifying notation using \\~](/languages/func/expressions#modifying-notation)\n- [Assembler functions](/languages/func/asm-functions)\n- [Polymorphic functions](/languages/func/functions#forall-declarator)\n- [Global Variables](/languages/func/global-variables)\n- [TVM instructions](/tvm/instructions)\n\n### Casting types in tuples\n\nIf a tuple contains various data types `[cell, slice, int, tuple, ...]`, there is the need to check the value and cast it accordingly before processing.\nThe following snippet illustrates this idea.\n\n```func\n;; Check if argument is null\nforall X -> int is_null (X x) asm \"ISNULL\";\n\n;; Check if argument is an int\nforall X -> int is_int (X x) asm \"<{ TRY:<{ 0 PUSHINT ADD DROP -1 PUSHINT }>CATCH<{ 2DROP 0 PUSHINT }> }>CONT 1 1 CALLXARGS\";\n\n;; Check if argument is a cell\nforall X -> int is_cell (X x) asm \"<{ TRY:<{ CTOS DROP -1 PUSHINT }>CATCH<{ 2DROP 0 PUSHINT }> }>CONT 1 1 CALLXARGS\";\n\n;; Check if argument is a slice\nforall X -> int is_slice (X x) asm \"<{ TRY:<{ SBITS DROP -1 PUSHINT }>CATCH<{ 2DROP 0 PUSHINT }> }>CONT 1 1 CALLXARGS\";\n\n;; Check if argument is a tuple\nforall X -> int is_tuple (X x) asm \"ISTUPLE\";\n\n;; Cast functions. They do not carry an operation,\n;; since they use the \"NOP\" TVM instruction.\n;; Their sole purpose is to tell the type-checker\n;; that it should see the argument as having\n;; the desired type.\nforall X -> int cast_to_int (X x) asm \"NOP\";\nforall X -> cell cast_to_cell (X x) asm \"NOP\";\nforall X -> slice cast_to_slice (X x) asm \"NOP\";\nforall X -> tuple cast_to_tuple (X x) asm \"NOP\";\n\n;; Removes the last element in the tuple and\n;; returns the mutated tuple and the element.\n;; The type of the returned element is arbitrary.\nforall X -> (tuple, X) ~tpop (tuple t) asm \"TPOP\";\n\n;; Process value of arbitrary type\nforall X -> () resolve_type (X value) impure {\n\n    ;; \"value\" has an arbitrary type.\n    ;; Check its type and cast it.\n\n    if (is_null(value)) {\n        ;; Do something with the null.\n    } elseif (is_int(value)) {\n        int valueAsInt = cast_to_int(value);\n        ;; Do something with the int.\n    } elseif (is_slice(value)) {\n        slice valueAsSlice = cast_to_slice(value);\n        ;; Do something with the slice.\n    } elseif (is_cell(value)) {\n        cell valueAsCell = cast_to_cell(value);\n        ;; Do something with the cell.\n    } elseif (is_tuple(value)) {\n        tuple valueAsTuple = cast_to_tuple(value);\n        ;; Do something with the tuple.\n    }\n}\n\n() main () {\n    ;; Create an initially empty tuple.\n    tuple t = empty_tuple();\n    ;; Add some values of different types to the tuple.\n    t~tpush(\"Some text\");\n    t~tpush(4);\n    ;; The tuple is [\"Some text\", 4].\n\n    ;; Since the tuple has values of different types,\n    ;; when extracting an element, use the\n    ;; keyword \"var\".\n    var value = t~tpop();\n\n    ;; Process the value.\n    resolve_type(value);\n}\n```\n\nThe `is_int` function uses [Fift code](/languages/fift/overview). Intuitively, the Fift code implements the\nfollowing FunC-like pseudocode:\n\n```func\nforall X -> int is_int (X x) {\n    try {\n        ;; Attempt to add 0 to the argument x.\n        ;; If this fails, then x is not an integer.\n        x + 0;\n        return -1;\n    } catch (_, _) {\n        return 0;\n    }\n}\n```\n\nSimilarly, the `is_cell` carries out the following FunC-like pseudocode, which makes use\nof the [CTOS TVM instruction](/tvm/instructions#d0-ctos):\n\n```func\nforall X -> int is_cell (X x) {\n    try {\n        ;; Under the assumption that x is a cell,\n        ;; CTOS will attempt to get a slice from cell x.\n        ;; If x turns out to be not a cell, CTOS will fail.\n        CTOS(x);\n        return -1;\n    } catch (_, _) {\n        return 0;\n    }\n}\n```\n\nFinally, the `is_slice` carries out the following FunC-like pseudocode, which makes use\nof the [SBITS TVM instruction](/tvm/instructions#d749-sbits):\n\n```func\nforall X -> int is_slice (X x) {\n    try {\n        ;; Under the assumption that x is a slice,\n        ;; SBITS will attempt to get the number of data bits\n        ;; in the slice.\n        ;; If x turns out to be not a slice, SBITS will fail.\n        SBITS(x);\n        return -1;\n    } catch (_, _) {\n        return 0;\n    }\n}\n```\n\n**References:**\n\n- [Modifying notation using \\~](/languages/func/expressions#modifying-notation)\n- [Assembler functions](/languages/func/asm-functions)\n- [Polymorphic functions](/languages/func/functions#forall-declarator)\n- [`empty_tuple`](/languages/func/stdlib#empty-tuple)\n- [`tpush`](/languages/func/stdlib#tpush)\n- [TVM instructions](/tvm/instructions)\n\n### Reversing tuples\n\nThe following example reverses any tuple. For example, given the input `[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]`,\nthe `reverse_tuple` produces the output `[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]`.\n\n```func\n;; Determines the number of elements in a tuple.\nint tuple_length (tuple t) asm \"TLEN\";\n\n;; Removes the last element in the tuple and\n;; returns the mutated tuple and the element.\n;; The type of the returned element is arbitrary.\nforall X -> (tuple, X) ~tpop (tuple t) asm \"TPOP\";\n\n;; Casts the given argument to an arbitrary length tuple.\nforall X -> tuple to_tuple (X x) asm \"NOP\";\n\ntuple reverse_tuple (tuple t1) {\n    ;; Create an initially empty tuple.\n    ;; This variable will be the accumulated result.\n    tuple t2 = empty_tuple();\n\n    repeat (t1.tuple_length()) {\n        ;; Take the last element in the original tuple.\n        var value = t1~tpop();\n        ;; And append it to the new tuple.\n        t2~tpush(value);\n    }\n    return t2;\n}\n\n() main () {\n    ;; Create an example tuple.\n    tuple t = to_tuple([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);\n\n    ;; Reverse the tuple.\n    tuple reversed_t = reverse_tuple(t);\n\n    ~dump(reversed_t); ;; [10 9 8 7 6 5 4 3 2 1]\n}\n```\n\nThe `tuple_length` [assembler function](/languages/func/asm-functions) uses the [TVM instruction `TLEN`](/tvm/instructions#6f88-tlen) to determine the number of elements in the tuple.\n\nThe `tpop` assembler function uses the [TVM instruction `TPOP`](/tvm/instructions#6f8d-tpop) to detach the last element from the tuple, and\nit returns the mutated tuple and the detached element.\n\nThe `to_tuple` casts **any** type into an arbitrary length tuple, which leads to run-time errors if `to_tuple` is used to cast non-tuple types.\nThe `to_tuple` is essentially a dummy function that does nothing,\nbecause it uses the [No operation `NOP`](/tvm/instructions#00-nop) instruction. The only purpose of `to_tuple` is to tell the type-checker\nto accept the input to `to_tuple` as a `tuple`.\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [Modifying notation using \\~](/languages/func/expressions#modifying-notation)\n- [Assembler functions](/languages/func/asm-functions)\n- [Polymorphic functions](/languages/func/functions#forall-declarator)\n- [`empty_tuple`](/languages/func/stdlib#empty-tuple)\n- [`tpush`](/languages/func/stdlib#tpush)\n- [TVM instructions](/tvm/instructions)\n\n### How to remove an item with a certain index from a tuple\n\n```func\n;; Determines the number of elements in a tuple.\nint tlen (tuple t) asm \"TLEN\";\n\n(tuple, ()) remove_item (tuple old_tuple, int place) {\n\n    ;; The result tuple so far. Initially it is empty.\n    tuple new_tuple = empty_tuple();\n\n    int i = 0;\n    while (i < old_tuple.tlen()) {\n        int el = old_tuple.at(i);\n        ;; When the place to delete is reached, skip\n        ;; that element by not pushing it to the result tuple.\n        if (i != place) {\n            ;; Since the current index i is not equal to\n            ;; the place to delete, push the element to\n            ;; the end of the result tuple.\n            new_tuple~tpush(el);\n        }\n        i += 1;\n    }\n    return (new_tuple, ());\n}\n\n() main () {\n    ;; Create an example tuple, intially empty\n    tuple numbers = empty_tuple();\n\n    ;; Insert some integers to the tuple\n    numbers~tpush(19);\n    numbers~tpush(999);\n    numbers~tpush(54);\n\n    ~dump(numbers);   ;; [19 999 54]\n\n    numbers~remove_item(1);\n\n    ~dump(numbers); ;; [19 54]\n}\n```\n\nThe `tlen` [assembler function](/languages/func/asm-functions) uses the [TVM instruction `TLEN`](/tvm/instructions#6f88-tlen) to determine the number of elements in the tuple.\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [Modifying notation using \\~](/languages/func/expressions#modifying-notation)\n- [Assembler functions](/languages/func/asm-functions)\n- [`empty_tuple`](/languages/func/stdlib#empty-tuple)\n- [`at`](/languages/func/built-ins/#at)\n- [`tpush`](/languages/func/stdlib#tpush)\n- [TVM instructions](/tvm/instructions)\n\n### Determine if tuples are equal\n\nThe approach involves iterating through both tuples and comparing each value recursively.\nSince tuples can contain different data types, check types and cast values dynamically.\n\n```func\n;; Determines the number of elements in a tuple.\nint tuple_length (tuple t) asm \"TLEN\";\n\n;; Removes the last element in the tuple and\n;; returns the mutated tuple and the element.\n;; The type of the returned element is arbitrary.\nforall X -> (tuple, X) ~tpop (tuple t) asm \"TPOP\";\n\n;; Cast functions. They do not carry an operation,\n;; since they use the \"NOP\" TVM instruction.\n;; Their sole purpose is to tell the type-checker\n;; that it should see the argument as having\n;; the desired type.\nforall X -> int cast_to_int (X x) asm \"NOP\";\nforall X -> cell cast_to_cell (X x) asm \"NOP\";\nforall X -> slice cast_to_slice (X x) asm \"NOP\";\nforall X -> tuple cast_to_tuple (X x) asm \"NOP\";\n\n;; Check if argument is null.\nforall X -> int is_null (X x) asm \"ISNULL\";\n\n;; Check if argument is an int.\nforall X -> int is_int (X x) asm \"<{ TRY:<{ 0 PUSHINT ADD DROP -1 PUSHINT }>CATCH<{ 2DROP 0 PUSHINT }> }>CONT 1 1 CALLXARGS\";\n\n;; Check if argument is a cell.\nforall X -> int is_cell (X x) asm \"<{ TRY:<{ CTOS DROP -1 PUSHINT }>CATCH<{ 2DROP 0 PUSHINT }> }>CONT 1 1 CALLXARGS\";\n\n;; Check if argument is a slice.\nforall X -> int is_slice (X x) asm \"<{ TRY:<{ SBITS DROP -1 PUSHINT }>CATCH<{ 2DROP 0 PUSHINT }> }>CONT 1 1 CALLXARGS\";\n\n;; Check if argument is a tuple.\nforall X -> int is_tuple (X x) asm \"ISTUPLE\";\n\n;; Determine if two slices are equal,\n;; by using the TVM instruction SDEQ.\nint are_slices_equal? (slice a, slice b) asm \"SDEQ\";\n\n;; Determine if two cells are equal by using their hashes.\nint are_cells_equal? (cell a, cell b) {\n    return a.cell_hash() == b.cell_hash();\n}\n\n(int) are_tuples_equal? (tuple t1, tuple t2) {\n    int equal? = -1; ;; initial value to true\n\n    if (t1.tuple_length() != t2.tuple_length()) {\n        ;; if tuples differ in length, they cannot be equal\n        return 0;\n    }\n\n    ;; At this point, both tuples have the same length\n\n    int i = t1.tuple_length();\n\n    ;; Iterate the tuples back to front,\n    ;; comparing corresponding elements at each iteration.\n    ;; Iterate while there are still elements to check\n    ;; in the tuples, and they remain equal.\n    ;; Recall that the AND boolean operator\n    ;; is emulated using the bitwise AND operator.\n    while (i > 0 & equal?) {\n\n        ;; Take the last element of both tuples\n        ;; and remove them from the tuples.\n        ;; This updates the tuples implicitly.\n        var v1 = t1~tpop();\n        var v2 = t2~tpop();\n\n        ;; Check the types of both elements.\n        ;; If they have different types, the\n        ;; execution will enter the \"else\" branch,\n        ;; marking the \"equal?\" flag to false.\n        ;; However, if they have the same type,\n        ;; check that their values\n        ;; are equal or not.\n        if (is_null(v1) & is_null(v2)) {\n            ;; nulls are always equal\n        } elseif (is_int(v1) & is_int(v2)) {\n            if (cast_to_int(v1) != cast_to_int(v2)) {\n                equal? = 0;\n            }\n        } elseif (is_slice(v1) & is_slice(v2)) {\n            if (~ are_slices_equal?(cast_to_slice(v1), cast_to_slice(v2))) {\n                equal? = 0;\n            }\n        } elseif (is_cell(v1) & is_cell(v2)) {\n            if (~ are_cells_equal?(cast_to_cell(v1), cast_to_cell(v2))) {\n                equal? = 0;\n            }\n        } elseif (is_tuple(v1) & is_tuple(v2)) {\n            ;; recursively determine nested tuples\n            if (~ are_tuples_equal?(cast_to_tuple(v1), cast_to_tuple(v2))) {\n                equal? = 0;\n            }\n        } else {\n            equal? = 0;\n        }\n\n        ;; Decrease the counter\n        i -= 1;\n    }\n\n    return equal?;\n}\n\n() main () {\n    ;; Create two equal tuples\n    tuple t1 = cast_to_tuple([[2, 6], [1, [3, [3, 5]]], 3]);\n    tuple t2 = cast_to_tuple([[2, 6], [1, [3, [3, 5]]], 3]);\n\n    ;; are_tuples_equal? returns -1, i.e., true\n    ~dump(are_tuples_equal?(t1, t2));\n}\n```\n\nFor function `are_slices_equal?` refer to recipe [\"Determine if the data bits of slices are equal\"](#determine-if-the-data-bits-of-slices-are-equal).\nFor function `are_cells_equal?` refer to recipe [\"Determine if the cells are equal\"](#determine-if-the-cells-are-equal).\nFor explanation of the functions that check types, refer to the recipe [\"Casting types in tuples\"](#casting-types-in-tuples).\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [Modifying notation using \\~](/languages/func/expressions#modifying-notation)\n- [Assembler functions](/languages/func/asm-functions)\n- [Polymorphic functions](/languages/func/functions#forall-declarator)\n- [`tpush`](/languages/func/stdlib#tpush)\n- [TVM instructions](/tvm/instructions)\n\n### Basic operations in lisp-style lists\n\n[Lisp-style lists](/languages/func/stdlib#lisp-style-lists) are represented as nested tuples. For example, the list `1, 2, 3` is represented as the\nnested tuple `[1, [2, [3, null]]]`, where the value `null` acts as a marker for the end of the list.\n\nUse the [`cons`](/languages/func/stdlib#cons) function to add an element at the front of the provided list. For example,\nif `lst` is the list `2, 3`, then `cons(1, lst)` is the list `1, 2, 3`. Internally, `cons(1, lst)` builds the tuple `[1, lst]`, where\n`lst` is the tuple `[2, [3, null]]`.\n\nThe [`null?`](/languages/func/built-ins#null%3F) function checks if the provided argument is the `null` value, or equivalently, the empty list.\n\nThe following snippet illustrates these functions:\n\n```func\n;; An initially empty list.\n;; \"null\" represents the empty list.\n;; The null value is obtained by calling the null() function.\ntuple numbers = null();\n\n;; Attach 100 as first element of the list\nnumbers = cons(100, numbers);\n;; Attach 200 as first element of the list,\n;; now 100 is the second element of the list\nnumbers = cons(200, numbers);\n;; \"numbers\" is the list: 200, 100.\n;; Or equivalently, the tuple: [200, [100, null]]\n\n;; Is the list null or equivalently, empty?\nif (numbers.null?()) {\n    ;; list-style list is empty\n} else {\n    ;; list-style list is not empty\n}\n```\n\n**References:**\n\n- [Lisp-style lists](/languages/func/stdlib#lisp-style-lists)\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [`cons`](/languages/func/stdlib#cons)\n- [`null`](/languages/func/stdlib#null)\n- [`null?`](/languages/func/built-ins#null%3F)\n\n### How to iterate through a lisp-style list\n\nAs described in the recipe [\"Basic operations in lisp-style lists\"](#basic-operations-in-lisp-style-lists),\n[Lisp-style lists](/languages/func/stdlib#lisp-style-lists) are represented as nested tuples.\n\nIt is possible to iterate a lisp-style list by using the function [`list-next`](/languages/func/stdlib#list-next),\nwhich returns the head of the list and the rest of the list. The following snippet illustrates its usage.\n\n```func\n() main () {\n    ;; Create an example list.\n    ;; Initially it is empty, indicated\n    ;; by the null value.\n    tuple l = null();\n    l = cons(1, l);\n    l = cons(2, l);\n    l = cons(3, l);\n    ;; Here, l is the list 3, 2, 1,\n    ;; or [3, [2, [1, null]]]\n\n    ;; Iterate the list\n    ;; while the list is not empty\n    while (~ l.null?()) {\n\n        ;; Store the list's head in x\n        ;; and update variable l so that it now\n        ;; contains the rest of the list\n        var x = l~list_next();\n\n        ;; Do something with x\n    }\n}\n```\n\n**References:**\n\n- [Lisp-style lists](/languages/func/stdlib#lisp-style-lists)\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [Modifying notation using \\~](/languages/func/expressions#modifying-notation)\n- [`cons`](/languages/func/stdlib#cons)\n- [`null`](/languages/func/stdlib#null)\n- [`null?`](/languages/func/built-ins#null%3F)\n- [`list_next`](/languages/func/stdlib#list-next)\n\n### How to iterate a cell tree\n\nEach cell can store up to `1023` bits of data and `4` cell references. Therefore, it is possible to represent\ncomplex tree structures by linking cells using cell references.\n\nGiven a tree of cells, use any [tree traversal algorithm](https://en.wikipedia.org/wiki/Tree_traversal)\nto access each cell in the tree. For example, the snippet below uses the\n[iterative version of pre-order traversal](https://en.wikipedia.org/wiki/Tree_traversal#Pre-order_implementation),\nwhich makes use of a stack, instead of recursive calls.\n\nThe stack is implemented using the same technique for [lisp-style lists](/languages/func/stdlib#lisp-style-lists).\nThe only difference is that the list grows by appending elements to the end of the list, instead of at the front.\nThe last element in the list is the top of the stack.\nMore concretely, if `s` is the current stack, append an element `x` by constructing the tuple `[s, x]`.\nThis tuple `[s, x]` is the new stack, with top element `x`.\nFor example, the stack `1, 2, 3`, where `3` is the top element, is represented using nested tuples\nas `[[[null, 1], 2], 3]`, where `null` represents the empty stack.\n\n```func\n;; Sets \"head\" to be the new top element of stack \"tail\".\n;; For example, if t is \"tail\" and x is \"head\",\n;; this function produces the tuple [t, x],\n;; which means that x is the new top element of the stack [t, x].\n;; The function returns the new stack and the unit value (),\n;; just to be able to use this function using modifying notation.\nforall X -> (tuple, ()) push_back (tuple tail, X head) asm \"CONS\";\n\n;; Removes the last element from the stack, and\n;; returns the modified stack and the removed element.\n;; For example, if the stack is [t, x], this\n;; function returns the stack t, and the element x.\nforall X -> (tuple, X) pop_back (tuple t) asm \"UNCONS\";\n\n() main () {\n    ;; An example tree of cells.\n    cell c = begin_cell()\n        .store_uint(1, 16)\n        .store_ref(begin_cell()\n            .store_uint(2, 16)\n        .end_cell())\n        .store_ref(begin_cell()\n            .store_uint(3, 16)\n            .store_ref(begin_cell()\n                .store_uint(4, 16)\n            .end_cell())\n            .store_ref(begin_cell()\n                .store_uint(5, 16)\n            .end_cell())\n        .end_cell())\n    .end_cell();\n\n    ;; Initialize the stack. null plays the roll\n    ;; of the empty stack.\n    tuple stack = null();\n\n    ;; Push the root cell into the stack to\n    ;; process it in the loop\n    stack~push_back(c);\n\n    ;; Iterate while there are cells in the stack\n    while (~ stack.null?()) {\n\n        ;; Pop a cell from the stack and convert it\n        ;; to a slice to be able to process it.\n        ;; The call stack~pop_back() implicitly\n        ;; modifies the stack.\n        slice s = stack~pop_back().begin_parse();\n\n        ;; Do something with the data in s\n\n        ;; If the current slice has any refs,\n        ;; add them to the stack.\n        ;; slice_refs returns the number of\n        ;; refs in slice s.\n        repeat (s.slice_refs()) {\n            ;; Obtain the cell using s~load_ref().\n            ;; This implicitly modifies the slice s\n            ;; so that it is ready to read the next\n            ;; cell reference.\n            ;; Then, push the cell to the stack.\n            stack~push_back(s~load_ref());\n        }\n    }\n}\n```\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [Modifying notation using \\~](/languages/func/expressions#modifying-notation)\n- [Builder primitives](/languages/func/stdlib#builder-primitives)\n- [Slice primitives](/languages/func/stdlib#slice-primitives)\n- [`Lisp-style lists`](/languages/func/stdlib#lisp-style-lists)\n- [Assembler functions](/languages/func/asm-functions)\n- [`null`](/languages/func/stdlib#null)\n- [`null?`](/languages/func/built-ins#null%3F)\n- [`slice_refs`](/languages/func/stdlib#slice-refs)\n- [TVM instructions](/tvm/instructions)\n\n## Contracts\n\n### How to determine if the contract state is empty\n\nConsider a smart contract that keeps a `counter` stored in its state, that tracks the number of internal messages the contract has received.\nWhen the contract receives its first message, the contract state is empty, which means that the `counter` has not been initialized yet.\nIt is important to handle all scenarios by checking if the state is empty and initializing the `counter` accordingly.\n\n```func\n() recv_internal() {\n    ;; \"get_data\" returns the persistent contract state, as a cell\n    cell contract_data = get_data();\n\n    ;; Obtain a slice from the contract data cell, for reading\n    slice cs = contract_data.begin_parse();\n\n    ;; Check that the contract state is empty\n    if (cs.slice_empty?()) {\n        ;; Contract data is empty, so create a fresh counter.\n        int counter = 1;\n\n        ;; To save the counter into the contract state,\n        ;; create a cell containing the counter.\n        ;; The counter is stored as an unsigned 32-bit integer.\n        cell new_data = begin_cell().store_uint(counter, 32).end_cell();\n\n        ;; Save the data cell into the contract state by using \"set_data\".\n        set_data(new_data);\n    } else {\n        ;; Contract data is not empty.\n        ;; Get our counter from the contract state and increase it\n        ;; The counter is an unsigned 32-bit integer.\n        int counter = cs~load_uint(32) + 1;\n\n        ;; To save the counter into the contract state,\n        ;; create a cell containing the counter.\n        ;; The counter is stored as an unsigned 32-bit integer.\n        cell new_data = begin_cell().store_uint(counter, 32).end_cell();\n\n        ;; Save the data cell into the contract state by using \"set_data\".\n        set_data(new_data);\n    }\n}\n```\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [Modifying notation using \\~](/languages/func/expressions#modifying-notation)\n- [`recv_internal` method](/languages/func/special-functions#receive-internal)\n- [`get_data`](/languages/func/stdlib#get-data)\n- [`begin_parse`](/languages/func/stdlib#begin-parse)\n- [`slice_empty?`](/languages/func/stdlib#slice-empty%3F)\n- [`begin_cell`](/languages/func/stdlib#begin-cell)\n- [`end_cell`](/languages/func/stdlib#end-cell)\n- [`store_uint`](/languages/func/stdlib#store-uint)\n- [`load_uint`](/languages/func/stdlib#load-uint)\n- [`set_data`](/languages/func/stdlib#set-data)\n\n### How to update the smart contract logic\n\nBelow is an example of a simple `CounterV1` smart contract that allows the counter to be incremented and includes logic for updating the contract.\n\n```func\n() recv_internal (slice in_msg_body) {\n    int op = in_msg_body~load_uint(32);\n\n    if (op == op::increase) {\n        int increase_by = in_msg_body~load_uint(32);\n        ctx_counter += increase_by;\n        save_data();\n        return ();\n    }\n\n    if (op == op::upgrade) {\n        cell code = in_msg_body~load_ref();\n        set_code(code);\n        return ();\n    }\n}\n```\n\nAfter interacting with the contract, and realizing that the functionality for decrementing the counter is missing. Fix this by copying the code from `CounterV1` and adding a new `decrease` function next to the existing `increase` function. The updated code will look like this:\n\n```func\n() recv_internal (slice in_msg_body) {\n    int op = in_msg_body~load_uint(32);\n\n    if (op == op::increase) {\n        int increase_by = in_msg_body~load_uint(32);\n        ctx_counter += increase_by;\n        save_data();\n        return ();\n    }\n\n    if (op == op::decrease) {\n        int decrease_by = in_msg_body~load_uint(32);\n        ctx_counter -= decrease_by;\n        save_data();\n        return ();\n    }\n\n    if (op == op::upgrade) {\n        cell code = in_msg_body~load_ref();\n        set_code(code);\n        return ();\n    }\n}\n```\n\nOnce the `CounterV2` smart contract is ready, compile it off-chain into a `cell` and send an upgrade message to the `CounterV1` contract:\n\n```javascript\nawait contractV1.sendUpgrade(provider.sender(), {\n    code: await compile('ContractV2'),\n    value: toNano('0.05'),\n});\n```\n\n**References:**\n\n- [`set_code`](/languages/func/stdlib#set-code)\n\n## Messages\n\n### How to build an internal message with default headers\n\nWhen a smart contract needs to send an internal message, it must first construct the message as a `cell`. This includes specifying technical flags, the recipient's address, and additional data.\n\nThe most common case involves sending an internal message that is bounceable, with no `StateInit`, and with message body serialized in the same message cell. The following `build_message` function illustrates this common case. The function receives as parameters the destination address `dest_addr` encoded as a slice, the amount in nanotons to send `amount`, and the requested operation opcode `opcode`:\n\n```func\ncell build_message(slice dest_addr, int amount, int opcode) {\n    cell msg = begin_cell()\n\n      ;; Sets 5 headers to their default values.\n      ;; In particular, the bounceable header is true.\n      .store_uint(0x18, 1 + 1 + 1 + 1 + 2)\n      .store_slice(dest_addr)  ;; destination address\n      .store_coins(amount)     ;; amount to send in nanotons\n\n      ;; Sets 7 more headers to their default values.\n      ;; Sets default value 0 to all the 7 headers.\n      .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)\n\n      ;; Message body starts here.\n      ;; Usually starts with an unsigned 32-bits integer,\n      ;; called \"opcode\", that identifies the requested operation.\n      .store_uint(op, 32)\n\n      ;; The next fields depend on the opcode.\n      ;; For example, an opcode representing a lookup operation\n      ;; would need to include the data to lookup\n      ;; ......\n    .end_cell();\n\n    return msg;\n}\n```\n\nThe call `store_uint(0x18, 1 + 1 + 1 + 1 + 2)` sets 5 headers to their default values. The sum `1 + 1 + 1 + 1 + 2`\nrepresents the number of bits occupied by each header, i.e., the first header occupies 1 bit, the second header 1 bit, and so on\nuntil the 5th header which occupies 2 bits. The hexadecimal number `0x18` is a shorthand for the 6 bits `011000`, which represents\nthe default values for each of the headers, i.e., the first header has value `0`, the second header `1`, and so on until the\n5th header, which has the two bits `00`.\n\nAmong these 5 headers, the third one is probably the most interesting for a programmer, because it corresponds to the bounceable flag,\nwhich is set to `1` (true) by default. If the flag is required to be `0` (false), use hexadecimal `0x10` instead of `0x18`,\nbecause `0x10` corresponds to the 6 bits `010000`.\n\nThe call `store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)` sets 7 further headers to the default value `0`. The sum `1 + 4 + 4 + 64 + 32 + 1 + 1` represents the number of bits occupied by each header. Among these 7 headers, the last two are probably the most interesting for a programmer, because they correspond to the `StateInit` header and the message body ref header, respectively. In particular, the default headers state that the message has no `StateInit`, and that the message body is not stored as a cell reference, but directly in the cell, together with the headers. Refer to recipes [\"How to send a deploy message\"](#how-to-send-a-deploy-message) and [\"How to set the message body as a ref in an internal message\"](#how-to-set-the-message-body-as-a-ref-in-an-internal-message) for examples on how to manipulate `StateInit` and the message body ref headers, respectively.\n\nFor further details on all the headers, see the sending messages page and\nthe [TL-B for messages](/foundations/whitepapers/tblkch#3-1-7-message-layout).\n\nHere is an example on how to use function `build_message` to send a message:\n\n```func\n;; Create a slice from a string containing the destination address\nslice addr = \"EQArzP5prfRJtDM5WrMNWyr9yUTAi0c9o6PfR4hkWy9UQXHx\"a;\n;; The amount to send in nanotons\nint amount = 1000000000;\n;; The opcode for the requested operation\nint op = 20;\n\n;; Create the message cell\ncell msg = build_message(addr, amount, op);\n\n;; Send the message, using default sending mode 0\nsend_raw_message(msg, 0);\n```\n\nRefer to the sending messages page for further details on sending modes in the `send_raw_message` function.\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [`begin_cell`](/languages/func/stdlib#begin-cell)\n- [`store_uint`](/languages/func/stdlib#store-uint)\n- [`store_slice`](/languages/func/stdlib#store-slice)\n- [`store_coins`](/languages/func/stdlib#store-coins)\n- [`end_cell`](/languages/func/stdlib#end-cell)\n- [TL-B for messages](/foundations/whitepapers/tblkch#3-1-7-message-layout)\n- Sending messages page\n- [`\"<address string>\"a` compile-time builtin](/languages/func/literals#string-with-suffix-a), where `<address string>` is a string encoding an address.\n- [`send_raw_message`](/languages/func/stdlib#send-raw-message)\n\n### How to set the message body as a ref in an internal message\n\nIf there is sufficient space, the message body can be stored in the same `cell` together with the message headers,\nas shown in the recipe [\"How to build an internal message with default headers\"](#how-to-build-an-internal-message-with-default-headers).\nIf there is not enough space in the message cell, the message body can be stored as a cell reference to the message, as shown in the following\nfunction. The function receives the destination address, the amount to send, and the message body as a separate cell.\n\n```func\ncell build_message(slice dest_addr, int amount, cell message_body) {\n    cell msg = begin_cell()\n\n      ;; Sets 5 headers to their default values.\n      ;; In particular, the bounceable header is true.\n      .store_uint(0x18, 1 + 1 + 1 + 1 + 2)\n      .store_slice(dest_addr)  ;; destination address\n      .store_coins(amount)     ;; amount to send in nanotons\n\n      ;; Sets 6 more headers to their default values.\n      ;; Sets default value 0 to all the 6 headers.\n      .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1)\n\n      ;; Activate the message body ref header\n      ;; to indicate that the message body is included as a\n      ;; cell reference\n      .store_uint(1, 1)\n\n      ;; Store the message body as a cell reference\n      .store_ref(message_body)\n    .end_cell();\n\n    return msg;\n}\n```\n\nThe call `store_uint(0x18, 1 + 1 + 1 + 1 + 2)` sets 5 headers to their default values, as in the recipe\n[\"How to build an internal message with default headers\"](#how-to-build-an-internal-message-with-default-headers).\n\nThe call `store_uint(0, 1 + 4 + 4 + 64 + 32 + 1)` sets 6 further headers to the default value `0`, as in\nthe first 6 headers in recipe [\"How to build an internal message with default headers\"](#how-to-build-an-internal-message-with-default-headers).\nThe last header, corresponding to the message body ref header, is set with the call `store_uint(1, 1)`, which indicates that the\nmessage body will be included as a cell reference.\n\nFor further details on all the headers, see the sending messages page and\nthe [TL-B for messages](/foundations/whitepapers/tblkch#3-1-7-message-layout).\n\nHere is an example on how to use function `build_message` to send a message:\n\n```func\n;; Create a slice from a string containing the destination address\nslice addr = \"EQArzP5prfRJtDM5WrMNWyr9yUTAi0c9o6PfR4hkWy9UQXHx\"a;\n;; The amount to send in nanotons\nint amount = 1000000000;\n;; Create a cell storing the message body\ncell message_body = begin_cell()\n    .store_uint(20, 32) ;; include an opcode\n    .store_slice(\"❤\")   ;; include further data required by the opcode\n    .end_cell();\n\n;; Create the message cell\ncell msg = build_message(addr, amount, message_body);\n\n;; Send the message, using default sending mode 0\nsend_raw_message(msg, 0);\n```\n\nRefer to the sending messages page for further details on sending modes in the `send_raw_message` function.\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [`begin_cell`](/languages/func/stdlib#begin-cell)\n- [`store_uint`](/languages/func/stdlib#store-uint)\n- [`store_slice`](/languages/func/stdlib#store-slice)\n- [`store_coins`](/languages/func/stdlib#store-coins)\n- [`end_cell`](/languages/func/stdlib#end-cell)\n- [TL-B for messages](/foundations/whitepapers/tblkch#3-1-7-message-layout)\n- Sending messages page\n- [`\"<address string>\"a` compile-time builtin](/languages/func/literals#string-with-suffix-a), where `<address string>` is a string encoding an address.\n- [`send_raw_message`](/languages/func/stdlib#send-raw-message)\n\n### How to set the message body as a slice in an internal message\n\nIf the message body needs to be included directly in the message cell, but the message body is already in a separate slice,\nwrite the slice into the message cell, as\nin the following function. The function receives the destination address, the amount to send, and the message body as a slice.\n\n```func\ncell build_message(slice dest_addr, int amount, slice message_body) {\n    cell msg = begin_cell()\n\n      ;; Sets 5 headers to their default values.\n      ;; In particular, the bounceable header is true.\n      .store_uint(0x18, 1 + 1 + 1 + 1 + 2)\n      .store_slice(dest_addr)  ;; destination address\n      .store_coins(amount)     ;; amount to send in nanotons\n\n      ;; Sets 7 more headers to their default values.\n      ;; Sets default value 0 to all the 7 headers.\n      .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)\n\n      ;; Message body starts here.\n      ;; Write the message body slice\n      .store_slice(message_body)\n    .end_cell();\n\n    return msg;\n}\n```\n\nThe function writes the default values for all the message headers, as in the recipe\n[\"How to build an internal message with default headers\"](#how-to-build-an-internal-message-with-default-headers).\n\nFor further details on all the headers, see the sending messages page and\nthe [TL-B for messages](/foundations/whitepapers/tblkch#3-1-7-message-layout).\n\nHere is an example on how to use function `build_message` to send a message:\n\n```func\n;; Create a slice from a string containing the destination address\nslice addr = \"EQArzP5prfRJtDM5WrMNWyr9yUTAi0c9o6PfR4hkWy9UQXHx\"a;\n;; The amount to send in nanotons\nint amount = 1000000000;\n;; Create a slice storing the message body\nslice message_body = begin_cell()\n    .store_uint(20, 32) ;; include an opcode\n    .store_slice(\"❤\")   ;; include further data required by the opcode\n    .end_cell()\n    .begin_parse();     ;; Transform the cell to a slice\n\n;; Create the message cell\ncell msg = build_message(addr, amount, message_body);\n\n;; Send the message, using default sending mode 0\nsend_raw_message(msg, 0);\n```\n\nRefer to the sending messages page for further details on sending modes in the `send_raw_message` function.\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [`begin_cell`](/languages/func/stdlib#begin-cell)\n- [`store_uint`](/languages/func/stdlib#store-uint)\n- [`store_slice`](/languages/func/stdlib#store-slice)\n- [`store_coins`](/languages/func/stdlib#store-coins)\n- [`end_cell`](/languages/func/stdlib#end-cell)\n- [`begin_parse`](/languages/func/stdlib#begin-parse)\n- [TL-B for messages](/foundations/whitepapers/tblkch#3-1-7-message-layout)\n- Sending messages page\n- [`\"<address string>\"a` compile-time builtin](/languages/func/literals#string-with-suffix-a), where `<address string>` is a string encoding an address.\n- [`send_raw_message`](/languages/func/stdlib#send-raw-message)\n\n### How to send a message containing a comment\n\nA \"comment\" is an ASCII string encoded as a slice. To send a message with a comment,\nwrite a `0` opcode followed by the comment, as done in the following function.\nThe function receives the destination address, the amount to send, and the comment encoded as a slice.\n\n```func\ncell build_message(slice dest_addr, int amount, slice comment) {\n    cell msg = begin_cell()\n\n      ;; Sets 5 headers to their default values.\n      ;; In particular, the bounceable header is true.\n      .store_uint(0x18, 1 + 1 + 1 + 1 + 2)\n      .store_slice(dest_addr)  ;; destination address\n      .store_coins(amount)     ;; amount to send in nanotons\n\n      ;; Sets 7 more headers to their default values.\n      ;; Sets default value 0 to all the 7 headers.\n      .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)\n\n      ;; Message body starts here.\n      ;; Write a 0 opcode, which means simple\n      ;; message with a comment\n      .store_uint(0, 32)\n\n      ;; Write the slice containing the comment\n      .store_slice(comment)\n    .end_cell();\n\n    return msg;\n}\n```\n\nThe function writes the default values for all the message headers, as in the recipe\n[\"How to build an internal message with default headers\"](#how-to-build-an-internal-message-with-default-headers).\n\nFor further details on all the headers, see the sending messages page and\nthe [TL-B for messages](/foundations/whitepapers/tblkch#3-1-7-message-layout).\n\nHere is an example on how to use function `build_message` to send a message:\n\n```func\n;; Create a slice from a string containing the destination address\nslice addr = \"EQArzP5prfRJtDM5WrMNWyr9yUTAi0c9o6PfR4hkWy9UQXHx\"a;\n;; The amount to send in nanotons\nint amount = 1000000000;\n;; Create a slice storing the comment\nslice comment = \"Hello from FunC!\";\n\n;; Create the message cell\ncell msg = build_message(addr, amount, comment);\n\n;; Send the message, using default sending mode 0\nsend_raw_message(msg, 0);\n```\n\nRefer to the sending messages page for further details on sending modes in the `send_raw_message` function.\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [`begin_cell`](/languages/func/stdlib#begin-cell)\n- [`store_uint`](/languages/func/stdlib#store-uint)\n- [`store_slice`](/languages/func/stdlib#store-slice)\n- [`store_coins`](/languages/func/stdlib#store-coins)\n- [`end_cell`](/languages/func/stdlib#end-cell)\n- [TL-B for messages](/foundations/whitepapers/tblkch#3-1-7-message-layout)\n- Sending messages page\n- [`\"<address string>\"a` compile-time builtin](/languages/func/literals#string-with-suffix-a), where `<address string>` is a string encoding an address.\n- [`\"<ascii string>\"` compile-time builtin](/languages/func/literals#string-without-suffix), where `<ascii string>` is an ASCII string.\n- [`send_raw_message`](/languages/func/stdlib#send-raw-message)\n\n### How to send a message with a long text comment\n\nA `cell` can store up to 1023 bits of data, which means up to 127 8-bit characters.\nIf there is a need to send a message with a really long comment, split the comment into several slices.\nEach slice should have at most 127 chars. Each slice should have a reference to the next one,\nforming a snake-like structure.\n\nThe following example illustrates the idea:\n\n```func\n;; Create a slice from a string containing the destination address\nslice addr = \"EQArzP5prfRJtDM5WrMNWyr9yUTAi0c9o6PfR4hkWy9UQXHx\"a;\n;; The amount to send in nanotons\nint amount = 1000000000;\n\n;; Create a cell storing the message body\n;; It contains a long string, that must be split into several\n;; slices, linked by references in a snake-like structure.\n;; Each slice has at most 127 chars\ncell message_body = begin_cell()\n    ;; zero opcode, i.e., message with comment\n    .store_uint(0, 32)\n    ;; The long string starts here\n    .store_slice(\"long, long, long message...\")\n    ;; Create a reference to the next part of the string\n    .store_ref(begin_cell()\n        .store_slice(\" store a string of almost any length, \")\n        ;; And another reference to the last part of the string\n        .store_ref(begin_cell()\n            .store_slice(\" as long as each slice has at most 127 chars.\")\n        .end_cell())\n    .end_cell())\n.end_cell();\n\n;; Create the message cell\ncell msg = build_message(addr, amount, message_body);\n\n;; Send the message, using default sending mode 0\nsend_raw_message(msg, 0);\n```\n\nThe `build_message` function is exactly the function used in the\nrecipe [How to set the message body as a ref in an internal message](#how-to-set-the-message-body-as-a-ref-in-an-internal-message).\n\nRefer to the sending messages page for further details on sending modes in the `send_raw_message` function.\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [`begin_cell`](/languages/func/stdlib#begin-cell)\n- [`store_uint`](/languages/func/stdlib#store-uint)\n- [`store_slice`](/languages/func/stdlib#store-slice)\n- [`store_ref`](/languages/func/stdlib#store-ref)\n- [`end_cell`](/languages/func/stdlib#end-cell)\n- [`\"<address string>\"a` compile-time builtin](/languages/func/literals#string-with-suffix-a), where `<address string>` is a string encoding an address.\n- [`\"<ascii string>\"` compile-time builtin](/languages/func/literals#string-without-suffix), where `<ascii string>` is an ASCII string.\n- [`send_raw_message`](/languages/func/stdlib#send-raw-message)\n- Sending messages page\n\n### How to send a deploy message\n\nWhen sending a deploy message, prepare a [`StateInit`](/foundations/messages/deploy) cell, as done in the recipe [How to build a `StateInit` cell](#how-to-build-a-StateInit-cell). Once the `StateInit` cell is ready, prepare a message cell in which the message body is included with the headers, or the message body is included as a separate cell.\n\nThe following function illustrates the case for the message body included in the same cell as the headers. The function receives the destination address, the amount to send, the `StateInit` cell, and the message body as a slice.\n\n```func\n() deploy(slice dest_addr, int amount, cell state_init, slice message_body) {\n    cell msg = begin_cell()\n\n      ;; Sets 5 headers to their default values.\n      ;; In particular, the bounceable header is true.\n      .store_uint(0x18, 1 + 1 + 1 + 1 + 2)\n      .store_slice(dest_addr)  ;; destination address\n      .store_coins(amount)     ;; amount to send in nanotons\n\n      ;; Sets 5 more headers to their default values.\n      ;; Sets default value 0 to all the 5 headers.\n      .store_uint(0, 1 + 4 + 4 + 64 + 32)\n\n      ;; Sets the StateInit header to the 2-bit integer 3,\n      ;; which signals that a StateInit cell is included\n      ;; as a separate reference cell.\n      .store_uint(3, 2)\n\n      ;; Set the message body header to the 1-bit integer 0,\n      ;; which indicates that the message body is\n      ;; included in the same cell.\n      .store_uint(0, 1)\n\n      ;; Message body starts here.\n      ;; Write the message body slice\n      .store_slice(message_body)\n\n      ;; Include the StateInit cell as a reference\n      .store_ref(state_init)\n    .end_cell();\n\n    ;; Send the deploy message in standard mode\n    send_raw_message(msg, 0);\n}\n```\n\nThe function writes the default values for all the message headers, following the same strategy as in the recipe [\"How to build an internal message with default headers\"](#how-to-build-an-internal-message-with-default-headers), with the exception of the last two headers: the `StateInit` header and the message body header.\n\nAccording to the TL-B for internal messages, the `StateInit` header satisfies:\n\n```text\ninit:(Maybe (Either StateInit ^StateInit))\n```\n\nwhich means that the header needs at most two bits, one for deciding the `Maybe` and, in case the `Maybe` bit is active, another for deciding the `Either`. In the function above, the `StateInit` header was set to the 2-bit integer `3`, which corresponds to the binary `11`. The first bit corresponds to the `Maybe`, and since it is active, it signals that there is a `StateInit` in the message. The second bit corresponds to the `Either`, and since it is active, it signals that the right branch of the `Either` was chosen, i.e., the branch `^StateInit`, which means that the `StateInit` is included as a reference cell in the message.\n\nThe message body header was set to the 1-bit value `0`, which means that the message body in included in the same cell together with the headers.\n\nAs a second example, the following function also includes a `StateInit`, but the message body is included as a separate cell. The function receives the destination address, the amount to send, the `StateInit` cell, and the message body as a cell.\n\n```func\n() deploy_body_cell(slice dest_addr, int amount, cell state_init, cell message_body) {\n    cell msg = begin_cell()\n\n      ;; Sets 5 headers to their default values.\n      ;; In particular, the bounceable header is true.\n      .store_uint(0x18, 1 + 1 + 1 + 1 + 2)\n      .store_slice(dest_addr)  ;; destination address\n      .store_coins(amount)     ;; amount to send in nanotons\n\n      ;; Sets 5 more headers to their default values.\n      ;; Sets default value 0 to all the 5 headers.\n      .store_uint(0, 1 + 4 + 4 + 64 + 32)\n\n      ;; Sets the StateInit header to the 2-bit integer 3,\n      ;; which signals that a StateInit cell is included\n      ;; as a separate reference cell.\n      .store_uint(3, 2)\n\n      ;; Set the message body header to the 1-bit integer 1,\n      ;; which indicates that the message body is\n      ;; included as a separate cell\n      .store_uint(1, 1)\n\n      ;; Include the StateInit cell as a reference\n      .store_ref(state_init)\n\n      ;; Include the message body as a reference\n      .store_ref(message_body)\n    .end_cell();\n\n    ;; Send the deploy message in standard mode\n    send_raw_message(msg, 0);\n}\n```\n\nFor further details on all the headers, see the sending messages page and\nthe [TL-B for messages](/foundations/whitepapers/tblkch#3-1-7-message-layout).\n\nRefer to the sending messages page for further details on sending modes in the `send_raw_message` function.\n\n**References:**\n\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [`begin_cell`](/languages/func/stdlib#begin-cell)\n- [`store_uint`](/languages/func/stdlib#store-uint)\n- [`store_slice`](/languages/func/stdlib#store-slice)\n- [`store_coins`](/languages/func/stdlib#store-coins)\n- [`store_ref`](/languages/func/stdlib#store-ref)\n- [`end_cell`](/languages/func/stdlib#end-cell)\n- [`send_raw_message`](/languages/func/stdlib#send-raw-message)\n- [TL-B for messages](/foundations/whitepapers/tblkch#3-1-7-message-layout)\n- Sending messages page\n\n### How to send a message with the entire balance\n\nTo transfer the entire balance of a smart contract, use [send mode `128`](/foundations/messages/modes).\nThis is particularly useful for proxy contracts that receive payments and forward them to the main contract.\n\n```func\n;; Create a slice from a string containing the destination address\nslice addr = \"EQArzP5prfRJtDM5WrMNWyr9yUTAi0c9o6PfR4hkWy9UQXHx\"a;\n;; The amount to send in nanotons.\n;; In this case, it is irrelevant the sent amount,\n;; because, later, the send mode 128 will include\n;; all the contract's balance in the message\nint amount = 0;\n;; The comment to send\nslice comment = \"Hello from FunC!\";\n\n;; Create the message cell\ncell msg = build_message(addr, amount, comment);\n\n;; Send the message, using mode 128\n;; The mode 128 sends the entire contract's balance in the message\nsend_raw_message(msg, 128);\n```\n\nThe `build_message` function is exactly the function used in the\nrecipe [How to send a message containing a comment](#how-to-send-a-message-containing-a-comment).\n\nRefer to the sending messages page for further details on sending modes in the `send_raw_message` function.\n\n**References:**\n\n- [`\"<address string>\"a` compile-time builtin](/languages/func/literals#string-with-suffix-a), where `<address string>` is a string encoding an address.\n- [`\"<ascii string>\"` compile-time builtin](/languages/func/literals#string-without-suffix), where `<ascii string>` is an ASCII string.\n- Sending messages page\n- [`send_raw_message`](/languages/func/stdlib#send-raw-message)\n\n### How to send a message in a proxy contract\n\nA proxy contract facilitates message exchange between a user and a main contract.\nThe proxy contract redirects messages based on the parameters it receives in the incoming message.\n\nFor example, this is a simple example of a proxy contract.\nIt expects that the incoming message body `in_msg_body` contains the message mode,\ndestination address, and the slice to send as body.\n\n```func\n() recv_internal (slice in_msg_body) {\n\n    ;; In the incoming message body,\n    ;; the first byte contains the message mode\n    ;; for the redirected message\n    int mode = in_msg_body~load_uint(8);\n\n    ;; Then, the destination address\n    slice addr = in_msg_body~load_msg_addr();\n\n    ;; And finally, everything that is left in \"in_msg_body\"\n    ;; will be the redirected message's body\n    slice body = in_msg_body;\n\n    ;; The amount to send in nanotons\n    int amount = 1000000000;\n\n    ;; Create the message cell\n    cell msg = build_message(addr, amount, body);\n\n    ;; Send the message, using the provided mode.\n    send_raw_message(msg, mode);\n}\n```\n\nThe `build_message` function is exactly the function used in the\nrecipe [How to set the message body as a slice in an internal message](#how-to-set-the-message-body-as-a-slice-in-an-internal-message).\n\nRefer to the sending messages page for further details on sending modes in the `send_raw_message` function.\n\n**References:**\n\n- [Modifying notation using \\~](/languages/func/expressions#modifying-notation)\n- [load\\_uint](/languages/func/stdlib#load-uint)\n- [`load_msg_addr`](/languages/func/stdlib#load-msg-addr)\n- Sending messages page\n- [`send_raw_message`](/languages/func/stdlib#send-raw-message)\n\n## Functions\n\n### How to write custom functions using asm keyword\n\nMany features in FunC come from predefined methods in the [Standard library](/languages/func/stdlib).\nHowever, there are many functionalities that the standard library does not cover, but are available as [TVM instructions](/tvm/instructions).\nIn such cases, it is possible to define functions that make use of the TVM instructions.\n\nFor example, while the function [`tpush`](/languages/func/stdlib#tpush), which adds an element to the end of a tuple, exists in the standard library,\nthere is no `tpop` function, which removes the last element in a tuple and returns the modified tuple and the removed element.\nBut there is a [TVM instruction `TPOP`](/tvm/instructions#6f8d-tpop) that does precisely this.\nSo, define the function `tpop` as an [assembler function](/languages/func/asm-functions) that wraps the `TPOP` instruction:\n\n```func\nforall X -> (tuple, X) ~tpop (tuple t) asm \"TPOP\";\n```\n\nThe return type `(tuple, X)` indicates that the function produces the modified tuple and the extracted element as a result.\nThe function is [polymorphic](/languages/func/types#polymorphism-with-type-variables) in the sense that the type of the returned element `X`\ncan be any type. The function name uses the symbol `~` to indicate that this function can be called\nusing [modifying notation](/languages/func/expressions#modifying-notation).\n\nFor example, if it is certain that tuple `t` has only integer elements, call the function using\n[modifying notation](/languages/func/expressions#modifying-notation), like this:\n\n```func\nint elem = t~tpop();\n```\n\nwhich will assign the removed element to `elem` and also modify tuple `t` implicitly.\n\nAs another example, the following function determines the length of a tuple by wrapping the [`TLEN` TVM instruction](/tvm/instructions#6f88-tlen):\n\n```func\nint tuple_length (tuple t) asm \"TLEN\";\n```\n\nFurther examples taken from the [Standard library](/languages/func/stdlib):\n\n```func\nslice begin_parse(cell c) asm \"CTOS\";\nbuilder begin_cell() asm \"NEWC\";\ncell end_cell(builder b) asm \"ENDC\";\n```\n\n**References:**\n\n- [Modifying notation using \\~](/languages/func/expressions#modifying-notation)\n- [Standard library](/languages/func/stdlib)\n- [TVM instructions](/tvm/instructions)\n- [Assembler functions](/languages/func/asm-functions)\n\n### How to use modifying notation on functions\n\nTo use [modifying notation](/languages/func/expressions#modifying-notation) on a function, define the function so\nthat it has a type of the form `(A, ...) -> (A, B)`, for arbitrary type `B`. Functions of this type usually mutate their first\nargument and return the mutated argument as their first result.\n\nFor example, a function `f` of type `(slice, int, slice) -> (slice, cell)`, can be called using modifying notation as\n`cell result = s~f(0, \"hello\")`, where `s` is some slice. The modifying notation is a shorthand for the standard function call\n`(s, cell result) = f(s, 0, \"hello\")`, where `s` is reassigned after the call to `f`.\n\nFor a more concrete example, the following defines a function that reads a digit from a slice that stores ASCII digits.\nThe function receives the slice as an argument and produces two results. The first result is the modified slice,\nso that it is ready to read the next digit.\nThe second result is the loaded digit.\n\n```func\n(slice, int) load_digit (slice s) {\n    ;; Load 8 bits (one char) from slice.\n    ;; x stores the decimal ASCII code of the char.\n    ;; Since load_uint is called using modifying notation,\n    ;; slice s is implicitly modified,\n    ;; and it is now ready to read the next 8 bits.\n    int x = s~load_uint(8);\n    ;; Char '0' has code 48. Substract it\n    ;; to get the digit as a number.\n    x -= 48;\n    ;; Return the modified slice and the digit.\n    return (s, x);\n}\n```\n\nThe function can be called using modifying notation as follows.\n\n```func\n() main () {\n    ;; Create a slice containing some ASCII digits\n    slice s = \"258\";\n    ;; Proceed to read the digits as integers\n    ;; using modifying notation on the function call.\n    ;; This ensures that the slice gets implicitly modified\n    ;; after reading each digit.\n    int c1 = s~load_digit();\n    int c2 = s~load_digit();\n    int c3 = s~load_digit();\n    ;; here s contains no more data,\n    ;; and c1 = 2, c2 = 5, c3 = 8\n}\n```\n\nRefer to the [modifying notation page](/languages/func/expressions#modifying-notation) for further details.\n\n**References:**\n\n- [Modifying notation using \\~](/languages/func/expressions#modifying-notation)\n- [`load_uint`](/languages/func/stdlib#load-uint)\n- [`\"<ascii string>\"` compile-time builtin](/languages/func/literals#string-without-suffix), where `<ascii string>` is an ASCII string.\n\n## Integer utilities\n\n### How to get the current time\n\nUse the function `now` to obtain the current UNIX timestamp.\n\n```func\nint current_time = now();\n\n;; Is the current time bigger than some timestamp?\nif (current_time > 1672080143) {\n    ;; do some stuff\n}\n```\n\n**References:**\n\n- [now](/languages/func/stdlib#now)\n\n### How to generate a random number\n\n<Aside\n  type=\"caution\"\n>\n  This method is not cryptographically secure.\n  For more details, see the Random number generation section.\n</Aside>\n\n```func\n;; do this only once before the first invocation of\n;; any of the functions \"rand\" or \"random\", to ensure that\n;; they will have a different seed every time the contract\n;; executes.\nrandomize_lt();\n\n;; Generate a random number in the range 0..9.\nint a = rand(10);\n;; Generate a random number in the range 0..999999.\nint b = rand(1000000);\n;; Generate an unsigned 256-bit integer.\nint c = random();\n```\n\n**References:**\n\n- [Random Number generator primitives](/languages/func/stdlib#random-number-generator-primitives)\n\n### Modulo operations\n\nAs an example, let's say there is a need to perform the following calculation for all 256 numbers:\n\n`(xp + zp) * (xp - zp)`.\n\nSince these operations are commonly used in cryptography, modulo operator for montgomery curves should be used.\n\n**Note:**\nVariable names like `xp+zp` are valid as long as there are no spaces between the operators.\n\n```func\n(int) modulo_operations (int xp, int zp) {\n   ;; 2^255 - 19 is a prime number for montgomery curves, meaning all operations should be done against its prime\n   int prime = 57896044618658097711785492504343953926634992332820282019728792003956564819949;\n\n   ;; muldivmod handles the next two lines itself\n   ;; int xp+zp = (xp + zp) % prime;\n   ;; int xp-zp = (xp - zp + prime) % prime;\n   (_, int xp+zp*xp-zp) = muldivmod(xp + zp, xp - zp, prime);\n   return xp+zp*xp-zp;\n}\n```\n\n**Reference:** [`muldivmod`](/tvm/instructions#A98C)\n\n### How to raise a number to a power\n\nTo compute `n^e`, the naive approach multiplies `e - 1` times the number `n` by itself. For example, `n^3`\nmeans to multiply by `n` `2` times: `(n * n) * n`.\n\nThe following code implements such idea. It has a complexity linear on `e`.\n\n```func\nint pow (int n, int e) {\n    if (e == 0) {\n        return 1;\n    }\n    int i = 0;\n    int value = n;  ;; \"value\" always stores the initial \"n\"\n    while (i < e - 1) { ;; Repeat e-1 times\n        n *= value;  ;; Multiply by the initial \"n\"\n                     ;; and accumulate the result.\n        i += 1;\n    }\n\n    ;; n stores the accumulated result\n    return n;\n}\n```\n\nThere is a more efficient way to compute `n^e` called [binary exponentiation](https://cp-algorithms.com/algebra/binary-exp.html).\nIt has a complexity base-2 logarithmic on `e`, i.e., `O(log_2 e)`.\nThis is the recursive implementation of the algorithm. Refer to the article for details.\n\n```func\nint binpow (int n, int e) {\n    if (e == 0) {\n        return 1;\n    }\n    if (e == 1) {\n        return n;\n    }\n    int p = binpow(n, e / 2);\n    p *= p;\n    if ((e % 2) == 1) {\n        p *= n;\n    }\n    return p;\n}\n```\n\nAn usage example of `binpow`:\n\n```func\n() main () {\n    int num = binpow(2, 3);\n    ~dump(num);   ;; 8\n}\n```\n\n**References:**\n\n- [Operators](/languages/func/operators)\n- [Loops](/languages/func/statements#loops)\n\n### How to convert the ASCII digits in a slice into an int\n\n```func\n;; Example slice containing ASCII digits\nslice string_number = \"26052021\";\n;; This variable will hold the final number\nint number = 0;\n\n;; Repeat while there is still data in the slice\nwhile (~ string_number.slice_empty?()) {\n    ;; Load 8 bits (one char) from the slice.\n    ;; \"x\" stores the decimal ASCII code of the char.\n    int x = string_number~load_uint(8);\n    ;; Char '0' has code 48. Substract it\n    ;; to get the digit as a number.\n    x -= 48;\n    ;; Accumulate the result.\n    number = (number * 10) + x;\n}\n```\n\n**References:**\n\n- [Modifying notation using \\~](/languages/func/expressions#modifying-notation)\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [`load_uint`](/languages/func/stdlib#load-uint)\n- [`\"<ascii string>\"` compile-time builtin](/languages/func/literals#string-without-suffix), where `<ascii string>` is an ASCII string.\n\n### How to convert an int into ASCII digits stored in a slice\n\n```func\n;; Example number to transform\nint n = 261119911;\n\n;; This will store the partially constructed string\nbuilder string = begin_cell();\n\n;; \"chars\" will be a lisp-style list, where each element\n;; is the decimal ASCII code of a digit.\n;; The list will store the ASCII codes of each digit\n;; in the number.\n;; So, since the number is 261119911, the list will be:\n;; ASCII code of 2, ASCII code of 6, ASCII code of 1, .....\n;; Initially, the list has the \"null\" value, to signal\n;; that it is empty.\ntuple chars = null();\n\ndo {\n    ;; Obtain the righmost digit in n\n    ;; and remove it from n\n    int r = n~divmod(10);\n\n    ;; Transform the digit \"r\" into its decimal ASCII code\n    ;; and place it as first element in the list.\n    ;; Even tough the digits of n are processed\n    ;; starting from the rigthmost, the list\n    ;; is filled back to front, ensuring that\n    ;; ASCII codes in the list match the order\n    ;; of the digits in the original \"n\"\n    chars = cons(r + 48, chars);\n} until (n == 0); ;; Stop until all digits are processed.\n\n;; Now, iterate the list.\ndo {\n    ;; Get the element at the head of the list\n    ;; and remove it from the list\n    int char = chars~list_next();\n\n    ;; Store the decimal ASCII code as a binary 8-bit ASCII code\n    string~store_uint(char, 8);\n} until (null?(chars));  ;; Stop until reaching the end of the list\n\n;; Transform the cell into a slice\nslice result = string.end_cell().begin_parse();\n```\n\n**References:**\n\n- [Modifying notation using \\~](/languages/func/expressions#modifying-notation)\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [`begin_cell`](/languages/func/stdlib#begin-cell)\n- [`end_cell`](/languages/func/stdlib#end-cell)\n- [`begin_parse`](/languages/func/stdlib#begin-parse)\n- [`null`](/languages/func/stdlib#null)\n- [`divmod`](/languages/func/stdlib#divmod)\n- [`store_uint`](/languages/func/stdlib#store_uint)\n- [List-style lists](/languages/func/stdlib#lisp-style-lists)\n\n## Errors\n\n### How to throw errors\n\nThe following snippet summarizes the main ways of throwing exceptions in FunC,\nby using functions `throw_if`, `throw_unless` and `throw`.\n\n```func\nint number = 198;\n\n;; The error 35 is thrown only if the number is greater than 50.\n;; In general, throw_if(n, cond) will throw error \"n\"\n;; only if \"cond\" is true.\nthrow_if(35, number > 50);\n\n;; the error 39 is thrown only if the number is NOT EQUAL to 198.\n;; In general, throw_unless(n, cond) will throw error \"n\"\n;; only if \"cond\" is false.\nthrow_unless(39, number == 198);\n\n;; the error 36 is thrown unconditionally\nthrow(36);\n```\n\n**References:**\n\n- [TVM exception codes](/tvm/exit-codes)\n- [`throw_if`](/languages/func/stdlib#throw-if)\n- [`throw_unless`](/languages/func/stdlib#throw-unless)\n- [`throw`](/languages/func/stdlib#throw)\n\n## Addresses\n\n### Generate an internal address\n\nWhen deploying a new contract, there is the need to generate its internal address because it is initially unknown. The internal address can be generated from the contract's `StateInit`, which contains the code and data of the new contract.\n\nAccording to the `MsgAddressInt` TL-B schema, an internal address is composed of the following headers:\n\n```text\naddr_std$10 anycast:(Maybe Anycast) workchain_id:int8 address:bits256;\n```\n\nTherefore, to create an internal address, the above headers must be written in a cell, where `address` header is computed using the hash of the contract's `StateInit`. The following function creates an internal address that follows these headers, and stores the address in a cell, which finally gets transformed into a slice, as slices tend to be the preferred format for storing internal addresses.\n\n```func\nslice generate_internal_address (int workchain_id, cell state_init) {\n    return begin_cell()\n        ;; Header addr_std$10, requires the bits 10,\n        ;; i.e., 2 as an unsigned integer\n        .store_uint(2, 2)\n        .store_uint(0, 1) ;; anycast header defaults to nothing\n        ;; workchain_id, 8-bits signed integer\n        .store_int(workchain_id, 8)\n        ;; The address as 256-bit unsigned integer.\n        ;; Use the function cell_hash to compute\n        ;; a hash of the provided state_init.\n        ;; This hash acts as the address.\n        .store_uint(cell_hash(state_init), 256)\n    .end_cell().begin_parse();\n}\n```\n\nRefer to recipe [\"How to build a `StateInit` cell\"](#how-to-build-a-stateinit-cell). Additionally, refer to recipe [\"How to send a deploy message\"](#how-to-send-a-deploy-message) for sending a deploy message.\n\nFurther information on workchain IDs are found in the [docs](/foundations/addresses/overview#workchain-id).\n\n**References:**\n\n- [Modifying notation using \\~](/languages/func/expressions#modifying-notation)\n- [Non-modifying notation using .](/languages/func/expressions#non-modifying-notation)\n- [`begin_cell`](/languages/func/stdlib#begin-cell)\n- [`end_cell`](/languages/func/stdlib#end-cell)\n- [`begin_parse`](/languages/func/stdlib#begin-parse)\n- [`cell_hash()`](/languages/func/stdlib#cell-hash)\n- [`store_uint`](/languages/func/stdlib#store-uint)\n- [`store_int`](/languages/func/stdlib#store-int)\n- [Workchain ID](/foundations/addresses/overview#workchain-id)\n- [Internal addresses](/foundations/addresses/overview#internal-addresses)\n\n### Generate an external address\n\nUse the TL-B scheme from [block](https://github.com/ton-blockchain/ton/blob/24dc184a2ea67f9c47042b4104bbb4d82289fac1/crypto/block/block.tlb#L101C1-L101C12) to determine the address format to generate an external address.\n\n```func\n(int) ubitsize (int a) asm \"UBITSIZE\";\n\nslice generate_external_address (int address) {\n    ;; addr_extern$01 len:(## 9) external_address:(bits len) = MsgAddressExt;\n\n    int address_length = ubitsize(address);\n\n    return begin_cell()\n        .store_uint(1, 2) ;; addr_extern$01\n        .store_uint(address_length, 9)\n        .store_uint(address, address_length)\n    .end_cell().begin_parse();\n}\n```\n\nSince there is a need to find the exact number of bits occupied by the address, [declare an asm function](#how-to-write-custom-functions-using-asm-keyword) with the `UBITSIZE` opcode. This function will return the minimum number of bits required to store a given number.\n\n**Reference:** [TVM instructions](/tvm/instructions#B603)\n"
  },
  {
    "path": "languages/func/declarations-overview.mdx",
    "content": "---\ntitle: \"Program declarations\"\nsidebarTitle: \"Overview\"\nnoindex: \"true\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nA FunC program is a list of:\n\n- [Function declarations and definitions](/languages/func/functions)\n- [Global variable declarations](/languages/func/global-variables)\n- [Compiler directives](/languages/func/compiler-directives)\n"
  },
  {
    "path": "languages/func/dictionaries.mdx",
    "content": "---\ntitle: \"FunC dictionaries\"\nsidebarTitle: \"Dictionaries\"\nnoindex: \"true\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nSmart contracts in TON can utilize dictionaries structured as ordered key-value mappings. Internally, these dictionaries are represented as tree-like structures composed of cells.\n\n<Aside\n  type=\"caution\"\n>\n  Handling potentially large trees of cells in TON introduces several important considerations:\n\n  - **Gas consumption for updates**\n    - Every update operation generates many new cells, costing 500 gas, as detailed on the [TVM instructions](/tvm/instructions) page.\n    - Careless updates can lead to excessive gas usage, potentially causing operations to fail due to gas exhaustion.\n    - Example: This issue occurred with the **Wallet bot** using the **highload-v2 wallet**. Each iteration's unbounded loop and expensive dictionary updates led to gas depletion. As a result, the bot triggered repeated transactions, eventually draining its balance ([see transaction details](https://tonviewer.com/transaction/fd78228f352f582a544ab7ad7eb716610668b23b88dae48e4f4dbd4404b5d7f6)).\n\n  - **Storage limitation**\n    - A binary tree containing $N$ key-value pairs requires $N-1$ forks, resulting in **at least** $2N-1$ cells.\n    - Since smart contract storage in TON is capped at 65,536 unique cells, the maximum number of dictionary entries is approximately 32,768. This limit may be slightly higher if some cells are reused within the structure.\n</Aside>\n\n## Dictionary kinds\n\n### \"Hash\" map\n\nHashmaps are the most widely used dictionary type in TON. They have a dedicated set of TVM opcodes for manipulation and are commonly used in smart contracts (see [TVM instructions](/tvm/instructions) - Dictionary manipulation).\n\nHashmaps map fixed-length keys, which are defined as an argument to all functions, to value slices. Despite the \"hash\" in its name, entries are ordered and allow efficient access to elements by key and retrieval of the previous or next key-value pair. Since values share space with internal node tags and possibly key fragments within the same cell, they cannot utilize the full 1023 bits. In such cases, the `~udict_set_ref` function often helps.\n\nAn empty hashmap is represented as `null` in TVM, meaning it is not stored as a cell. A single bit is first saved to store a dictionary in a cell (0 for empty, 1 otherwise), followed by a reference if the hashmap is not empty. This makes `store_maybe_ref` and `store_dict` interchangeable. Some smart contract developers use `load_dict` to load a `Maybe ^Cell` from an incoming message or storage.\n\n**Available hashmap operations:**\n\n- Load from a slice, store to a builder;\n- Get/Set/Delete a value by key;\n- Replace a value (update an existing key) or add a new value (if the key is absent);\n- Move to the next/previous key-value pair (entries are ordered by keys, enabling [iteration](/languages/func/cookbook#how-to-iterate-dictionaries) if gas constraints allow);\n- Retrieve the minimal or maximal key with its value;\n- Fetch and execute a function (continuation) by key.\n\nTo prevent gas exhaustion, smart contracts should limit the number of dictionary updates per transaction. If a contract's balance is used to maintain the hashmap under specific conditions, it can send itself a message to continue processing in another transaction.\n\n<Aside>\n  TVM provides instructions for retrieving a sub-dictionary — a subset of entries within a given key range. These operations (`SUBDICTGET` and similar) are currently untested and can only be explored at the TVM assembly level.\n</Aside>\n\n#### Hashmap examples\n\nTo illustrate, let's examine a hashmap that maps 257-bit integer keys to empty value slices. This type of hashmap serves as a presence indicator, storing only the existence of elements.\n\nYou can quickly check this by running the following Python script. If needed, you can use a different SDK instead of `pytoniq`:\n\n```python\nimport pytoniq\nk = pytoniq.HashMap(257)\nem = pytoniq.begin_cell().to_slice()\nk.set(5, em)\nk.set(7, em)\nk.set(5 - 2**256, em)\nk.set(6 - 2**256, em)\nprint(str(pytoniq.begin_cell().store_maybe_ref(k.serialize()).end_cell()))\n```\n\nThis structure forms a binary tree, which appears balanced except for the root cell:\n\n```\n1[80] -> {\n  2[00] -> {\n    265[9FC00000000000000000000000000000000000000000000000000000000000000080] -> {\n      4[50],\n      4[50]\n    },\n    266[9FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40] -> {\n      2[00],\n      2[00]\n    }\n  }\n}\n```\n\nFor further [examples of hashmap parsing](/languages/tl-b/overview#hashmap-parsing-example), refer to the official documentation.\n\n### Augmented maps\n\nAugmented maps with additional data in each node are used internally by TON validators to calculate the total balance of all contracts in a shard. By storing the total subtree balance in each node, validators can quickly validate updates. There are no TVM primitives for working with these maps.\n\n### Prefix dictionary\n\n<Aside>\n  Testing shows that documentation on prefix dictionaries is insufficient. Avoid using them in production contracts unless you fully understand how the relevant opcodes, such as `PFXDICTSET`, work.\n</Aside>\n"
  },
  {
    "path": "languages/func/expressions.mdx",
    "content": "---\ntitle: \"FunC expressions\"\nsidebarTitle: \"Expressions\"\nnoindex: \"true\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nExpressions in FunC combine literals, variables, operators, and function calls to produce a value when evaluated.\n\nAn expression in FunC can be:\n\n- A [number literal](/languages/func/literals#number-literals)\n- An [identifier](/languages/func/literals#identifiers)\n- A [compile-time builtin](/languages/func/literals#compile-time-built-ins)\n- An [operator](/languages/func/operators)\n- A [variable declaration](#variable-declaration)\n- A [function call](#function-call)\n\nWe focus on variable declarations and function calls, since the other kind of expressions are explained in their respective articles.\n\nAs a general rule, all sub-expressions inside an expression are evaluated from left to right,\nexcept in cases where [asm stack rearrangement](/languages/func/functions#rearranging-stack-entries) explicitly defines the order.\n\n## Variable declaration\n\nLocal variables must be initialized at the time of declaration. Since variable declarations are expressions, the result of evaluating a declaration like:\n\n```func\ntype iden = expr\n```\n\nreturns the value produced by `expr`, in addition to defining variable `iden` with value `expr`.\n\nFor instance: `(int x = 3) + x;` declares `x` and assigns to it the value `3`. The result of the expression `(int x = 3)` is therefore `3`, which means that `(int x = 3) + x` evaluates to `6`, since `x` has value `3` after the declaration.\n\nHere are further examples of variable declarations, where each line is independent from the other ones. It is possible to use the keyword `var` to let the type checker infer the type, see [hole types](/languages/func/types#hole-type).\n\n```func\nint x = 2;\nvar x = 2;               ;; Equivalent to previous, but with type inference\n(int, int) p = (1, 2);\n(int, var) p = (1, 2);   ;; Equivalent to previous, but with type inference\n[int, var, int] t = [1, 2, 3];\n```\n\nIn the previous examples, `p` and `t` store the entire tensor and tuple, respectively. But it is possible to deconstruct tensors and tuples and assign each component to different variables. Here are some examples that showcase different ways of deconstructing tensors and tuples:\n\n```func\n(int x, int y, int z) = (1, 2, 3);       ;; Assign each tensor component to x, y, and z.\n(int, int, int) (x, y, z) = (1, 2, 3);   ;; Equivalent to previous\nvar (x, y, z) = (1, 2, 3);               ;; Equivalent to previous, but with type inference\n(int x = 1, int y = 2, int z = 3);       ;; Assigning each component directly\n[int x, int y, int z] = [1, 2, 3];       ;; Assign each tuple component to x, y, and z\n[int, int, int] [x, y, z] = [1, 2, 3];   ;; Equivalent to previous\nvar [x, y, z] = [1, 2, 3];               ;; Equivalent to previous, but with type inference\n```\n\nA variable can be redeclared in the same scope. For example, the following code is valid:\n\n```func\nint x = 2;\nint y = x + 1;\nint x = 3;\n```\n\nIn this example, the second occurrence of `int x` is not a new declaration but a compile-time check ensuring that `x` has type `int`. The third line is equivalent to `x = 3;`.\n\nThe following example, which redeclares `x` with type `(int, int)` at the third line, is also valid:\n\n```func\nint x = 2;\nint y = x + 1;\n(int, int) x = (y, y + 1);\n```\n\nAfter the third line, variable `x` has type `(int, int)`.\n\n### Variable redeclaration in nested scopes\n\nIn nested scopes, a new variable with the same name can be declared, just like in C:\n\n```func\nint x = 0;\nint i = 0;\nwhile (i < 10) {\n  (int, int) x = (i, i + 1);\n  ;; Here x is a variable of type (int, int)\n  i += 1;\n}\n;; Here, x refers to the original variable of type int declared above\n```\n\nHowever, global variables **cannot** be redeclared. See [Global variables](/languages/func/global-variables/).\n\n### Underscore\n\nThe underscore `_` is used when a value is not needed.\nFor example, if `foo` is a function of type `int -> (int, int, int)`,\nyou can retrieve only the first return value while ignoring the rest:\n\n```func\n(int fst, _, _) = foo(42);\n```\n\n## Function call\n\nA function call in FunC follows a conventional syntax: the function name is followed by its arguments, separated by commas. However, unlike many conventional languages, FunC also treats functions as taking a single tensor argument.\n\nFor example, suppose `foo` is a function of type `(int, int, int) -> int`. The following two lines are equivalent ways of calling `foo`:\n\n```func\nint x = foo(1, 2, 3);    ;; Three arguments separated by ,\nint x = foo((1, 2, 3));  ;; The tensor (1, 2, 3) passed as a single argument\n```\n\nEquivalently, we could also assign tensor `(1, 2, 3)` to a variable, and then call `foo`:\n\n```func\n(int, int, int) t = (1, 2, 3);\nint x = foo(t);    ;; Pass the tensor as a single argument\n```\n\n### Function composition\n\nTo illustrate how function composition works in FunC, suppose that together with the previous `foo` function, there is also a `bar` function of type `int -> (int, int, int)`.\n\nSince `foo` expects a single tensor argument, you can pass the entire result of `bar(42)` directly into `foo`:\n\n```func\nint x = foo(bar(42));\n```\n\nThis is equivalent to the longer form, which decomposes the result tensor of `bar(42)` and then calls `foo` by passing all arguments separated by commas:\n\n```func\n(int a, int b, int c) = bar(42);\nint x = foo(a, b, c);\n```\n\n### Functions as first-class objects\n\nIn FunC, functions are first-class objects: they can be assigned to variables, passed as arguments to other functions, and returned from functions.\n\nFor example, the following function `apply`, receives a function `f` of type `int -> int`, and a value `v` of type `int` as arguments. Function `apply` invokes `f` with argument `v` and returns the result of the application, i.e., `apply` computes the expression `f(v)`.\n\n```func\nint apply(int -> int f, int v) {\n  return f(v);\n}\n```\n\nLet us suppose we have an increment function:\n\n```func\nint inc(int x) {\n  return x + 1;\n}\n```\n\nWe can then invoke `apply` by passing the increment function:\n\n```func\napply(inc, 2);   ;; produces 3, or equivalently, inc(2)\n```\n\nIt is also possible to assign the increment function to variables:\n\n```func\nvar f = inc;\n```\n\nor return it from functions:\n\n```func\nint -> int return_inc() {\n  return inc;\n}\n```\n\n<Aside>\n  FunC does not support lambda expressions. This means that it is not possible to create [anonymous functions](https://en.wikipedia.org/wiki/Anonymous_function).\n</Aside>\n\n### Special function call notation\n\nIn addition to the standard syntax for calling a function, FunC supports two function call notations for specific situations, the [non-modifying notation](#non-modifying-notation), and the [modifying notation](#modifying-notation), which are explained next.\n\n#### Non-modifying notation\n\nIn FunC, a function with at least one argument can be called using the dot `.` notation, also called _non-modifying notation_.\n\nFor example, the function `store_uint`, which stores an unsigned integer into a cell builder and returns the modified builder, has type `(builder, int, int) -> builder`, where:\n\n- The first argument is the builder object.\n- The second argument is the value to store.\n- The third argument is the unsigned integer bit length.\n\nThe following way of calling `store_uint`:\n\n```func\nbuilder b = begin_cell();\nb = store_uint(b, 239, 8);\n```\n\nis equivalent to:\n\n```func\nbuilder b = begin_cell();\nb = b.store_uint(239, 8);   ;; Uses non-modifying notation\n```\n\nThe dot `.` notation allows the first argument of a function to be placed before the function name,\nsimplifying the code further:\n\n```func\nbuilder b = begin_cell().store_uint(239, 8);\n```\n\nwhich is equivalent to the standard syntax for calling a function:\n\n```func\nbuilder b = store_uint(begin_cell(), 239, 8);\n```\n\nUsing the `.` notation it is possible to chain many function calls together:\n\n```func\nbuilder b = begin_cell().store_uint(239, 8)\n                        .store_int(-1, 16)\n                        .store_uint(0xff, 10);\n```\n\nwhich is equivalent to the longer form:\n\n```func\nbuilder b = begin_cell();\nb = b.store_uint(239, 8);\nb = b.store_int(-1, 16);\nb = b.store_uint(0xff, 10);\n```\n\nor to the more difficult to read form, which nests all the calls:\n\n```func\nbuilder b = store_uint(\n    store_int(\n        store_uint(\n             begin_cell(),\n             239,\n             8),\n        -1,\n        16),\n    0xff,\n    10\n);\n```\n\n#### Modifying notation\n\nIf a function's first argument is of type `A` and its return type follows the structure `(A, B)`, where `B` is an arbitrary type, the function can be called using the `~` notation, also called _modifying notation_.\n\nThe primary purpose of the `~` notation is to automatically update the first argument in a function call. More concretely, suppose `foo` is a function of type `(builder, int, int) -> (builder, int)`, then the call `v = b~foo(2, 3)`, which uses the `~` notation, is equivalent to the standard call `(b, v) = foo(b, 2, 3)`. The statement `(b, v) = foo(b, 2, 3)` reassigns (or updates) the first argument `b` after the call to `foo` finishes. The `~` notation serves as a shortcut to express this reassignment of the first argument.\n\nOne possible application of the `~` notation is for working with cell slices. For example, consider a cell slice `cs` and the function `load_uint`, which has type: `(slice, int) -> (slice, int)`. The function `load_uint` takes a cell slice and a number of bits to load, returning the remaining slice and the loaded unsigned integer value.\n\nThe following three calls are equivalent:\n\n```func\n(cs, int x) = load_uint(cs, 8);     ;; Standard function call\n(cs, int x) = cs.load_uint(8);      ;; Call using non-modifying notation (i.e., `.`)\nint x = cs~load_uint(8);            ;; Call using modifying notation (i.e., `~`)\n```\n\n#### Adapting functions to use `~`\n\nWhen a function type is of the form `(A, ...) -> A`, it is possible to adapt the function so that the `~` notation can be used on such a function. This can be achieved using unit types, by redefining the function type to `(A, ...) -> (A, ())`.\n\nFor example, consider an increment function `inc` of type `int -> int`:\n\n```func\nint inc(int x) {\n  return x + 1;\n}\n```\n\nTo increment a variable `y` using `inc`, the function should be used as follows:\n\n```func\ny = inc(y);\n```\n\nAttempting to use the `~` notation on `inc` would fail:\n\n```func\ny~inc();    ;; DOES NOT COMPILE\n```\n\nbecause `inc` does not have a return type of the form `(int, B)`, where `B` is some type.\n\nTo use the `~` notation on `inc`, first redefine the function so that it now has type `int -> (int, ())` as follows:\n\n```func\n(int, ()) inc(int x) {\n  return (x + 1, ());\n}\n```\n\nNow, the following code increments `y`:\n\n```func\ny~inc();\n```\n\n#### `.` and `~` in function names\n\nPreviously, we redefined `inc` to have type `int -> (int, ())` so that it was possible to use the `~` notation on it.\n\nHowever, it would be bothersome to use `inc` in cases where we do not want to increment a variable, but we just want to store the increment in a different variable:\n\n```func\n(int y, _) = inc(x);\n```\n\nIn other words, we would _also_ like to use `inc` as if it was the original function with type `int -> int`:\n\n```func\nint y = inc(x);\n```\n\nIn FunC, it is possible to _also_ keep the original `inc` of type `int -> int` so that we can use `inc` in different ways, like:\n\n```func\nx~inc(); ;; Increments x, using modifying notation\nint y = inc(x); ;; Doesn't modify x, but stores the increment in y\nint z = x.inc(); ;; Equivalent to previous, but using non-modifying notation\n```\n\nThis is achieved by declaring a function `~inc` alongside the original `inc`:\n\n```func\nint inc(int x) {    ;; Original inc function\n  return x + 1;\n}\n(int, ()) ~inc(int x) {  ;; inc version to be able to use ~ notation\n  return (x + 1, ());\n}\n```\n\nThis is possible because of the way FunC resolves function calls:\n\n- If a function is called with `.`, e.g., `x.foo()`, the compiler looks for a `.foo` definition.\n- If a function is called with `~`, e.g., `x~foo()`, the compiler looks for a `~foo` definition.\n- If neither `.foo` nor `~foo` is defined, the compiler falls back to the regular `foo` definition.\n"
  },
  {
    "path": "languages/func/functions.mdx",
    "content": "---\ntitle: \"FunC functions\"\nsidebarTitle: \"Functions\"\nnoindex: \"true\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nEvery function declaration or definition follows a common pattern. The general form is:\n\n```func\n[<forall declarator>] <return type> <function name>(<comma separated function args>) <specifiers> <function body>\n```\n\nwhere `[ ... ]` represents an optional entry. Here,\n\n- `<forall declarator>` is the [`forall` declarator](#forall-declarator), which declares that the function is [polymorphic](https://en.wikipedia.org/wiki/Parametric_polymorphism). This is optional.\n- `<return type>` is the [return type](#return-type) of the function.\n- `<function name>` is the [function name](#function-name).\n- `<comma separated function args>` is a comma separated list of [function arguments](#function-arguments), each argument consisting on a type and the argument's name.\n- `<specifiers>` are [specifiers](#specifiers) that instruct the compiler on how to process the function.\n- `<function body>` is the actual [function body](#function-body), which can be of three kinds: an [empty body](#empty-body), an [assembler body](#assembler-body), or a [standard body](#standard-body).\n\n## Return type\n\nThe return type can be any atomic or composite type, as described in the [Types](/languages/func/types) section.\n\nFor example, the following functions are valid:\n\n```func\nint foo() { return 0; }\n(int, int) foo'() { return (0, 0); }\n[int, int] foo''() { return [0, 0]; }\n(() -> int) foo'''() { return foo; }\n() foo''''() { return (); }\n```\n\nFunC also supports **type inference** with the use of underscore `_` as the return type.\n\nFor example:\n\n```func\n_ divAndMod(int m, int n) {\n  return (m /% n);\n}\n```\n\nThere, the function `divAndMod` has the inferred type `(int, int) -> (int, int)`. The function computes the division and modulo of the parameters `m` and `n` by using the [division and modulo](/languages/func/operators#division-and-modulo%2C-%2F%25) operator `/%`, which always returns a two-element tensor `(int, int)`.\n\n## Function name\n\nA function name can be any valid [identifier](/languages/func/literals#identifiers). Additionally, it may start with the symbols `.` or `~`, which have specific meanings explained in the [special function call notation](/languages/func/expressions#special-function-call-notation) section. Specifically, refer to this [section](/languages/func/expressions#and-in-function-names) to understand how the symbols `.` or `~` affect the function name.\n\nFor example, `udict_add_builder?`, `dict_set`, and `~dict_set` are all valid function names, and each is distinct. These functions are defined in [stdlib.fc](/languages/func/stdlib).\n\nFunC reserves several function names. See the [reserved functions](/languages/func/special-functions) article for more details.\n\n## Function arguments\n\nA function can receive zero or more argument declarations, each declaration separated by a comma. The following kinds of argument declarations are allowed:\n\n- Ordinary declaration: an argument is declared using **its type** followed by **its name**. Example:\n\n  ```func\n  int foo(int x) {\n    return x + 2;\n  }\n  ```\n\n  Here, `int x` declares an argument named `x` of type `int` in function `foo`.\n\n  An example that declares multiple arguments:\n\n  ```func\n  int foo(int x, int y) {\n    return x + y;\n  }\n  ```\n\n  An example that declares no arguments:\n\n  ```func\n  int foo() {\n    return 0;\n  }\n\n  ```\n\n- Unused argument declaration: only its type needs to be specified. Example:\n\n  ```func\n  int first(int x, int) {\n    return x;\n  }\n  ```\n\n  This is a valid function of type `(int, int) -> int`, but the function does not use its second argument.\n\n- Argument with inferred type declaration: If an argument's type is not explicitly declared, it is inferred by the type-checker. For example,\n\n  ```func\n  int inc(x) {\n    return x + 1;\n  }\n  ```\n\n  This defines a function `inc` with the inferred type `int -> int`, meaning `x` is automatically recognized as an `int`.\n\n<Aside>\n  Even though a function may appear to take multiple arguments, it takes a single [tensor type](/languages/func/types#tensor-types) argument. For more details on this distinction, refer to the [function call](/languages/func/expressions#function-call) section.\n\n  However, for convenience, the individual components of this tensor are conventionally referred to as function arguments.\n</Aside>\n\n## Specifiers\n\nIn FunC, function specifiers modify the behavior of functions. There are three types:\n\n1. `impure`\n1. Either `inline` or `inline_ref`, but not both\n1. `method_id`\n\nOne, multiple, or none can be used in a function declaration. However, they must appear in the order of the above list, e.g., `impure` must come before `inline` and `method_id`, `inline_ref` must come before `method_id`, etc.\n\n### `impure` specifier\n\nThe `impure` specifier indicates that a function has side effects, such as modifying contract storage, sending messages, or throwing exceptions. If a function is not marked as `impure` and its result is unused, the FunC compiler may delete the function call for optimization.\n\nFor example, the [stdlib.fc](/languages/func/stdlib) function [`random`](/languages/func/stdlib#random) changes the internal state of the random number generator:\n\n```func\nint random() impure asm \"RANDU256\";\n```\n\nThe `impure` keyword prevents the compiler from removing calls to this function:\n\n```func\nvar n = 0;\nrandom();     ;; Even though the result of random is not used,\n              ;; the compiler will not remove this call\n              ;; because random has the impure specifier.\n```\n\n### Inline specifier\n\nA function marked as `inline` is directly substituted into the code wherever it is called, eliminating the function call overhead. Recursive calls are not allowed for inline functions.\n\nFor example:\n\n```func\n(int) add(int a, int b) inline {\n    return a + b;\n}\n```\n\nSince the `add` function is marked with the `inline` specifier, the compiler substitutes `add(a, b)` with `a + b` directly in the code.\n\nFor instance, the compiler will replace the following code:\n\n```func\nvar a = 1;\nvar b = 2;\nvar n = add(a, b);\n```\n\nwith this code:\n\n```func\nvar a = 1;\nvar b = 2;\nvar n = a + b;\n```\n\n### `inline_ref` specifier\n\nWhen a function is marked with the `inline_ref` specifier, its code is stored in a separate cell. Each time the function is called, the TVM executes a `CALLREF` command, which loads the code stored in the referenced cell and executes the function code.\n\nTo give you a very high level idea on how to visualize this, think how programs are stored in the blockchain. Anything in the blockchain is a cell. A program is a [directed acyclic graph (DAG)](/foundations/whitepapers/tblkch#1-1-1-tvm-cells) of cells. Each cell stores TVM instructions, and can have up to 4 references to other cells. Each one of those references represent code that the TVM can jump to.\n\nSo, you can picture a program like this:\n\n```text\nCell 1\n\ninstruction 1\ninstruction 2\n.....\ncall reference A\n.....\ninstruction n\n----------------------------------------\nReference to cell A | Reference to cell B |\n```\n\nwhere `Reference to cell A`, and `Reference to cell B` are references to other cells containing further code of the program. When the TVM executes the instruction `call reference A`, the TVM loads the cell referenced by `Reference to cell A` and executes the cell.\n\nWhen a function is marked as `inline_ref`, its code is placed in a separate cell, name it `C`. Then, everywhere the function is called in the original program,\nit is replaced with a `call reference C`. Then, the reference to `C` is added to the original program as a cell reference.\n\nMore concretely, imagine the following program:\n\n```func\nint foo() inline_ref {\n  return 1;\n}\n\nint main() {\n  return (foo() + foo());\n}\n```\n\nThen, this would create two cells, one storing the code of the `main` function, call it cell `M`; and another cell storing the code of the `foo` function, because it is marked as `inline_ref`, call it cell `F`. The two calls to `foo` inside `main` will be replaced by reference calls to `F`.\n\nAnd the reference to `F` is added as a reference in cell `M`:\n\n```text\nCell M\n\ncall reference to F\ncall reference to F\nADD\n----------------------------------------\nReference to F |\n\n\nCell F\n\n1 PUSHINT\n```\n\nWhen `call reference to F` executes, the TVM loads the cell for `F` and executes it.\n\nAs the example suggests, contrary to the `inline` specifier, the code for `foo` is not duplicated, because the two calls for `foo` are loading the same cell. As such, `inline_ref` is generally more efficient regarding code size.\n\nThe only case where `inline` might be preferable is if the function is called just once, because loading cell references costs gas.\n\nHowever, recursive calls to `inline_ref` functions remain impossible, as TVM cells do not support cyclic references.\n\n### `method_id` specifier\n\nIn a TVM program, every function has an internal integer ID that identifies it uniquely. These IDs are necessary because of the way the TVM calls functions within a program: it uses a dictionary where each key is a function ID that maps to the corresponding function code. When the TVM needs to invoke a particular function, the TVM looks up the ID in the dictionary and executes the corresponding code.\n\nBy default, functions are assigned sequential numbers starting from `1`. If a function has the `method_id` specifier, the compiler will compute an ID using the formula `(crc16(<function_name>) & 0xffff) | 0x10000` instead. Additionally, such function becomes a get-method (or getter method), which are functions that can be invoked by its name in lite client or TON explorer.\n\nThe `method_id` specifier has the variant `method_id(<some_number>)`, which allows you to set a function's ID to a specific number manually.\n\nFor example, this defines a function whose ID is computed by the compiler and the function is available as a get-method in TON blockchain explorers:\n\n```func\nint get_counter() method_id {\n  load_data();\n  return ctx_counter;  ;; Some global variable\n}\n```\n\nThis other example defines the same function, but this time it sets the specific ID `65536`. Again, the function is available as a get-method in TON explorers.\n\n```func\nint get_counter() method_id(65536) {\n  load_data();\n  return ctx_counter;  ;; Some global variable\n}\n```\n\n<Aside\n  type=\"caution\"\n  title=\"Important limitations and recommendations\"\n>\n  **19-bit limitation**: Method IDs are limited to signed 19-bit integers, meaning the valid range is from `-2^18` (inclusive) to `(2^18 - 1)` (inclusive),\n  i.e., from `-262,144` to `262,143`.\n\n  **Reserved ranges**:\n\n  - -4 to 0 for [special functions](/languages/func/special-functions): `main` or `recv_internal` (ID = 0), `recv_external` (ID = -1), `run_ticktock` (ID = -2), `split_prepare` (ID = -3), `split_install` (ID = -4)\n  - 1 to 999 for additional functions (approximate range).\n  - 65536 and above: default range for user functions when using automatic generation: `(crc16(function_name) & 0xffff) | 0x10000`\n\n  **Best practice**: It's recommended to **avoid setting method IDs manually** and rely on automatic generation instead. Manual assignment can lead to conflicts and unexpected behavior.\n</Aside>\n\n## Function body\n\n### Empty body\n\nAn empty body, marked with a single semicolon `;` indicates that the function is declared but not yet defined. Its definition must appear later in the same file or a different file processed before the current one by the FunC compiler. A function with an empty body is also called a _function declaration_.\n\nFor example:\n\n```func\n int add(int x, int y);\n```\n\nThis declares a function named `add` with type `(int, int) -> int` but does not define it.\n\nIn FunC, all functions must be defined or declared before using them in other functions, which explains the need for function declarations.\n\nFor example, the following code calls function `foo` inside the `main` function, but `foo` is defined _after_ `main`.\n\nHence, the compiler rejects the code:\n\n```func\n() main() {\n  var a = foo();    ;; DOES NOT COMPILE\n                    ;; foo is not declared nor\n                    ;; defined before main\n}\n\nint foo() {\n  return 0;\n}\n```\n\nTo fix the error, either declare `foo` before `main`:\n\n```func\nint foo();      ;; foo declared before main,\n                ;; but defined after main\n\n() main() {\n  var a = foo();\n}\n\nint foo() {\n  return 0;\n}\n```\n\nOr move the definition of `foo` before main:\n\n```func\nint foo() {\n  return 0;\n}\n\n() main() {\n  var a = foo();\n}\n```\n\n### Assembler body\n\nAn assembler body defines the function using low-level TVM primitives for use in a FunC program. The body consists on the keyword `asm`, followed a list of TVM instructions, and ending with symbol `;`.\n\nFor example:\n\n```func\n  int add(int x, int y) asm \"ADD\";\n```\n\nThis defines the function `add` of type `(int, int) -> int`, using the TVM instruction `ADD`.\n\nRefer to the [assembler functions](/languages/func/asm-functions) article for more details.\n\n### Standard body\n\nA standard body uses a [block statement](/languages/func/statements#block-statement), i.e., the body of the function is defined inside curly braces `{ }`.\n\nFor example:\n\n```func\nint add(int x, int y) {\n  return x + y;\n}\n```\n\nThis defines a function that adds its two arguments and returns the result of the addition.\n\n## `forall` declarator\n\nThe `forall` declarator has the following syntax:\n\n```func\nforall <comma separated list of type variables names> ->\n```\n\nThe declarator starts with the `forall` keyword and finishes with the symbol `->`. Each element in the comma separated list must be a type variable name. A type variable name can be any [identifier](/languages/func/literals#identifiers), but capital letters are commonly used.\n\nThe `forall` declarator makes the function a [polymorphic function](https://en.wikipedia.org/wiki/Parametric_polymorphism), meaning that when the function is called, the type variables get replaced with actual types.\n\nFor example:\n\n```func\nforall X, Y -> [Y, X] pair_swap([X, Y] pair) {\n  [X p1, Y p2] = pair;\n  return [p2, p1];\n}\n```\n\nThis function declares two type variables `X` and `Y`. The function uses these two type variables to declare an argument `pair` of type `[X, Y]`, i.e., a [tuple](/languages/func/types#tuple-types) where the first component is of type `X` and the second component of type `Y`. The function then swaps the components of the tuple and returns a tuple of type `[Y, X]`.\n\nThat `pair_swap` is polymorphic means that it can be called with tuples of type `[int, int]`, `[int, cell]`, `[cell, slice]`, `[[int, int], cell]`, etc.\n\nFor instance:\n\n- `pair_swap([2, 3])` returns `[3, 2]`. In this case, both type variables `X` and `Y` get substituted with `int`.\n- `pair_swap([1, [2, 3, 4]])` returns `[[2, 3, 4], 1]`. In this case, type variable `X` gets substituted with `int`, and `Y` with `[int, int, int]`.\n\nEven though the function is polymorphic, the compiled assembly code remains the same for any substitution of the type variables. This is possible due to the polymorphic nature of stack manipulation operations.\n\nHowever, other forms of polymorphism, such as [`ad-hoc` polymorphism](https://en.wikipedia.org/wiki/Ad_hoc_polymorphism) with type classes, are not supported.\n\n<Aside>\n  At the moment, type variables in polymorphic functions cannot be instantiated with tensor types. There is only one exception: the tensor type `(a)`, where `a` is not a tensor type itself, since the compiler treats `(a)` as if it was `a`.\n\n  This means you can't use `pair_swap` on a tuple of type `[(int, int), int]` because type `(int, int)` is a tensor type.\n</Aside>\n"
  },
  {
    "path": "languages/func/global-variables.mdx",
    "content": "---\ntitle: \"Global variables\"\nsidebarTitle: \"Global variables\"\nnoindex: \"true\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n## Definition\n\n**A global variable** is a variable that can be read and assigned at any function in the entire program, including functions declared in other `.fc` files,\nas long as those `.fc` files are [imported](/languages/func/compiler-directives#%23include) after the global\nvariable [declaration](#declaration). It is possible to use global variables imported from other `.fc` files.\n\nGlobal variables are useful for remembering values across functions, without the need to pass those values as arguments to every single function in the program.\n\nUnder the hood, global variables in FunC are stored inside the tuple of the [`c7` TVM control register](/foundations/whitepapers/tvm#1-3-2-list-of-control-registers),\nwith a maximum limit of 31 variables.\n\n## Declaration\n\nGlobal variables are declared using the `global` keyword, followed by the variable's type and name. For example:\n\n```func\nglobal ((int, int) -> int) op;\n```\n\nThis defines global variable `op` of type `(int, int) -> int`. In other words, `op` can store a function that receives two arguments and returns an integer.\n\nHere is an example that uses global variable `op`:\n\n```func\nglobal ((int, int) -> int) op;\n\nint check_commutative(int a, int b) {\n  return op(a, b) == op(b, a);\n}\n\nint add(int a, int b) {\n  return a + b;\n}\n\nint main() {\n  op = add;\n  return check_commutative(2, 3);\n}\n```\n\nThe example defines two auxiliary functions: `check_commutative` and `add`, in addition to the program entry point [`main`](/languages/func/special-functions#main).\nFunction `check_commutative` checks if the operator stored in the global variable `op` satisfies the commutative property for the specified inputs `a` and `b`.\nFunction `add`, adds its two inputs.\nFunction `main` assigns the addition function `add` to the global variable `op`. Then, it verifies the commutativity of addition for the specific values: `2`, `3`.\n\nIn FunC, you can _omit the type_ of global variables. In this case, the compiler determines the type based on how the variable is used. Equivalently,\ninstead of declaring the type, you can use the `var` keyword as a replacement for the type.\n\nFor example, in the previous program you can declare the variable `op` as:\n\n```func\nglobal op;\n```\n\nor as:\n\n```func\nglobal var op;\n```\n\nFunC allows declaring global variable multiple times, as long as all the declarations have the same type.\nThe declarations can even happen in different `.fc` files.\n\nFor example, the following does not compile, because the second declaration changes the type of `A` from `int` to `cell`:\n\n```func\nglobal int A;\n\nint foo() {\n  return 0;\n}\n\nglobal cell A;    ;; DOES NOT COMPILE, cell should be int\n```\n\n<Aside>\n  Global variables do _not_ allow initialization during declaration, contrary to local variables, which must be initialized during declaration.\n  For example,\n\n  ```func\n  global int a = 5;  ;; DOES NOT COMPILE\n  ```\n\n  Reading a global variable that has not been assigned, will result in the [`null` value](/languages/func/types#null-values).\n</Aside>\n\n<Aside>\n  Global variables do not survive after the TVM finishes execution. They are reset every time the\n  [TVM initializes](/tvm/initialization).\n  Use permanent storage to remember values between TVM executions by using the [`set_data`](/languages/func/stdlib#set-data) function.\n\n  For example, in the following code, you should **not** expect that global variable `prev_value` will remember the message value\n  `msg_value` of the previously received internal message. Because every time the contract receives an internal message,\n  the TVM initializes.\n\n  ```func\n  global int prev_value;\n\n  () recv_internal(int msg_value, cell in_msg_cell, slice in_msg) {\n    ;; ...\n    ;; ...\n    if (prev_value > 123456) {   ;; prev_value will NOT have the value\n      ;; do something            ;; of the previously received message\n    }\n    prev_value = msg_value;    ;; Use permanent storage instead\n  }\n  ```\n</Aside>\n\n## Multiple declarations\n\nFunC allows users to declare multiple global variables using a single `global` keyword.\n\nThe following example:\n\n```func\nglobal int A;\nglobal cell B;\nglobal C;\n```\n\nis equivalent to this:\n\n```func\nglobal int A, cell B, C;\n```\n\n## Restrictions on declarations\n\nA local variable **cannot** have the same name of a previously declared global variable **but only if their types differ**.\n\nThe following example does not compile, because the local variable `C` of type `int` has the same name as the global variable `C` of type `cell`,\nand `int` and `cell` are different types.\n\n```func\nglobal cell C;\n\nint main() {\n  int C = 3; ;; DOES NOT COMPILE\n  return C;\n}\n```\n\nHowever, if the local variable and the global variable have the same type and the same name, the declaration of the local variable actually means assignment\nto the global variable. For example,\n\n```func\nglobal int C;\n\nint main() {\n  int C = 3;\n  return C;\n}\n```\n\nIn this case, `int C = 3;` is not declaring a new local variable, but instead assigning value `3` to the global variable `C`.\n"
  },
  {
    "path": "languages/func/known-issues.mdx",
    "content": "---\ntitle: \"Known issues\"\nsidebarTitle: \"Known issues\"\nnoindex: \"true\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n## Constant evaluation breaks function argument substitution\n\n### Removes division by zero exception\n\nFor the following operators and arithmetic functions, the compiler carries out optimizations\nduring constant evaluation that removes the expected division by zero exception.\n\n#### Multiplication/division built-ins\n\nIssue page: [#1678](https://github.com/ton-blockchain/ton/issues/1678)\n\nFor functions [`muldiv`](/languages/func/built-ins#muldiv), [`muldivc`](/languages/func/built-ins#muldivc) and [`muldivr`](/languages/func/built-ins#muldivr),\nif any of their first two arguments is zero at compilation time, the compiler replaces the function call with 0, irrespective of the function's\nthird argument, i.e., the divisor. This means that the function calls get replaced by 0 even when the divisor is 0,\neffectively removing the expected division by zero exception.\n\nExamples:\n\n```func\n;; All these produce 0, irrespective of divisor z, \n;; even when z is 0.\nmuldiv(0, 1, z);\nmuldivc(1, 0, z);\nmuldivr(0, 1, z);\n```\n\n#### Operators /, % combined with comparison operators\n\nIssue pages: [#1659](https://github.com/ton-blockchain/ton/issues/1659),\n[#1660](https://github.com/ton-blockchain/ton/issues/1660),\n[#1661](https://github.com/ton-blockchain/ton/issues/1661),\n[#1662](https://github.com/ton-blockchain/ton/issues/1662).\n\nThe compiler simplifies the [division `/`](/languages/func/operators#division%2C-%2F) and [modulo `%`](/languages/func/operators#modulo%2C-%25) operators when their left argument is `0`,\nbut only when `/` and `%` are used in tandem with comparison operators like `>=`, `>`, `==`, etc.\n\nFor example, the following expressions are **not** simplified to 0 at compile-time, which is the correct behavior:\n\n```func\n0 / z;   ;; NOT replaced by 0\n0 % z;   ;; NOT replaced by 0\n```\n\nHowever, when comparison operators are used, the following expressions get simplified, irrespective of the value of `z`:\n\n```func\n(0 % z) >= 0;  ;; Replaced by true\n(0 / z) >= 0;  ;; Replaced by true\n(0 % z) != 1;  ;; Replaced by true\n```\n\nThis means that the FunC compiler removes the expected division by zero exception in the above examples when `z = 0`.\n\nThe following are further examples where the left operand of `/` and `%` is simplified to `0` by FunC, resulting in a final\nexpression that the compiler simplifies to `true`, irrespective of the value of `z`:\n\n```func\n(~(-1) / z) >= 0;\n((1 & (~ 1)) / z) >= 0;\n((z & 0) / z) >= 0;\n((z * 0) / z) >= 0;\n(~(-1) % z) >= 0;\n((1 & (~ 1)) % z) >= 0;\n((z & 0) % z) >= 0;\n((z * 0) % z) >= 0;\n((x & 0) % z) == 1;\n((x * 0) % z) == 1;\n((-1 % z) % 1) <= 0;\n```\n\n### Removes integer overflow exception\n\nIssue pages: [#1656](https://github.com/ton-blockchain/ton/issues/1656),\n[#1657](https://github.com/ton-blockchain/ton/issues/1657),\n[#1658](https://github.com/ton-blockchain/ton/issues/1658).\n\nThe following expressions should produce overflows for particular values of `z`,\nbut the FunC compiler simplifies them irrespective of `z`:\n\n```func\n(0 & (- z)) <= 0;     ;; Should overflow for z = -115792089237316195423570985008687907853269984665640564039457584007913129639936,\n                      ;; but simplified to true  \n(0 * (- z)) <= 0;     ;; Should overflow for z = -115792089237316195423570985008687907853269984665640564039457584007913129639936,\n                      ;; but simplified to true  \n((z / -1) % 2) > -2;  ;; Should overflow for z = -115792089237316195423570985008687907853269984665640564039457584007913129639936,\n                      ;; but simplified to true  \n```\n\nThe following are further examples of expressions that should produce integer overflows at the indicated values,\nbut the FunC compiler simplifies them to `true` irrespective of the value of `z`:\n\n```func\n(~(-1) & (-1 * z)) <= 0;         ;; for z = MIN_INT.\n((1 & (~ 1)) & (z / -1)) <= 0;   ;; for z = MIN_INT.\n((z & 0) & (z * 2)) <= 0;        ;; for z = MAX_INT \n((z * 0) & (z + 1)) <= 0;        ;; for z = MAX_INT.\n(~(-1) * (-1 * z)) <= 0;         ;; for z = MIN_INT\n((1 & (~ 1)) * (z / -1)) <= 0;   ;; for z = MIN_INT\n((z & 0) * (z * 2)) <= 0;        ;; for z = MAX_INT\n((z * 0) * (z + 1)) <= 0;        ;; for z = MAX_INT\n((-1 * z) % 2) > -2;             ;; for z = MIN_INT\n((- z) % 2) > -2;                ;; for z = MIN_INT\n((z * 2) % 2) > -2;              ;; for z = MAX_INT \n((z + 1) % 2) > -2;              ;; for z = MAX_INT\n```\n\nwhere `MIN_INT = -115792089237316195423570985008687907853269984665640564039457584007913129639936` and\n`MAX_INT = 115792089237316195423570985008687907853269984665640564039457584007913129639935`.\n\n### Incorrect results\n\n#### Involving operator `~%`\n\nIssue Page: [#1670](https://github.com/ton-blockchain/ton/issues/1670)\n\nIn the following code:\n\n```func\nint calc(int x) {\n    return ((x ~% -3) <= 0);\n}\n\nint calc3(int x, int y, int z) {\n    return ((x ~% y) <= z);\n}\n```\n\ncalling `calc(1)` produces `-1`. But calling `calc3(1,-3,0)` produces `0`. But the expected behavior is `calc(1) = calc3(1,-3,0)`, since `calc` is just a specialization of `calc3`.\n\nThe same happens with comparison operators: `<=>`, `!=`, and `==`, i.e., the following expressions also produce differing results:\n\n- `((x ~% -3) <=> 1)` in `calc` function, and `((x ~% y) <=> z)` in `cal3` function. Produces `calc(1) = -1`, and `calc3(1,-3,1) = 0`.\n- `((x ~% -3) != 1)` in `calc` function, and `((x ~% y) != z)` in `cal3` function. Produces `calc(1) = -1`, and `calc3(1,-3,1) = 0`.\n- `((x ~% -3) == 1)` in `calc` function, and `((x ~% y) == z)` in `cal3` function. Produces `calc(1) = 0`, and `calc3(1,-3,1) = -1`.\n\n#### Involving operator `^%`\n\nIssue Page: [#1669](https://github.com/ton-blockchain/ton/issues/1669)\n\nIn the following code:\n\n```func\nint calc(int x) {\n    return ((x ^% -2) <= 0);\n}\n\nint calc3(int x, int y, int z) {\n    return ((x ^% y) <= z);\n}\n```\n\ncalling `calc(1)` produces `-1`. But calling `calc3(1,-2,0)` produces `0`. But the expected behavior is `calc(1) = calc3(1,-2,0)`, since `calc` is just a specialization of `calc3`.\n\nThe same happens with comparison operators: `<=>`, `!=`, and `==`. The following expressions also produce differing results:\n\n- `((x ^% -2) <=> 1)` in `calc` function, and `((x ^% y) <=> z)` in `cal3` function. Produces `calc(1) = -1`, and `calc3(1,-2,1) = 0`.\n- `((x ^% -2) != 1)` in `calc` function, and `((x ^% y) != z)` in `cal3` function. Produces `calc(1) = -1`, and `calc3(1,-2,1) = 0`.\n- `((x ^% -2) == 1)` in `calc` function, and `((x ^% y) == z)` in `cal3` function. Produces `calc(1) = 0`, and `calc3(1,-2,1) = -1`.\n\n## Stack underflow in `run_methodX` functions\n\nIssue Page: [#1883](https://github.com/ton-blockchain/ton/issues/1883).\n\nThe following code produces a stack underflow when `run_method3` executes:\n\n```func\n() test(int a, int b, int c) impure method_id(16384) {\n   ~dump(a);\n   ~dump(b); \n   ~dump(c);\n}\n\n() recv_internal() impure {\n      run_method3(16384, 100, 200, 300);\n}\n```\n\nThe expected behavior is that `test` function prints `100`, `200`, and `300` in the debug logs when `run_method3` executes.\n\nThe functions `run_method0`, `run_method1`, and `run_method2` have similar problems with stack underflow.\n\n## FunC does not throw on 1024 bits long slice constant creation with s literal\n\nIssue page: [#1153](https://github.com/ton-blockchain/ton/issues/1153).\n\nThe following is successfully compiled:\n\n```func\nconst slice s = \"abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd\"s;\n\n() main () {\n    ~dump(s);\n}\n```\n\nBut the compiler should have thrown a compilation error due to the string being too long.\n\n## FunC ignores argument order when calling built-ins or asm functions via variables\n\nPage issue: [#1681](https://github.com/ton-blockchain/ton/issues/1681).\n\n```func\n;; Correct: directly calls built-in, respects ret_order\n(int, int) correctBuiltin(int a, int b) {\n    return moddiv(a, b);\n}\n\n;; Incorrect: calling built-in via variable, ignores ret_order\n(int, int) incorrectBuiltin(int a, int b) {\n    var f = moddiv;\n    return f(a, b);\n}\n\n;; Define the asm function with explicit ret_order\n(int, int) myAsm(int a, int b) asm(-> 1 0) \"SWAP\";\n\n;; Correct: directly calls asm function with explicit ret_order\n(int, int) correctAsm(int a, int b) {\n    return myAsm(a, b);\n}\n\n;; Incorrect: calls asm function via variable, ignores ret_order\n(int, int) incorrectAsm(int a, int b) {\n    var f = myAsm;\n    return f(a, b);\n}\n\n() main () {\n    ~dump([correctBuiltin(5, 1)]);    ;; [0 5] Correct\n    ~dump([incorrectBuiltin(5, 1)]);  ;; [5 0] Incorrect\n    ~dump([correctAsm(5, 1)]);        ;; [5 1] Correct\n    ~dump([incorrectAsm(5, 1)]);      ;; [1 5] Incorrect\n}\n```\n\n## FunC crashes with fatal assertion when tensor exceeds 254 elements\n\nIssue Page: [1682](https://github.com/ton-blockchain/ton/issues/1682)\n\nThe compiler crashes with a fatal internal assertion if a tensor exceeds 254 elements, instead of a proper user-facing error.\n\nExample:\n\n```func\n() main() {\n    var x = (\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n    );\n}\n```\n\nwhich crashes with message:\n\n```text\nfatal: Assertion failed at analyzer.cpp:46: k <= 254 && n <= 0x7fff00\n```\n"
  },
  {
    "path": "languages/func/libraries.mdx",
    "content": "---\ntitle: \"Other FunC libraries\"\nsidebarTitle: \"Other libraries\"\nnoindex: \"true\"\n---\n\n## Standard libraries\n\n- [stdlib](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/stdlib.fc/): the FunC standard library\n- [mathlib](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/mathlib.fc/): the FunC fixed-point math library\n\n## Libraries from community\n\n- [`continuation-team/openlib.func`](https://github.com/continuation-team/openlib.func/): reduces transaction fees in common scenarios.\n- [`open-contracts/utils`](https://github.com/TonoxDeFi/open-contracts/tree/main/contracts/utils/): utility library.\n- [`open-contracts/strings`](https://github.com/TonoxDeFi/open-contracts/tree/main/contracts/strings/): provides string manipulation functions.\n- [`open-contracts/math`](https://github.com/TonoxDeFi/open-contracts/tree/main/contracts/math/): extends FunC arithmetic operations with additional math functions.\n- [`open-contracts/tuples`](https://github.com/TonoxDeFi/open-contracts/tree/main/contracts/tuples/): collection of tuple-related functions for FunC.\n- [`open-contracts/crypto`](https://github.com/TonoxDeFi/open-contracts/tree/main/contracts/crypto/): provides cryptographic operations for secp256k1 curves.\n- [`toncli/test-libs`](https://github.com/disintar/toncli/tree/master/src/toncli/lib/test-libs/): supports TL-B schema operations, including message and type parsing and generation.\n- [`ston-fi/funcbox`](https://github.com/ston-fi/funcbox/): collection of FunC snippets and utilities.\n"
  },
  {
    "path": "languages/func/literals.mdx",
    "content": "---\ntitle: \"FunC literals\"\nsidebarTitle: \"Literals\"\nnoindex: \"true\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n## Number literals\n\nFunC supports decimal and hexadecimal integer literals, including those with leading zeros:\n\n- Examples of valid integer literals: `0`, `123`, `-17`, `00987`, and `-0`. <br />\n- Examples of valid hexadecimal literals: `0xef`, `0xEF`, `0x0`, `-0xfFAb`, `0x0001`, and `-0x0`.\n\n## Identifiers\n\nFunC allows a broad range of identifiers for functions and variable names. Any single-line string that meets the following conditions qualifies as a valid identifier:\n\n- It **does not** contain special symbols: `;`, `,`, `(`, `)`, `[`, `]`, spaces including tabs, `~`, and `.`.\n- It **does not** start as a [comment](/languages/func/comments) or a [string literal](#string-literals) (i.e., with `\"` at the beginning).\n- It is **not** a [number literal](#number-literals).\n- It is **not** an underscore `_`.\n- It is **not** a [reserved keyword](/languages/func/built-ins#reserved-keywords).\n- It is **not** the name of a [built-in](/languages/func/built-ins#built-ins).\n\nAdditionally, **function** names in function definitions can start with `.` or `~`.\n\n<Aside>\n  FunC allows an exception regarding identifiers for local variables. Local variables can use the name of a [built-in with a non-symbolic name](/languages/func/built-ins#built-ins-with-non-symbolic-names).\n</Aside>\n\n**Examples of valid identifiers:**\n\n- `query`, `query'`, `query''`\n- `elem0`, `elem1`, `elem2`\n- `CHECK`\n- `_internal_value`\n- `message_found?`\n- `get_pubkeys&signatures`\n- `dict::udict_set_builder`\n- `fatal!`\n\n**Examples of less common, but still valid identifiers:**\n\n- `123validname`\n- `2+2=2*2`\n- `-alsovalidname`\n- `0xefefefhahaha`\n- `{hehehe}`\n- ``pa{--}in\"`aaa`\"``\n\n**Examples of valid function names:**\n\n- `fun_a`\n- `~fun_a?`\n- `._how123`\n\n**Examples of invalid identifiers:**\n\n- `take(first)Entry` - contains parentheses `(` and `)`\n- `\"not_a_string` - starts with a `\"`, like a string literal\n- `msg.sender` - includes a `.`\n- `send_message,then_terminate` - contains a `,`\n- `_` - just an underscore, which is not valid on its own\n- ``pa;;in\"`aaa`\"`` - contains `;`\n- `{-aaa-}` - it is a comment\n- `aa(bb` - contains an opening parenthesis\n- `123` - a number literal\n- `_+_` - it is a reserved builtin name\n\n**Special identifiers in backticks:**\n\nFunC allows identifiers enclosed in backticks `` ` ``.\n\nThese identifiers can contain any characters except:\n\n- Newline characters `\\n`\n- Backticks `` ` `` themselves, except the opening and closing ones.\n\n**Examples of valid backtick identifiers:**\n\n- `` `I'm a variable identifier too` ``\n- `` `any symbols ; ~ () are allowed here...` ``\n\n<Aside type=\"tip\">\n  Identifiers in FunC usually follow these naming conventions:\n\n  - **Apostrophe `'` at the end:** used when a variable is a modified version of its original value.\n    - Example:\n      ```func\n      cell dict' = udict_set(dict, 100, 0, v);\n      ```\n      Here, function `udict_set` updates key `0` with value `v` in dictionary `dict`. The updated dictionary name is `dict'`.\n\n  - **Question mark `?` at the end:** typically used for boolean variables or functions that return a success flag.\n    - Example:\n      ```func\n      (slice v, int found?) = udict_get?(dict, 100, 0);\n      ```\n      Here, function `udict_get?` looks up index `0` in dictionary `dict`, and returns the associated value `v` (if found) and a flag `found?` which indicates whether the index was found in the dictionary.\n</Aside>\n\n## Constants\n\nFunC allows defining **compile-time constants** that are substituted and pre-computed during compilation.\n\n**Syntax:**\n\n```func\nconst optional-type identifier = value-or-expression;\n```\n\n- `optional-type` (e.g., `int` or `slice`) is optional but improves readability and ensures type correctness.\n- `value-or-expression`can be a literal or an expression involving literals and previously defined constants.\n\nMultiple constants can be defined in the same `const` declaration by separating them with `,`.\n\n**Example usage:**\n\n```func\nconst int101 = 101;                      ;; Numeric constant\nconst str1 = \"const1\", str2 = \"aabbcc\"s; ;; Multiple string constants separated with ,\nconst int int240 = (int101 * 10) << 3;   ;; Constant computed from an expression\nconst slice str2r = str2;                ;; Constant referencing another constant\n```\n\n<Aside type=\"tip\">\n  Numeric constants are replaced during compilation, which means that all optimizations and pre-computations apply efficiently.\n</Aside>\n\n## Compile-time built-ins\n\nFunC has a special syntax for compile-time operations that compute slices and integer hashes out of ASCII strings. These compile-time operations are invoked by enclosing the ASCII string in double quotes `\"`, followed by a suffix representing the compile-time operation to apply on the string, like:\n\n```func\n\"this is a string\"u\n```\n\nwhere the suffix `u` represents the compile-time operation to invoke on the ASCII string.\n\nThese built-ins are evaluated during compilation time, which means that the FunC compiler replaces the built-in call anywhere it occurs with the result of the call. In particular, it is possible to use these compile-time built-ins while declaring constants:\n\n```\nconst c = \"some string\"s;\n```\n\nWe now describe the possible string suffixes.\n\n### String without suffix\n\nIf no suffix is provided, the compiler computes a slice from the ASCII string, such that the contents of the slice is the binary code of the ASCII string.\n\n```func\nconst c = \"hello\";     ;; c has the slice x{68656c6c6f}, where 68656c6c6f\n                       ;; is the slice contents in hexadecimal, representing\n                       ;; the ASCII code of the string.\n```\n\n### String with suffix `s`\n\nSuffix `s` interprets the string as an hexadecimal number and produces a slice having the binary representation of the hexadecimal number. If the string is not an hexadecimal number, the compiler signals an error.\n\n```func\nconst c = \"abcdef\"s;   ;; c has the slice x{abcdef}, where abcdef is the\n                       ;; slice contents in hexadecimal.\n                       ;; Note that abcdef is a valid hexadecimal number.\n```\n\n### String with suffix `a`\n\nSuffix `a` interprets the string as an address and creates a slice containing a [`MsgAddressInt` structure](/foundations/addresses/overview#internal-addresses) from the address.\n\n```func\n;; c has slice x{9FE6666666666666666666666666666666666666666666666666666666666666667_}\n;; The slice contents represent the MsgAddressInt structure:\n;; addr_std$10 anycast:none$0 workchain_id:int8=0xFF address:bits256=0x33...33\nconst c = \"Ef8zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM0vF\"a;\n```\n\n### String with suffix `u`\n\nSuffix `u` produces the decimal representation of the binary code of the ASCII string.\n\n```\nconst c = \"NstK\"u;     ;; c has the integer 1316189259\n                       ;; which is the decimal representation of the\n                       ;; ASCII code of the string\n```\n\n### String with suffix `h`\n\nSuffix `h` generates an integer from the first 32 bits of the string's SHA-256 hash.\n\n```func\nconst c = \"transfer(slice, int)\"h;  ;; c has the integer 2053302440\n```\n\n### String with suffix `H`\n\nSuffix `H` generates an integer from the full 256-bit SHA-256 hash of the string.\n\n```func\n;; c has the integer\n;; 55356924298749527416066000120313684523410504308849542670649639903159354505593\nconst c = \"transfer(slice, int)\"H\n```\n\n### String with suffix `c`\n\nSuffix `c` generates an integer from the `crc32` value of the string.\n\n```func\nconst c = \"transfer(slice, int)\"c   ;; c has the integer 2235694568\n```\n\n### String with multiple lines\n\nSpecial characters like `\\n` are not supported in strings, but you can create multi-line strings by writing the text across multiple lines, all surrounded by triple quotes `\"\"\"`. The triple quotes syntax also supports the previously described suffixes.\n\nFor example:\n\n```func\nint a = \"\"\"\n   hash me baby one more time\n   .... Oh, baby, baby\n\"\"\"h;     ;; a has value 876244482\n```\n"
  },
  {
    "path": "languages/func/operators.mdx",
    "content": "---\ntitle: \"FunC operators\"\nsidebarTitle: \"Operators\"\nnoindex: \"true\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nThis page lists all the operators in FunC in decreasing order of their precedence, with examples of usage.\n\n## Table of operators\n\n<Aside>\n  Currently, all the unary and binary operators are integer operators. Logical operators are bitwise integer operators (cf. [absence of boolean type](/languages/func/types#no-boolean-type)).\n</Aside>\n\nThe following table lists operators in order of decreasing precedence, from highest to lowest.\n\n| Brief description       | Operators                                                                                                                                                                                                                                                                         |\n| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Parentheses             | [`(` `)`](#parentheses)                                                                                                                                                                                                                                                           |\n| Unary bitwise NOT       | [`~`](#bitwise-not%2C)                                                                                                                                                                                                                                                            |\n| Multiplicative          | [`*`](#multiplication%2C) [`/`](#division%2C-%2F) [`^/`](#ceiling-division%2C-%5E%2F) [`~/`](#rounding-division%2C-%2F) [`%`](#modulo%2C-%25) [`^%`](#ceiling-modulo%2C-%5E%25) [`~%`](#rounding-modulo%2C-%25) [`/%`](#division-and-modulo%2C-%2F%25) [`&`](#bitwise-and%2C-%26) |\n| Unary integer negation  | [`-`](#negation%2C)                                                                                                                                                                                                                                                               |\n| Additive                | [`+`](#addition%2C-%2B) [`-`(integer subtraction)](#subtraction%2C) [`\\|`](#bitwise-or%2C-%7C) [`^`](#bitwise-xor%2C-%5E)                                                                                                                                                         |\n| Shifts                  | [`>>`](#shift-right%2C-%3E%3E) [`<<`](#shift-left%2C-%3C%3C) [`^>>`](#ceiling-shift-right%2C-%5E%3E%3E) [`~>>`](#rounding-shift-right%2C-%3E%3E)                                                                                                                                  |\n| Comparison and Equality | [`>`](#greater-than%2C-%3E) [`>=`](#greater-than-or-equal%2C-%3E%3D) [`<`](#less-than%2C-%3C) [`<=`](#less-than-or-equal%2C-%3C%3D) [`<=>`](#comparison%2C-%3C%3D%3E) [`==`](#equality%2C-%3D%3D) [`!=`](#inequality%2C-%3D)                                                      |\n| Ternary                 | [`?:`](#ternary%2C-%3F%3A)                                                                                                                                                                                                                                                        |\n| Assignment              | [`=`](#assignment%2C-%3D) and all [augmented assignment operators](#augmented-assignment-operators)                                                                                                                                                                               |\n\nAll [binary operators](#binary-operators) are left-associative, with the exception of:\n\n- [Assignment operators](#assignment%2C-%3D) (i.e., bottom row in the table), which are right-associative.\n- [Division-modulo operator](#division-and-modulo%2C-%2F%25) `/%`, which is neither left associative nor right associative.\n\nAlso, the [ternary operator](#ternary%2C-%3F%3A) `?:` is right-associative.\n\nFor example:\n\n- `1 - 2 + 3` parses as `(1 - 2) + 3`, producing `2` as result.\n- `a = b += c = 10` parses as `(a = (b += (c = 10)))`, producing the final values `c = 10`, `b = 11`, and `a = 11`, under the assumption that `b` had value `1` initially.\n- `0 ? a : 1 ? b : c` parses as `0 ? a : (1 ? b : c)`, producing `b` as a result.\n- `3 /% 5 /% 7` does _not_ compile, neither `(3 /% 5) /% 7` nor `3 /% (5 /% 7)`.\n\n<Aside>\n  In expressions, all operators should be separated from their arguments, otherwise the expression is interpreted as an [identifier](/languages/func/literals#identifiers).\n\n  For example:\n\n  - `- x` - Negates x.\n  - `-x` - Interpreted as a single identifier, not an operation.\n  - `x + y` - Adds `x` and `y`.\n  - `x+y` - Interpreted as a single identifier, not an operation.\n</Aside>\n\n## Precedence\n\nPrecedence is used to determine which operator should be considered in a particular situation.\nWhenever ambiguity arises, FunC prefers operators with higher precedence over those with lower precedence.\n\nFor example, consider this expression:\n\n```func\n10 - 6 * 2\n```\n\nThe expression is ambiguous because it could be parsed in two different ways:\n\n```func\n(10 - 6) * 2   ;; Evaluate first 10 - 6\n10 - (6 * 2)   ;; Evaluate first 6 * 2\n```\n\nHowever, since the multiplication operator `*` has higher precedence than the subtraction operator `-`,\nFunC will prefer to evaluate the multiplication first:\n\n```func\n10 - (6 * 2)   ;; Evaluate first 6 * 2\n```\n\n<Aside type=\"tip\">\n  Neglecting precedence rules can often lead to confusing situations with operators.\n  The correct order of operations can be ensured by wrapping every operation in parentheses,\n  since parentheses have the highest precedence of all expressions and operators.\n</Aside>\n\n## Parentheses\n\nParentheses (also called round brackets, `()`) are more punctuation symbols than actual operators,\nbut their [precedence](#precedence) is higher than the precedence of any other operator.\nUse parentheses to override the order of operations:\n\n```func\n5 * 5 - 2;    ;; 23\n5 * (5 - 2);  ;; 15\n```\n\n## Unary operators\n\nUnary here means that they are applied only to one operand of the given expression.\nAll unary operators are prefix operators, i.e., placed before the operand.\n\n### Bitwise NOT, `~`\n\nThe tilde (bitwise NOT) operator `~` inverts or flips each bit in the binary\nrepresentation of the expression, changing each `1` to `0`, and vice versa.\n\n```func\nint answer = 42;\n~ answer;     ;; -43\n~ (~ answer); ;; 42\n~ (~ 0);      ;; 0\n```\n\nThe `~` operator also behaves as expected on `-1` and `0`, which are the [emulated values](/languages/func/types#no-boolean-type) for `true` and `false`:\n\n```func\n~ 0;          ;; -1,  NOT false is true \n~ (- 1);      ;; 0,   NOT true is false\n```\n\nHence, `~` can work as [logical NOT](https://en.wikipedia.org/wiki/Negation) when computing boolean conditions:\n\n```func\n~ (1 <= 4);    ;; 0,  since 1 <= 4 returns true (-1)\n1 > 4;         ;; 0,  logically equivalent to previous\n```\n\n### Negation, `-`\n\nThe minus sign (negation) operator `-` reverses the sign of the expression.\n\n```func\nint five = 5;\n- five;         ;; -5\n- (- five);     ;; 5\n- (- 1);        ;; 1\n```\n\n## Binary operators\n\nBinary here means that they are applied to two operands of the given expression.\nAll binary operators are infix operators, i.e., placed in the middle of the two operands.\n\n### Multiplication, `*`\n\nThe asterisk (multiplication) operator `*` is used for multiplication of two values.\nGoing beyond the range of the integer type will result in an error with [exit code 4](/tvm/exit-codes#4%3A-integer-overflow): `Integer overflow`.\n\n```func\nint five = 5;\nfive * 2;         ;; 10\nfive * five;      ;; 25\n```\n\n### Division, `/`\n\nThe slash (division) operator `/` is used for integer division of two values, which truncates toward zero if the result\nis positive and away from zero if the result is negative. This is also called [rounding down](https://en.wikipedia.org/wiki/Rounding#Rounding_down)\nor rounding toward negative infinity.\n\nAn attempt to divide by zero results in an error with [exit code 4](/tvm/exit-codes#4%3A-integer-overflow): `Integer overflow`.\n\n```func\n(- 1) / 5;        ;; -1, rounding down away from 0\n(- 1) / (- 5);    ;; 0, rounding down toward zero\n1 / (- 5);        ;; -1, rounding down away from 0\n1 / 5;            ;; 0, rounding down toward 0\n6 / 5;            ;; 1, rounding down toward 0\n(- 6) / 5;        ;; -2, rounding down away from 0\n```\n\n### Ceiling division, `^/`\n\nThe caret-slash (ceiling division) operator `^/` is used for integer division of two values, which truncates away from zero if the result\nis positive and toward zero if the result is negative. This is also called [rounding up](https://en.wikipedia.org/wiki/Rounding#Rounding_up)\nor rounding toward positive infinity.\n\nAn attempt to divide by zero results in an error with [exit code 4](/tvm/exit-codes#4%3A-integer-overflow): `Integer overflow`.\n\n```func\n(- 1) ^/ 5;       ;; 0, rounding up toward 0\n(- 1) ^/ (- 5);   ;; 1, rounding up away from zero\n1 ^/ (- 5);       ;; 0, rounding up toward 0\n1 ^/ 5;           ;; 1, rounding up away from 0\n6 ^/ 5;           ;; 2, rounding up away from 0\n(- 6) ^/ 5;       ;; -1, rounding up toward 0\n```\n\n### Rounding division, `~/`\n\nThe tilde-slash (rounding division) operator `~/` is used for integer division of two values, which truncates to the nearest integer but using the following\ntie-breaking rule for half values: if the fractional part is `0.5`, it is truncated away from zero if the result is positive, and truncated toward zero\nif the result is negative. This is also called [rounding half up](https://en.wikipedia.org/wiki/Rounding#Rounding_half_up)\nor rounding half toward positive infinity.\n\nAn attempt to divide by zero results in an error with [exit code 4](/tvm/exit-codes#4%3A-integer-overflow): `Integer overflow`.\n\n```func\n(- 6) ~/ 5;      ;; -1, rounding -1.2 to nearest integer\n(- 6) ~/ (- 5);  ;; 1, rounding 1.2 to nearest integer\n8 ~/ (- 5);      ;; -2, rounding -1.6 to nearest integer\n8 ~/ 5;          ;; 2, rounding 1.6 to nearest integer\n3 ~/ 2;          ;; 2, rounding half value 1.5 away from 0\n(- 3) ~/ 2;      ;; -1, rounding half value -1.5 toward 0\n```\n\n### Modulo, `%`\n\nThe percent sign (modulo) operator `%` is used for obtaining the modulo of integer division, which is the remainder of dividing the operands with the `/` operator.\nConcretely, `a % b` is defined as `a - (b * (a / b))`, where `/` is the [division operator](#division%2C-%2F), `*` is the [multiplication operator](#multiplication%2C),\nand `-` is the [subtraction operator](#subtraction%2C).\n\nIf `b` in the expression `a % b` is `0`, the result is an error with [exit code 4](/tvm/exit-codes#4%3A-integer-overflow): `Integer overflow`.\n\n```func\n(- 6) % 5;       ;; 4, result of formula: -6 - (5 * (-6 / 5))\n(- 6) % (- 5);   ;; -1, result of formula: -6 - (-5 * (-6 / -5))\n8 % (- 5);       ;; -2, result of formula: 8 - (-5 * (8 / -5))\n8 % 5;           ;; 3, result of formula: 8 - (5 * (8 / 5))\n3 % 2;           ;; 1, result of formula: 3 - (2 * (3 / 2))\n(- 3) % 2;       ;; 1, result of formula: -3 - (2 * (-3 / 2))\n```\n\nThe result of `%` always has the same sign as the divisor (i.e., `b` is the divisor in the expression `a % b`). This means that the modulo is not the same as the\nremainder from [Euclidean division](https://en.wikipedia.org/wiki/Euclidean_division), because in Euclidean division the remainder is always non-negative,\nindependently of the sign of the divisor. The modulo `%` and the remainder from Euclidean division coincide when both operands are non-negative.\n\nIf you want to compute remainders as in Euclidean division by using the `%` operator, the best way is to use only unsigned integers.\nAlternatively, consider using the `abs` function to ensure non-negative values:\n\n```func\nabs(-3) % abs(-4)   ;; 3, same as 3 % 4\n```\n\n### Ceiling modulo, `^%`\n\nThe caret-percent sign (ceiling modulo) operator `^%` is used for obtaining the ceiling modulo of integer ceiling division, which is the remainder of dividing the\noperands with the `^/` operator.\nConcretely, `a ^% b` is defined as `a - (b * (a ^/ b))`, where `^/` is the [ceiling division operator](#ceiling-division%2C-%5E%2F),\n`*` is the [multiplication operator](#multiplication%2C), and `-` is the [subtraction operator](#subtraction%2C).\n\nIf `b` in the expression `a ^% b` is `0`, the result is an error with [exit code 4](/tvm/exit-codes#4%3A-integer-overflow): `Integer overflow`.\n\n```func\n(- 6) ^% 5;       ;; -1, result of formula: -6 - (5 * (-6 ^/ 5))\n(- 6) ^% (- 5);   ;; 4, result of formula: -6 - (-5 * (-6 ^/ -5))\n8 ^% (- 5);       ;; 3, result of formula: 8 - (-5 * (8 ^/ -5))\n8 ^% 5;           ;; -2, result of formula: 8 - (5 * (8 ^/ 5))\n3 ^% 2;           ;; -1, result of formula: 3 - (2 * (3 ^/ 2))\n(- 3) ^% 2;       ;; -1, result of formula: -3 - (2 * (-3 ^/ 2))\n```\n\nThe result of `^%` always has the opposite sign of the divisor (i.e., `b` is the divisor in the expression `a ^% b`).\n\n### Rounding modulo, `~%`\n\nThe tilde-percent sign (rounding modulo) operator `~%` is used for obtaining the rounding modulo of integer rounding division, which is the remainder of dividing the\noperands with the `~/` operator.\nConcretely, `a ~% b` is defined as `a - (b * (a ~/ b))`, where `~/` is the [rounding division operator](#rounding-division%2C-%2F),\n`*` is the [multiplication operator](#multiplication%2C),\nand `-` is the [subtraction operator](#subtraction%2C).\n\nIf `b` in the expression `a ~% b` is `0`, the result is an error with [exit code 4](/tvm/exit-codes#4%3A-integer-overflow): `Integer overflow`.\n\n```func\n(- 6) ~% 5;       ;; -1, result of formula: -6 - (5 * (-6 ~/ 5))\n(- 6) ~% (- 5);   ;; -1, result of formula: -6 - (-5 * (-6 ~/ -5))\n8 ~% (- 5);       ;; -2, result of formula: 8 - (-5 * (8 ~/ -5))\n8 ~% 5;           ;; -2, result of formula: 8 - (5 * (8 ~/ 5))\n3 ~% 2;           ;; -1, result of formula: 3 - (2 * (3 ~/ 2))\n(- 3) ~% 2;       ;; -1, result of formula: -3 - (2 * (-3 ~/ 2))\n```\n\n### Division and modulo, `/%`\n\nThe slash-percent sign (division and modulo) operator `/%` returns a two element [tensor](/languages/func/types#tensor-types), where the first element is the result\nof applying the [division operator](#division%2C-%2F) `/` on the operands,\nand the second element is the result of applying the [modulo operator](#modulo%2C-%25) on the operands.\n\nIf `b` in the expression `a /% b` is `0`, the result is an error with [exit code 4](/tvm/exit-codes#4%3A-integer-overflow): `Integer overflow`.\n\n```func\n(- 6) /% 5;       ;; (-2, 4), which is: (-6 / 5, -6 % 5)\n(- 6) /% (- 5);   ;; (1, -1), which is: (-6 / -5, -6 % -5)\n8 /% (- 5);       ;; (-2, -2), which is: (8 / -5, 8 % -5)\n8 /% 5;           ;; (1, 3), which is: (8 / 5, 8 % 5)\n3 /% 2;           ;; (1, 1), which is: (3 / 2, 3 % 2)\n(- 3) /% 2;       ;; (-2, 1), which is: (-3 / 2, -3 % 2)\n```\n\n`/%` is the only binary operator that does not associate to the right or to the left:\n\n```func\n10 /% 2 /% 3;     ;; Does NOT compile \n(10 /% 2) /% 3;   ;; Does NOT compile \n10 /% (2 /% 3);   ;; Does NOT compile \n```\n\nThe reason for this non-associativity of `/%` is that it returns a 2-element tensor. This means that you must decompose the tensor before using the values.\nSee more about decomposition notation in the [variable declaration](/languages/func/expressions#variable-declaration) section.\n\n```func\n(int x, int y) = 10 /% 2;    ;; x stores 5, y stores 0\n(int z, int w) = x /% 3;     ;; z stores 1, w stores 2\n```\n\n### Bitwise AND, `&`\n\nThe ampersand (bitwise AND) operator `&` applies a [bitwise AND](https://en.wikipedia.org/wiki/Bitwise_operation#AND),\nwhich performs the logical AND operation on each pair of corresponding bits of the operands.\nThis is useful when we want to clear selected bits of a number, where each bit represents an individual flag or a boolean state.\nThis makes it possible to “store” up to 257 boolean values per integer, as all integers in FunC are 257-bit signed.\n\n```func\n2 & 1;     ;; 0,  since 2 and 1 has no bits in common\n4 & 1;     ;; 0,  since 4 and 1 has no bits in common\n3 & 1;     ;; 1,  since 3 and 1 has in common only the lowest degree bit\n1 & 1;     ;; 1,  & is idempotent, as expected of logical AND\n```\n\nThe `&` operator also behaves as expected on `-1` and `0`, which are the [emulated values](/languages/func/types#no-boolean-type) for `true` and `false`:\n\n```func\n0 & 0;          ;; 0,   false AND false is false \n0 & (- 1);      ;; 0,   false AND true is false\n(- 1) & 0;      ;; 0,   true AND false is false\n(- 1) & (- 1);  ;; -1,  true AND true is true\n```\n\nHence, `&` can work as logical AND when computing boolean conditions:\n\n```func\n(1 <= 4) & (2 < 3);   ;; -1,  since (1 <= 4) and (2 < 3) both return -1\n```\n\n### Addition, `+`\n\nThe plus (addition) operator `+` is used for adding numbers together.\nGoing beyond the range of the integer type will result in an error with [exit code 4](/tvm/exit-codes#4%3A-integer-overflow): `Integer overflow`.\n\n```func\n2 + 2;      ;; 4\n- 1 + 1;    ;; 0\n```\n\n### Subtraction, `-`\n\nThe minus (subtraction) operator `-` is used for subtracting numbers from each other.\nGoing beyond the range of the integer type will result in an error with [exit code 4](/tvm/exit-codes#4%3A-integer-overflow): `Integer overflow`.\n\n```func\n2 - 2;    ;; 0\n- 1 - 1;  ;; -2\n```\n\n### Bitwise OR, `|`\n\nThe bar (bitwise OR) operator `|` applies a [bitwise OR](https://en.wikipedia.org/wiki/Bitwise_operation#OR), which performs the\nlogical OR operation on each pair of corresponding bits of the operands.\nThis is useful when we want to apply a specific [bitmask](https://en.wikipedia.org/wiki/Mask_\\(computing\\)).\n\n```func\n2 & 1;     ;; 3, \n4 & 1;     ;; 5, \n3 & 1;     ;; 3,  \n1 & 1;     ;; 1,  | is idempotent, as expected of logical OR\n```\n\nThe `|` operator also behaves as expected on `-1` and `0`, which are the [emulated values](/languages/func/types#no-boolean-type) for `true` and `false`:\n\n```func\n0 | 0;          ;; 0,    false OR false is false \n0 | (- 1);      ;; -1,   false OR true is true\n(- 1) | 0;      ;; -1,   true OR false is true\n(- 1) | (- 1);  ;; -1,   true OR true is true\n```\n\nHence, `|` can work as logical OR when computing boolean conditions:\n\n```func\n(1 <= 4) | (3 < 2);   ;; -1,  since (1 <= 4) returns -1\n```\n\n### Bitwise XOR, `^`\n\nThe caret (bitwise XOR) operator `^` applies a [bitwise XOR](https://en.wikipedia.org/wiki/Bitwise_operation#XOR), performing the\n[logical exclusive OR](https://en.wikipedia.org/wiki/Exclusive_or) operation on each pair of corresponding bits of the operands.\nThe result in each position is `1` if exactly one of the bits is `1`, or `0` if both bits are `0` or both bits are `1`.\nThus, it compares two bits, yielding `1` if the bits are different and `0` if they are the same.\n\nIt is useful for inverting selected bits of an operand (also called toggling or flipping), as any bit can be toggled by “XORing” it with `1`.\n\n```func\n6 ^ 2;     ;; 4, \n4 ^ 2;     ;; 6, \n3 ^ 1;     ;; 2,  \n1 ^ 1;     ;; 0,\n```\n\nThe `^` operator also behaves as expected on `-1` and `0`, which are the [emulated values](/languages/func/types#no-boolean-type) for `true` and `false`:\n\n```func\n0 ^ 0;          ;; 0,    false XOR false is false \n0 ^ (- 1);      ;; -1,   false XOR true is true\n(- 1) ^ 0;      ;; -1,   true XOR false is true\n(- 1) ^ (- 1);  ;; 0,    true XOR true is false\n```\n\n### Shift right, `>>`\n\nThe double greater than (shift right) operator `>>` returns an integer whose binary representation is the left operand value\nshifted by the right operand number of bits to the right.\nExcess bits shifted off to the right are discarded, and copies of the leftmost bit are shifted in from the left.\nThis operation is also called \"sign-propagating right shift\" or \"arithmetic right shift\" because the sign of the resulting number\nis the same as the sign of the left operand.\n\n`x >> n` is a more efficient way to divide `x` by `2^n`, where the division truncation is done by flooring.\nIn other words, `x >> n` is equivalent to `floor(x / 2^n)`, where `floor` is the [floor function](https://en.wikipedia.org/wiki/Floor_and_ceiling_functions),\n`2^n` is exponentiation of `2` by `n`, and `/` is standard [arithmetical division](https://en.wikipedia.org/wiki/Division_\\(mathematics\\)).\n\n```func\n2 >> 1;       ;; 1,  since floor(2 / 2^1) = 1\n(- 2) >> 1;   ;; -1, because >> preserves the sign of the left operand,\n              ;; or equivalently floor(-2 / 2^1) = -1       \n \n8 >> 2;       ;; 2,  since floor(8 / 2^2) = 2\n5 >> 1;       ;; 2,  since floor(5 / 2^1) = 2\n(- 14) >> 2;  ;; -4  since floor(-14 / 2^2) = -4\n```\n\n### Shift left, `<<`\n\nThe double less-than (shift left) operator `<<` returns an integer whose binary representation is the left operand value shifted to the left\nby the number of bits specified by the right operand.\nExcess bits shifted off from the left are discarded, and zero bits are shifted in from the right.\n\n`x << n` is a more efficient way to multiply `x` by `2^n`.\nIn other words, `x << n` is equivalent to `x * 2^n`, where `2^n` is exponentiation of `2` by `n` and `*` is standard arithmetical multiplication.\n\nExceeding the range of the integer type will result in an error with [exit code 4](/tvm/exit-codes#4%3A-integer-overflow): `Integer overflow`.\n\n```func\n2 << 1;   ;; 4,  since 2 * 2^1 = 4\n1 << 5;   ;; 32, since 1 * 2^5 = 32\n2 << 5;   ;; 64, since 2 * 2^5 = 64\n```\n\n### Ceiling shift right, `^>>`\n\nThe caret-double greater than (ceiling shift right) operator computes an efficient way to divide the left operand by `2^n`, where `n` is the right operand and\nthe division truncation is done by ceiling.\n\nIn other words, `x ^>> n` is equivalent to `ceil(x / 2^n)`, where `ceil` is the [ceil function](https://en.wikipedia.org/wiki/Floor_and_ceiling_functions),\n`2^n` is exponentiation of `2` by `n`, and `/` is standard [arithmetical division](https://en.wikipedia.org/wiki/Division_\\(mathematics\\)).\n\n```func\n2 ^>> 1;       ;; 1,  since ceil(2 / 2^1) = 1\n(- 2) ^>> 1;   ;; -1, since ceil(-2 / 2^1) = -1\n8 ^>> 2;       ;; 2,  since ceil(8 / 2^2) = 2\n5 ^>> 1;       ;; 3,  since ceil(5 / 2^1) = 3\n(- 14) ^>> 2;  ;; -3  since ceil(-14 / 2^2) = -3\n```\n\n### Rounding shift right, `~>>`\n\nThe tilde-double greater than (rounding shift right) operator computes an efficient way to divide the left operand by `2^n`, where `n` is the right operand and\nthe division truncation is done by [rounding half up](https://en.wikipedia.org/wiki/Rounding#Rounding_half_up).\nIn other words, `x ~>> n` is equivalent to `floor(x / 2^n + 0.5)`, where `floor` is the [floor function](https://en.wikipedia.org/wiki/Floor_and_ceiling_functions),\n`2^n` is exponentiation of `2` by `n`, `/` is standard [arithmetical division](https://en.wikipedia.org/wiki/Division_\\(mathematics\\)), and `+` is standard arithmetical addition.\n\n```func\n15 ~>> 3;       ;; 2,  since floor(15 / 2^3 + 0.5) = 2\n12 ~>> 3;       ;; 2,  since floor(12 / 2^3 + 0.5) = 2\n11 ~>> 3;       ;; 1,  since floor(11 / 2^3 + 0.5) = 1\n(- 14) ~>> 3;   ;; -2, since floor(-14 / 2^3 + 0.5) = -2\n(- 12) ~>> 3;   ;; -1  since floor(-12 / 2^3 + 0.5) = -1\n```\n\n### Greater than, `>`\n\nThe greater than operator `>` returns `-1` if the left operand is greater than the right operand and `0` otherwise.\n\n```func\n2 > 2;          ;; 0\n(- 1) > (- 3);  ;; -1\n```\n\n### Greater than or equal, `>=`\n\nThe greater than or equal to operator `>=` returns `-1` if the left operand is greater than or equal to the right operand and `0` otherwise.\n\n```func\n2 >= 2;           ;; -1\n(- 3) >= (- 1);   ;; 0\n```\n\n### Less than, `<`\n\nThe less than operator `<` returns `-1` if the left operand is less than the right operand and `0` otherwise.\n\n```func\n2 < 2;           ;; 0\n(- 3) < (- 1);   ;; -1\n```\n\n### Less than or equal, `<=`\n\nThe less than or equal to operator `<=` returns `-1` if the left operand is less than or equal to the right operand and `0` otherwise.\n\n```func\n2 <= 2;           ;; -1\n(- 1) <= (- 3);   ;; 0\n```\n\n### Comparison, `<=>`\n\nThe less than or equal or greater than (comparison) operator `<=>`, returns `-1` if the left operand is less than the right operand,\n`0` if the left and right operands are equal, or `1` if the left operand is greater than the right operand.\n\n```func\n1 <=> 2;           ;; -1\n(- 2) <=> (- 2);   ;; 0\n2 <=> (- 1)        ;; 1\n```\n\n### Equality, `==`\n\nThe equality operator `==` checks whether its two operands are equal, returning `-1` if they are and `0` otherwise.\nThe `==` can only compare integers.\n\n```func\n1 == 2;           ;; 0\n(- 2) == (- 2);   ;; -1\n```\n\n### Inequality, `!=`\n\nThe inequality operator `!=` checks whether its two operands are different, returning `-1` if they are and `0` otherwise.\nThe `!=` can only compare integers.\n\n```func\n1 != 2;           ;; -1\n(- 2) != (- 2);   ;; 0\n```\n\n### Ternary, `?:`\n\nThe conditional (ternary) operator `?:` is the only operator that takes three operands: a condition followed by a question mark\n(`?`), then an [expression](/languages/func/expressions) to execute (the \"consequent\" expression) if the condition evaluates to an integer different from `0`, followed by a colon (`:`),\nand finally the expression to execute (the \"alternative\" expression) if the condition evaluates to `0`.\nThis operator is frequently used as an alternative to an `if...else` statement.\n\n```\n<condition> ? <consequent expression> : <alternative expression>\n```\n\nBoth the consequent and alternative expressions must have the same type. The condition must have the type integer.\n\n```func\n2 ? 3 : 4;      ;; 3, since the condition evaluates to an integer different from 0\n0 ? 3 : 4;      ;; 4, since the condition evaluates to 0\n1 < 2 ? 3 : 4;  ;; 3, since the condition evaluates to -1\n1 != 4 ? begin_cell() : 5;   ;; DOES NOT COMPILE: consequent and alternative do not have the same type\n```\n\n### Assignment, `=`\n\nThe assignment operator `=` is used to assign the result of an [expression](/languages/func/expressions) to a variable. After execution, the `=` operator returns the value assigned to the variable.\n\n```func\na = 5;       ;; Assigns 5 to variable a, and returns 5\nb = 5 + a;   ;; Assigns 10 to variable b, and returns 10\n```\n\nSince the assignment operator returns the assigned value, it can be used in expressions:\n\n```func\n(a = 5) + 10;   ;; Assign 5 to a, and the expression evaluates to 15\n(a = 5) + a;    ;; Assigns 5 to a, and the expression evaluates to 10,\n                ;; since a = 5 evaluates to 5, and 5 + a is 10.\n```\n\nThe operator `=` is right associative:\n\n```func\n(b = a = 5) + b;   ;; Parses as (b = (a = 5)) + b.\n                   ;; So, it does the following:\n                   ;; (1) a = 5 assigns 5 to a, and returns 5. \n                   ;; (2) b = (a = 5) assigns 5 to b, and returns 5.\n                   ;; (3) (b = (a = 5)) + b, evaluates to 10, since b has value 5.\n                   ;; From here onwards, a and b have value 5.\n```\n\nThe assignment operator can also occur in [variable declarations](/languages/func/expressions#variable-declaration), which are also expressions:\n\n```func\nint x = 5;        ;; Declares integer variable x with value 5, and returns 5.\na = (int y = 5);  ;; Declares integer variable y with value 5, then assigns 5 to a, and returns 5.\n                  ;; From here onwards, a has value 5 and y is also available with value 5.\n(int z = 5) + z;  ;; Declares integer variable z with value 5, and the expression evaluates to 10,\n                  ;; since after the declaration, z has value 5.\n                  ;; From here onwards, z is available with value 5.\n```\n\n### Augmented assignment operators\n\nAugmented (or compound) assignment operators such as `+=` combine an operation with an assignment.\nAugmented assignments are semantically equivalent to regular assignments `=` but include an operation:\n\n```func\na += 5;  \n;; is equivalent to:\na = a + 5;\n```\n\nAfter execution, the augmented operator returns the final value assigned to the variable:\n\n```func\nint a = 0; int b = 2;\na += 4;         ;; returns 4 and assigns 4 to a,  equivalent to a = a + 4.\nb *= 10;        ;; returns 20 and assigns 20 to b, equivalent to b = b * 10.\n(b /= 2) + 1;   ;; returns 11 and assigns 10 to b, equivalent to (b = b / 2) + 1.\n```\n\nList of augmented assignment operators:\n\n- `*=`, which uses the [multiplication operator](#multiplication%2C) `*`.\n- `/=`, which uses the [division operator](#division%2C-%2F) `/`.\n- `^/=`, which uses the [ceiling division operator](#ceiling-division%2C-%5E%2F) `^/`.\n- `~/=`, which uses the [rounding division operator](#rounding-division%2C-%2F) `~/`.\n- `%=`, which uses the [modulo operator](#modulo%2C-%25) `%`.\n- `^%=`, which uses the [ceiling modulo operator](#ceiling-modulo%2C-%5E%25) `^%`.\n- `~%=`, which uses the [rounding modulo operator](#rounding-modulo%2C-%25) `~%`.\n- `&=`, which uses the [bitwise AND operator](#bitwise-and%2C-%26) `&`.\n- `+=`, which uses the [addition operator](#addition%2C-%2B) `+`.\n- `-=`, which uses the [subtraction operator](#subtraction%2C) `-`.\n- `|=`, which uses the [bitwise OR operator](#bitwise-or%2C-%7C) `|`.\n- `^=`, which uses the [bitwise XOR operator](#bitwise-xor%2C-%5E) `^`.\n- `>>=`, which uses the [shift right operator](#shift-right%2C-%3E%3E) `>>`.\n- `<<=`, which uses the [shift left operator](#shift-left%2C-%3C%3C) `<<`.\n- `^>>=`, which uses the [ceiling shift right operator](#ceiling-shift-right%2C-%5E%3E%3E) `^>>`.\n- `~>>=`, which uses the [rounding shift right operator](#rounding-shift-right%2C-%3E%3E) `~>>`.\n"
  },
  {
    "path": "languages/func/overview.mdx",
    "content": "---\ntitle: \"FunC language overview\"\nsidebarTitle: \"Overview\"\nnoindex: \"true\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside>\n  TON Blockchain uses [Tolk](/languages/tolk) as the official language. Other languages are still available, and legacy codebases exist, but Tolk is the only actively supported language. The FunC compiler, for instance, is no longer maintained.\n</Aside>\n\nFunC is a domain-specific, statically typed language with C-like syntax designed to write smart contracts on TON. It can be characterized as an intermediate-level language sitting on top of the [Fift](/languages/fift) assembly language.\n\nExample of a FunC function for sending funds:\n\n```func\n() send_money(slice address, int amount) impure inline {\n    var msg = begin_cell()\n        ;; Set the message to be non-bounceable\n        .store_uint(0x10, 6)\n        .store_slice(address)\n        .store_coins(amount)\n        .end_cell();\n\n    send_raw_message(msg, 64);\n}\n```\n\nwhere\n\n- [`()`](/languages/func/types#tensor-types) is the return type, that stands for \"do not return value\", similar to `void` in C;\n- `send_money` is the name of the function;\n- `slice address` is the first parameter, address to send money to; it's type is [`slice`](/languages/func/types#atomic-types);\n- `int amount` is the second parameter, amount to be sent; it's type is [`int`](/languages/func/types#atomic-types);\n- `impure inline` are [specifiers](/languages/func/functions#specifiers), which are flags that tell the compiler to process the method in a specific way;\n- `var msg = ...` defines a variable without specifying its type; it will hold a [cell](/foundations/serialization/cells) with a [message](/foundations/messages/overview);\n- [`begin_cell()`](/languages/func/stdlib#begin-cell) creates a [cell builder](/tvm/builders-and-slices);\n- [`store_uint`](/languages/func/stdlib#store-uint), [`store_slice`](/languages/func/stdlib#store-slice), [`store_coins`](/languages/func/stdlib#store-coins) methods store data into the builder:\n  - [flags](/foundations/messages/internal);\n  - receiving address;\n  - amount on Toncoin to attach to the message.\n- [`.end_cell()`](/languages/func/stdlib#end-cell) method finalizes the builder and turns it into a cell;\n- [`send_raw_message`](/languages/func/stdlib#send-raw-message) function sends the message, where the parameter `64` describes a [sending mode](/foundations/messages/internal).\n\n## Compiler\n\nThe compiler converts FunC programs into [Fift](/languages/fift) assembly code. The Fift assembly code is then compiled down to the [TON Virtual Machine](/tvm/overview) bitcode by the [Fift](/languages/fift) compiler.\n\nDevelopers can use the compiled bitcode, structured as a [bag of cells](/foundations/serialization/boc) like all data in the TON blockchain, to test smart contracts, send messages, or execute it in a local TVM instance.\n\n### End-to-end tooling\n\nThe easiest way to install the FunC compiler is the [`@ton-community/func-js`](https://www.npmjs.com/package/@ton-community/func-js) NPM package. It requires [Node.js](https://nodejs.org/en/download) v22 or later.\n\nThe package has both the FunC and [Fift](/languages/fift) compilers, and produces bitcode directly from the FunC source code, without manually invoking Fift.\n\nTo install it, run the following command in the project root folder:\n\n```bash\nnpm i @ton-community/func-js\n```\n\nThen, to compile a specific FunC file, run the following command:\n\n```bash\nnpx func-js ./contract.fc --boc ./output.boc\n```\n\nwhere `contract.fc` is the FunC source file in the project root, and `output.boc` is the compiled bitcode output.\n\nFunC standard library is supplied separately from the language. Download `smartcont_lib.zip` from the [latest release](https://github.com/ton-blockchain/ton/releases), extract it, and copy `stdlib.fc` to the project root.\n\nAlternatively, use the [Blueprint](/contract-dev/blueprint/overview) to start a project pre-configured for development in FunC.\n\n### Compile manually using the binaries\n\nPrebuilt FunC compiler binaries for Windows, macOS (Intel or ARM64), and Ubuntu are available on the [GitHub](https://github.com/ton-blockchain/ton/releases).\n\n1. Download the corresponding binary for operating system:\n\n   - Linux: `func-linux-x86_64` (Intel/AMD) and `func-linux-arm64` (ARM64)\n   - Mac: `func-mac-x86-64` (Intel/AMD) and `func-mac-arm64` (ARM64)\n   - Windows: `func.exe`\n\n   Rename the executable, for example, to `func`, for easier use on the command line, and add it to system's `PATH`.\n\n1. Download the FunC standard library.\n\n   Get the `smartcont_lib.zip` from the same [GitHub](https://github.com/ton-blockchain/ton/releases/tag/v2025.07), extract it, and copy `stdlib.fc` to project root.\n\n1. Compile a FunC file to Fift assembly code.\n\n   Run the following command in the project root:\n\n```bash\nfunc contract.fc -o output.fif\n```\n\nwhere `contract.fc` is the FunC file to compile, and `output.fif` is the generated Fift output.\n\nTo compile the generated Fift file `output.fif` further down to TVM bitcode, use the Fift compiler. See the [Fift](/languages/fift) for download and usage instructions.\n\n<Aside>\n  The last FunC compiler version is v2025.07. The FunC compiler is no longer developed. New releases are focused on the [Tolk](https://github.com/ton-blockchain/ton/releases/latest) compiler.\n</Aside>\n\n## Tutorials\n\n<Aside>\n  The tutorials in this section are provided by external contributors and may not reflect FunC's current development status. They are offered as additional resources for exploring FunC's applications.\n</Aside>\n\n- [Challenge 1: Simple NFT deploy](https://github.com/romanovichim/TONQuest1/)\n- [Challenge 2: Chatbot contract](https://github.com/romanovichim/TONQuest2/)\n- [Challenge 3: Jetton vending machine](https://github.com/romanovichim/TONQuest3/)\n- [Challenge 4: Lottery/raffle](https://github.com/romanovichim/TONQuest4/)\n- [Challenge 5: Create UI to interact with the contract in 5 minutes](https://github.com/romanovichim/TONQuest5/)\n- [Challenge 6: Analyzing NFT sales on the Getgems marketplace](https://github.com/romanovichim/TONQuest6/)\n- [TON hello world Part 2: guide for writing your first smart contract](https://ton-community.github.io/tutorials/02-contract/)\n- [TON hello world Part 4: guide for testing your first smart contract](https://ton-community.github.io/tutorials/04-testing/)\n- [10 lessons for developing contracts in FunC](https://github.com/romanovichim/TonFunClessons_Eng/) — [Russian version](https://github.com/romanovichim/TonFunClessons_ru/)\n- [FunC quiz](https://t.me/toncontests/60/) — a short Telegram quiz focused on FunC, with a few general TON questions.\n\n## Contests\n\n| Contest           | Tasks                                                     | Solutions                                                                                                                                                           |\n| :---------------- | :-------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| TSC #5 (Dec 2023) | [Tasks](https://github.com/ton-community/tsc5/)           | —                                                                                                                                                                   |\n| TSC #4 (Sep 2023) | [Tasks](https://github.com/ton-community/tsc4/)           | [1](https://github.com/aSpite/tsc4-contracts) [2](https://github.com/ProgramCrafter/tsc4) [3](https://github.com/Gusarich/tsc4) [4](https://github.com/akifoq/tsc4) |\n| TSC #3 (Dec 2022) | [Tasks](https://github.com/ton-blockchain/func-contest3/) | [Solutions](https://github.com/nns2009/TON-FunC-contest-3/)                                                                                                         |\n| TSC #2 (Jul 2022) | [Tasks](https://github.com/ton-blockchain/func-contest2/) | [Solutions](https://github.com/ton-blockchain/func-contest2-solutions/)                                                                                             |\n| TSC #1 (Mar 2022) | [Tasks](https://github.com/ton-blockchain/func-contest1/) | [Solutions](https://github.com/ton-blockchain/func-contest1-solutions/)                                                                                             |\n\n## Changelog\n\n[History of FunC](/languages/func/changelog)\n"
  },
  {
    "path": "languages/func/special-functions.mdx",
    "content": "---\ntitle: \"Reserved functions\"\nsidebarTitle: \"Reserved functions\"\nnoindex: \"true\"\n---\n\nFunC, or more specifically, the Fift assembler, reserves several function names with predefined [IDs](/languages/func/functions#method-id-specifier):\n\n- [`recv_internal`](#receive-internal) and [`main`](#main) have `id = 0`\n- [`recv_external`](#receive-external) has `id = -1`\n- [`run_ticktock`](#run-ticktock) has `id = -2`\n- [`split_prepare`](#split-prepare) has `id = -3`\n- [`split_install`](#split-install) has `id = -4`\n\nEvery program must include a function with `id = 0`, meaning it must define either `recv_internal` or `main`, but **not** both.\n\n#### Receive internal\n\nThe `recv_internal` function is invoked when a smart contract receives an inbound [internal message](/foundations/messages/internal).\n\nAny of the following `recv_internal` declarations can be used:\n\n```func\n() recv_internal(int balance, int msg_value, cell in_msg_cell, slice in_msg_body)\n() recv_internal(int msg_value, cell in_msg_cell, slice in_msg_body)\n() recv_internal(cell in_msg_cell, slice in_msg_body)\n() recv_internal(slice in_msg_body)\n() recv_internal()\n```\n\nThere,\n\n- `balance` is the smart contract balance in nanotons after adding the amount `msg_value` in the inbound message. It is an integer.\n- `msg_value` is the amount in nanotons included in the inbound message. It is an integer.\n- `in_msg_cell` is the inbound message, given as a cell.\n- `in_msg_body` is the inbound message body, equal to the body field in `in_msg_cell`. The body is given as a cell slice.\n\n<Aside>\n  Each time a contract receives a message, the [TVM initializes](/tvm/initialization) and pushes into the stack the following four pieces of data, in this order:\n\n  - The balance of the contract.\n  - The coins included in the inbound message.\n  - The message itself as a cell.\n  - The message body as a slice.\n\n  This means that the message body slice is the value at the top of the stack, since it was pushed last.\n\n  At the moment `recv_internal` executes, its arguments are assigned values from the stack as follows:\n\n  ```func\n  () recv_internal(arg_1, arg_2, ....., arg_n-1, arg_n)\n  ;;                 |       |            |        |\n  ;;                 |       |            |        value at the top of the stack\n  ;;                 |       |            |\n  ;;                 |       |            second value from the top of the stack\n  ;;                 |       |\n  ;;                 |       (n-1)-th value from the top of the stack\n  ;;                 |\n  ;;                 n-th value from the top of the stack\n  ```\n\n  This means that if, for example, you use the declaration:\n\n  ```func\n  () recv_internal(cell in_msg_cell, slice in_msg_body)\n  ```\n\n  `in_msg_body` will get assigned the value at the top of the stack (which corresponds to the message body slice), and `in_msg_cell` will receive the second value from the top of the stack (which corresponds to the message as a cell). The rest of values in the stack remain unassigned to variables during the execution of `recv_internal`, meaning that they will remain unused in the stack and will be dropped once the TVM finishes execution.\n\n  The declarations of `recv_internal` with fewer arguments consume slightly less gas, because each unused value in the stack is automatically dropped from the stack once `recv_internal` finishes execution, without the need to spend gas by explicitly executing a DROP instruction, which is an alias of [`s0 POP`](/tvm/instructions#3-pop).\n</Aside>\n\n<Aside\n  type=\"danger\"\n>\n  The FunC compiler does not check if the `recv_internal` arguments will actually match the values in the stack. For example, the following declaration will compile, but leads to errors during contract execution, because variable `in_msg_body` will not hold a slice, but the contract's balance, which is an integer!\n\n  ```func\n  () recv_internal(slice in_msg_body, int msg_value, cell in_msg_cell, int balance)\n  ```\n\n  Be careful of accidentally permuting the arguments in `recv_internal`. Only use the five possible declarations listed previously for `recv_internal`.\n</Aside>\n\n#### Main\n\n`main` is an alias for [`recv_internal`](#receive-internal).\n\nIf the intention of the code is to handle inbound internal messages, it is preferable to use `recv_internal` over `main`, since `recv_internal` states more clearly the intention of the code.\n\n#### Receive external\n\nThe `recv_external` function handles inbound [external messages](/foundations/messages/external-in). It allows declarations similar to those for [`recv_internal`](#receive-internal):\n\n```func\n() recv_external(int balance, int msg_value, cell in_msg_cell, slice in_msg_body)\n() recv_external(int msg_value, cell in_msg_cell, slice in_msg_body)\n() recv_external(cell in_msg_cell, slice in_msg_body)\n() recv_external(slice in_msg_body)\n() recv_external()\n```\n\nThe only difference is that `msg_value` is always `0`, since external messages cannot carry coins, as they are created outside the blockchain.\n\nThe behavior of the stack is identical to the behavior described for [`recv_internal`](#receive-internal).\n\n#### Run ticktock\n\nThe `run_ticktock` triggers at inbound tick and tock messages. It allows the following possible declarations:\n\n```func\n() run_ticktock(int balance, int address, int is_tock)\n() run_ticktock(int address, int is_tock)\n() run_ticktock(int is_tock)\n() run_ticktock()\n```\n\nThere:\n\n- `balance` is the smart contract balance in nanotons. It is an integer.\n- `address` is the address of the current account inside the masterchain. It is an unsigned 256-bit integer.\n- `is_tock` a flag that indicates if it is a tock message (`-1`) or a tick message (`0`).\n\nThe behavior of the stack is identical to the behavior described for [`recv_internal`](#receive-internal).\n\n### Split prepare\n\nThe `split_prepare` triggers for inbound split prepare messages. Even though the `split_prepare` name is currently reserved, split prepare messages are currently not in use.\n\n### Split install\n\nThe `split_install` triggers for inbound split install messages. Even though the `split_install` name is currently reserved, split install messages are currently unavailable.\n"
  },
  {
    "path": "languages/func/statements.mdx",
    "content": "---\ntitle: \"FunC statements\"\nsidebarTitle: \"Statements\"\nnoindex: \"true\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nFunC statements can occur anywhere inside function bodies.\n\n## Expression statements\n\nThe most common type of statement is the expression statement—an expression followed by `;`.\n\nSee the [FunC expressions](/languages/func/expressions) article for details on the allowed expressions.\n\n## `return` statement\n\nThe `return` statement ends function execution and specifies a value to be returned to the function caller. Any statement after the `return` statement is not executed.\n\nIn this example, the `return` statement instructs the function to halt execution and produce `x + 1` as a result.\n\n```func\nint inc(int x) {\n  return x + 1;\n}\n```\n\nIn this example, only the first `return` executes:\n\n```func\nint inc(int x) {\n  return x + 1;\n  return x;\n}\n```\n\n## Block statement\n\nA block statement is used to group zero or more statements. The block is delimited by a pair of curly braces `{ ... }`. A block statement also defines a scope, in which variables defined in the block are accessible only in the block or in nested blocks.\n\nFor example:\n\n```func\nint x = 1;\nint y = 2;\n{ ;; x and y are accessible in this block.\n  int z = x + y;\n  {\n    ;; x, y, and z are accessible in this block.\n    int w = z;    ;; The block declares w,\n                  ;; which is only accessible in this block.\n  }\n  ;; w is no longer accessible here.\n  ;; x, y, and z are still accessible here.\n}\n;; z is no longer accessible here, but x and y are.\n```\n\n## Conditional statements\n\nThese statements control the flow of the code based on a condition.\n\n### `if...else` statement\n\nWhen executing an `if...else` statement, first, the specified condition is evaluated.\n\nIf the condition evaluates to an integer different from `0`, see [absence of boolean type](/languages/func/types#no-boolean-type), the block after the condition is executed. Otherwise, if the condition evaluates to `0`, the optional `else` block is executed.\n\nIf the `else` block is missing, nothing happens, and execution continues further.\n\nExamples:\n\n```func\n;; The condition evaluates to -1, so the block executes\nif (1 < 10) {\n  do_something();\n}\n```\n\n```func\n;; The condition evaluates to 0, so the block does not execute\nif (11 < 10) {\n  do_something();\n}\n;; No else is provided. So, execution continues here, after the block.\n```\n\n```func\n;; The condition evaluates to 0, so the block does not execute\nif (11 < 10) {\n  do_something();\n} else {         ;; else is provided. So, the else block executes.\n  handle_else();\n}\n```\n\nCurly brackets `{}` are required in each block of an `if...else` statement.\n\nFor example, the following code will not compile:\n\n```func\nif (1 < 10) {\n  do_something();\n} else if (2 > 1) {   ;; else block must have curly brackets\n  do_something2();\n}\n```\n\nThat is because the `else` block must have curly brackets:\n\n```func\nif (1 < 10) {\n  do_something();\n} else {    ;; else block now has curly brackets\n  if (2 > 1) {\n    do_something2();\n  }\n}\n```\n\nThe above example can be written in a simpler form by using the `elseif` keyword, to avoid the need to write several nested curly brackets in the `else` case:\n\n```func\nif (1 < 10) {\n  do_something();\n} elseif (2 > 1) {\n  do_something2();\n}\n```\n\nIn general, the `elseif` keyword is useful for stating several alternative cases:\n\n```func\nif (cond) {\n  do_1();\n} elseif (cond2) {\n  do_2();\n} elseif (cond23) {\n  do_3();\n} else {\n  do_4();\n}\n```\n\nThe alternative cases can also include the `elseifnot` keyword, which allows the inclusion of [`ifnot` statements](#ifnot%E2%80%A6else-statement) in the alternatives:\n\n```func\nif (cond) {\n  do_1();\n} elseif (cond2) {  ;; if in else case\n  do_2();\n} elseifnot (cond23) {  ;; ifnot in else case\n  do_3();\n} else {\n  do_4();\n}\n```\n\n### `ifnot...else` statement\n\nThe `ifnot...else` statement is equivalent to the [`if...else` statement](#if%E2%80%A6else-statement) but with the condition negated using the [bitwise `~` operator](/languages/func/operators#bitwise-not%2C).\n\nMore specifically:\n\n```func\nifnot (cond) {\n  do_something();\n} else {\n  handle_else();\n}\n```\n\nis equivalent to:\n\n```func\nif (~ cond) {  ;; Standard if..else, with condition negated using ~\n  do_something();\n} else {\n  handle_else();\n}\n```\n\nIn other words, if the condition in the `ifnot` evaluates to `0`, see [absence of boolean type](/languages/func/types#no-boolean-type), the block after the condition is executed. Otherwise, if the condition evaluates to an integer different from `0`, the optional `else` block is executed.\n\nIf the `else` block is missing, nothing happens, and execution continues further.\n\nExamples:\n\n```func\nifnot (1 > 10) {   ;; The condition evaluates to 0, the block executes\n  do_something();\n}\n```\n\n```func\nifnot (11 > 10) {   ;; The condition evaluates to -1, the block does not execute\n  do_something();\n}\n;; No else is provided. Execution continues here, after the block.\n```\n\n```func\nifnot (11 > 10) {   ;; The condition evaluates to -1, the block does not execute\n  do_something();\n} else {         ;; else is provided. The else block executes.\n  handle_else();\n}\n```\n\nSimilarly to the `if...else`, it is possible to use the keyword `elseifnot` to add several alternative cases:\n\n```func\nifnot (cond) {\n  do_1();\n} elseifnot (cond2) {\n  do_2();\n} elseifnot (cond23) {\n  do_3();\n} else {\n  do_4();\n}\n```\n\nThe alternative cases can also include the `elseif` keyword, which allows the inclusion of standard [`if` statements](#if%E2%80%A6else-statement) in the alternatives:\n\n```func\nifnot (cond) {      ;; ifnot\n  do_1();\n} elseif (cond2) {  ;; if in else case\n  do_2();\n} elseifnot (cond23) {  ;; ifnot in else case\n  do_3();\n} else {\n  do_4();\n}\n```\n\n## Loops\n\nFunC supports `repeat`, `while`, and `do { ... } until` loops. The `for` loop is not supported.\n\n### `repeat` loop\n\nThe `repeat` loop executes a block of code a specified number of times. The number of repetitions should be given as a positive 32-bit integer in the inclusive range from `1` to `2^31 - 1`, i.e., `2,147,483,647`. If the value is greater, an error with [exit code 5](/tvm/exit-codes#5%3A-integer-out-of-expected-range), `Integer out of expected range`, will be thrown.\n\n```func\nint x = 1;\nrepeat(10) { ;; Repeats the block 10 times.\n  x *= 2;    ;; Each iteration multiplies x by 2.\n}\n;; x has value 1024\n```\n\n```func\nint x = 1;\nint y = 10;\nrepeat(y + 6) {  ;; Repeats the block 16 times.\n  x *= 2;        ;; Each iteration multiplies x by 2.\n}\n;; x has value 65536\n```\n\nIf the specified number of repetitions is equal to `0` or any negative number in the inclusive range from `-2^256` to `-1`, it is ignored, and the code block is not executed at all.\n\n```func\nint x = 1;\nrepeat(-1) {  ;; Block does not execute.\n  x *= 2;\n}\n;; x has value 1\n```\n\n### `while` loop\n\nThe `while` loop continues executing the block of code as long as the given condition evaluates to an integer different from `0`, see [absence of boolean type](/languages/func/types#no-boolean-type).\n\n```func\nint x = 5;\nwhile (x < 10) {  ;; Executes the block 5 times.\n                  ;; Each iteration increases x by 1.\n                  ;; The loop stops when x becomes 10.\n  x += 1;\n}\n;; x has value 10\n```\n\n### `do...until` loop\n\nThe `do...until` loop is a post-test loop that executes the block of code at least once and then continues to execute it until the given condition evaluates to an integer different from `0`, see [absence of boolean type](/languages/func/types#no-boolean-type).\n\n```func\nint x = 0;\ndo {      ;; The block always executes at least once\n  x += 3;\n} until (x % 9 == 0);  ;; Executes the block 3 times.\n                       ;; Each iteration increases x by 3.\n                       ;; The loop stops when x becomes divisible by 9.\n;; x has value 9\n```\n\n## `try...catch` statement\n\n_Available in FunC since v0.4.0_\n\nThe `try...catch` statement consists of a `try` block and a `catch` block. The code in the `try` block is executed first, and if it fails, all changes made within the `try` block are rolled back, and the `catch` block is executed instead.\n\nThe `catch` block has two arguments, which are local to the `catch` block:\n\n- The exception parameter, which can be of any type. Used to provide extra information about the error.\n- The error code, an integer, which identifies the kind of error.\n\n```func\ntry {\n  do_something();\n} catch (x, n) {\n  ;; x is the exception parameter\n  ;; n is the error code\n  handle_exception();\n}\n```\n\nUnlike many other languages, in FunC, all changes are **undone** if an error occurs inside the `try` block. These modifications include updates to local and global variables and changes to [control registers](/foundations/whitepapers/tvm#1-3-2-list-of-control-registers). For example, `c4` for storage, `c5`for action/messages, `c7` for context, etc.\n\nAny contract storage updates and outgoing messages are also reverted.\n\nHowever, certain [TVM state components](/foundations/whitepapers/tvm#1-4-total-state-of-tvm-scccg) are **not** rolled back, such as:\n\n- Codepage settings\n- Gas counters\n\nAs a result, all gas consumed within the `try` block is still accounted for, and any modifications carried out by operations that change gas limits (e.g., [`accept_message`](/languages/func/stdlib#accept-message) or [`set_gas_limit`](/languages/func/stdlib#set-gas-limit)) will remain in effect.\n\nIn this example:\n\n```func\nint x = 0;\ntry {\n  x += 1;     ;; x now has value 1\n  throw(100);\n} catch (arg, e) {\n  ;; x is rolled back to value 0.\n  x += 2;\n}\n;; Here, x has value 2.\n```\n\nalthough `x` is incremented to `1` inside the `try` block, the modification is **rolled back** due to the exception produced by the [`throw`](/languages/func/built-ins#throw) function. Hence, `x` has value `0` at the moment the `catch` block starts execution. However, the gas consumed inside the `try` block is **not** rolled back when the `catch` block starts execution.\n\nHere is an example which illustrates how to generate and use the exception parameter:\n\n```func\nint x = 10;\ntry {\n  throw_arg(-1, 100);    ;; throw an exception with error code 100\n                         ;; and exception parameter -1\n} catch (arg, e) {\n  if (e == 100) {        ;; Handle exceptions with error code 100\n     arg.cast_to_int();  ;; Tell the type checker that the\n                         ;; exception parameter is an integer\n                         ;; arg = -1, e = 100\n     x = arg + 1;\n  }\n}\n;; x has value 0\n```\n\nIn the above example, [`throw_arg(-1, 100)`](/languages/func/built-ins#throw-arg) produces an exception with error code `100` and exception parameter `-1`. However, since the exception parameter can be of any type, which may vary depending on the exception, FunC cannot determine its type at compile time in the `catch` block.\n\nThis requires the developer to manually cast the exception parameter. In the example, casting of the exception parameter is achieved with the [assembler](/languages/func/functions#assembler-function-body-definition) and [polymorphic](/languages/func/functions#polymorphism-with-forall) function `cast_to_int`, which receives an argument of any type and returns the same argument as an integer by wrapping the [`NOP` (no operation) TVM instruction](/tvm/instructions#00-nop):\n\n```func\nforall X -> int cast_to_int(X x) asm \"NOP\";\n```\n"
  },
  {
    "path": "languages/func/stdlib.mdx",
    "content": "---\ntitle: \"Standard library of FunC\"\nsidebarTitle: \"Standard library\"\nnoindex: \"true\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside>\n  This section covers the [stdlib.fc](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/stdlib.fc) library, which provides standard functions for FunC.\n</Aside>\n\nThe FunC standard library serves as a wrapper around the most commonly used TVM assembly commands that aren’t built-in.\nFor detailed descriptions of these commands, refer to the [TVM documentation](/tvm).\nSome explanations in this document adapted from there.\n\nSome functions in the library are commented out, meaning they have already been optimized and integrated as built-in operations.\nHowever, their type signatures and behaviors remain unchanged.\n\nAdditionally, some less frequently used TVM commands are not yet included in the standard library. These may be added in future updates.\n\n## Tuple manipulation primitives\n\nMost function names and types in this section are self-explanatory.\nFor more details on polymorphic functions, refer to the [Polymorphism with forall](/languages/func/functions#polymorphism-with-forall) section.\n\n**Note:** Currently, values of atomic type `tuple` cannot be converted into composite tuple types (e.g.,`[int, cell]`) and vice versa.\n\n### Lisp-style lists\n\nLists can be represented as nested 2-element tuples. Empty list is conventionally represented as TVM `null` value (it can be obtained by calling `null()`). For example, the tuple `(1, (2, (3, null)))` represents the list `[1, 2, 3]`. Elements of a list can be of different types.\n\nLists in FunC are represented as nested two-element tuples. An empty list is conventionally represented by the TVM `null` value, which can be obtained using `null()`.\nFor example, the tuple `(1, (2, (3, null)))` corresponds to the list `[1, 2, 3]`. Lists in FunC can contain elements of different types.\n\n#### `cons`\n\n```func\nforall X -> tuple cons(X head, tuple tail) asm \"CONS\";\n```\n\nAdds an element to the beginning of a lisp-style list.\n\n#### `uncons`\n\n```func\nforall X -> (X, tuple) uncons(tuple list) asm \"UNCONS\";\n```\n\nExtracts the head and tail of a lisp-style list.\n\n#### `list_next`\n\n```func\nforall X -> (tuple, X) list_next(tuple list) asm( -> 1 0) \"UNCONS\";\n```\n\nExtracts the head and tail of a lisp-style list. It can be used as a [(non-)modifying method](/languages/func/statements#methods-calls).\n\n**Example**\n\n```func\n() foo(tuple xs) {\n    (_, int x) = xs.list_next(); ;; get the first element, `_` means do not use tail list\n    int y = xs~list_next(); ;; pop the first element\n    int z = xs~list_next(); ;; pop the second element\n}\n```\n\n#### `car`\n\n```func\nforall X -> X car(tuple list) asm \"CAR\";\n```\n\nReturns the head of a lisp-style list.\n\n#### `cdr`\n\n```func\ntuple cdr(tuple list) asm \"CDR\";\n```\n\nReturns the tail of a lisp-style list.\n\n### Other tuple primitives\n\n#### `empty_tuple`\n\n```func\ntuple empty_tuple() asm \"NIL\";\n```\n\nCreates an empty tuple (0 elements).\n\n#### `tpush`\n\n```func\nforall X -> tuple tpush(tuple t, X value) asm \"TPUSH\";\nforall X -> (tuple, ()) ~tpush(tuple t, X value) asm \"TPUSH\";\n```\n\nAppends a value to the tuple `(x1, ..., xn)`, forming `(x1, ..., xn, x)`. The resulting tuple must not exceed 255 elements,\nor a type check exception is thrown.\n\n#### `single`\n\n```func\nforall X -> [X] single(X x) asm \"SINGLE\";\n```\n\nCreates a tuple with a single element — singleton\n\n#### `unsingle`\n\n```func\nforall X -> X unsingle([X] t) asm \"UNSINGLE\";\n```\n\nUnpacks a singleton.\n\n#### `pair`\n\n```func\nforall X, Y -> [X, Y] pair(X x, Y y) asm \"PAIR\";\n```\n\nCreates a two-element tuple (pair).\n\n#### `unpair`\n\n```func\nforall X, Y -> (X, Y) unpair([X, Y] t) asm \"UNPAIR\";\n```\n\nUnpacks a pair into two separate values.\n\n#### `triple`\n\n```func\nforall X, Y, Z -> [X, Y, Z] triple(X x, Y y, Z z) asm \"TRIPLE\";\n```\n\nCreates a three-element tuple (triple).\n\n#### `untriple`\n\n```func\nforall X, Y, Z -> (X, Y, Z) untriple([X, Y, Z] t) asm \"UNTRIPLE\";\n```\n\nUnpacks a triple into three separate values.\n\n#### `tuple4`\n\n```func\nforall X, Y, Z, W -> [X, Y, Z, W] tuple4(X x, Y y, Z z, W w) asm \"4 TUPLE\";\n```\n\nCreates a four-element tuple.\n\n#### `untuple4`\n\n```func\nforall X, Y, Z, W -> (X, Y, Z, W) untuple4([X, Y, Z, W] t) asm \"4 UNTUPLE\";\n```\n\nUnpacks a four-element tuple into four separate values.\n\n### Tuple element access\n\n#### `first`\n\n```func\nforall X -> X first(tuple t) asm \"FIRST\";\n```\n\nReturns the first element of a tuple.\n\n#### `second`\n\n```func\nforall X -> X second(tuple t) asm \"SECOND\";\n```\n\nReturns the second element of a tuple.\n\n#### `third`\n\n```func\nforall X -> X third(tuple t) asm \"THIRD\";\n```\n\nReturns the third element of a tuple.\n\n#### `fourth`\n\n```func\nforall X -> X fourth(tuple t) asm \"3 INDEX\";\n```\n\nReturns the fourth element of a tuple.\n\n### Pair and triple element access\n\n#### `pair_first`\n\n```func\nforall X, Y -> X pair_first([X, Y] p) asm \"FIRST\";\n```\n\nReturns the first element of a pair.\n\n#### `pair_second`\n\n```func\nforall X, Y -> Y pair_second([X, Y] p) asm \"SECOND\";\n```\n\nReturns the second element of a pair.\n\n#### `triple_first`\n\n```func\nforall X, Y, Z -> X triple_first([X, Y, Z] p) asm \"FIRST\";\n```\n\nReturns the first element of a triple.\n\n#### `triple_second`\n\n```func\nforall X, Y, Z -> Y triple_second([X, Y, Z] p) asm \"SECOND\";\n```\n\nReturns the second element of a triple.\n\n#### `triple_third`\n\n```func\nforall X, Y, Z -> Z triple_third([X, Y, Z] p) asm \"THIRD\";\n```\n\nReturns the third element of a triple.\n\n## Domain specific primitives\n\n### Extracting info from c7\n\nThe [c7 special register][c7] holds useful data about smart contract execution.\nThe following primitives facilitate easy retrieval of this information:\n\n#### `now`\n\n```func\nint now() asm \"NOW\";\n```\n\nReturns the current Unix timestamp as an integer.\n\n#### `my_address`\n\n```func\nslice my_address() asm \"MYADDR\";\n```\n\nRetrieves the smart contract’s internal address as a Slice containing `MsgAddressInt`. If needed, it can be further processed using functions like `parse_std_addr`.\n\n#### `get_balance`\n\n```func\n[int, cell] get_balance() asm \"BALANCE\";\n```\n\nReturns the smart contract's balance as a `tuple`:\n\n- `int`: The remaining balance in nanotoncoins.\n- `cell`: A dictionary (with 32-bit keys) containing balances of extra currencies.\n\nSince this is retrieved during the compute phase, the balance reflects the incoming message `value`, with `storage_fee` and `import_fee` already subtracted.\n\n<Aside\n  type=\"danger\"\n>\n  Raw primitives such as `send_raw_message` do not update this field.\n</Aside>\n\n#### `cur_lt`\n\n```func\nint cur_lt() asm \"LTIME\";\n```\n\nReturns the logical time of the current transaction.\n\n#### `block_lt`\n\n```func\nint block_lt() asm \"BLOCKLT\";\n```\n\nReturns the logical time at the beginning of the current block.\n\n#### `config_param`\n\n```func\ncell config_param(int x) asm \"CONFIGOPTPARAM\";\n```\n\nReturns the value of the global configuration parameter with integer index `i` as `cell` or `null` value.\n\n#### `my_code`\n\n```func\ncell my_code() asm \"MYCODE\";\n```\n\nRetrieves the smart contract's code from `c7`.\n\n<Aside\n  type=\"danger\"\n>\n  This function is not included in the standard library, but is often sought by developers. You need to manually add initialization it to your contract system, with the `asm` word specified as shown in the snippet above.\n</Aside>\n\n### Hashes\n\n#### `cell_hash`\n\n```func\nint cell_hash(cell c) asm \"HASHCU\";\n```\n\nCalculates the representation hash of the given `cell c` and returns it as a 256-bit unsigned integer `x`.\nThis function is handy for signing and verifying signatures of arbitrary entities structured as a tree of cells.\n\n#### `slice_hash`\n\n```func\nint slice_hash(slice s) asm \"HASHSU\";\n```\n\nComputes the hash of the given `slice s` and returns it as a 256-bit unsigned integer `x`.\nThe result is equivalent to creating a standard cell containing only the data and references\nfrom `s` and then computing its hash using `cell_hash`.\n\n#### `string_hash`\n\n```func\nint string_hash(slice s) asm \"SHA256U\";\n```\n\nCalculates the SHA-256 hash of the data bits in the given `slice s`.\nA cell underflow exception is thrown if the bit length of `s` is not a multiple of eight.\nThe hash is returned as a 256-bit unsigned integer `x`.\n\n### Signature checks\n\n#### `check_signature`\n\n```func\nint check_signature(int hash, slice signature, int public_key) asm \"CHKSIGNU\";\n```\n\nChecks whether the given `signature` is a valid Ed25519 signature of the provided\n`hash` using the specified `public key`. The `hash` and `public key` are both 256-bit unsigned integers. The `signature` must be at least 512 bits long, and only the first 512 bits are used.\nIf the signature is valid, the function returns `-1`; otherwise, it returns `0`.\n\nRemember that `CHKSIGNU` converts the hash into a 256-bit slice and then calls `CHKSIGNS`.\nThis means that if the `hash` was initially generated from some data,\nthat data gets hashed _twice_ — the first time when creating the hash and the second time within `CHKSIGNS`.\n\n#### `check_data_signature`\n\n```func\nint check_data_signature(slice data, slice signature, int public_key) asm \"CHKSIGNS\";\n```\n\nVerifies whether the given `signature` is a valid Ed25519 signature for the data contained in the `slice data`,\nusing the specified `public key`, just like `check_signature`.\nA cell underflow exception is thrown if the data bit length is not a multiple of eight.\nThe verification follows the standard Ed25519 process,\nwhere SHA-256 is used to derive a 256-bit number from `data`, which is then signed.\n\n### Computation of BoC size\n\nThe following functions help calculate storage fees for user-provided data.\n\n#### `compute_data_size?`\n\n```func\n(int, int, int, int) compute_data_size?(cell c, int max_cells) asm \"CDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT\";\n```\n\nReturns `(x, y, z, -1)` or `(null, null, null, 0)`. It recursively calculates the number of unique cells `x`, data bits `y`, and cell references `z` in the **directed acyclic graph (DAG)** at `cell c`. This provides the total storage used by the DAG while recognizing identical cells.\n\nThe computation uses a depth-first traversal with a hash table to track visited cells, preventing redundant visits.\nIf the total amount of visited cells `x` exceeds `max_cells`, the process stops before visiting the `(max_cells + 1)` -th cell, and the function returns `0` to indicate failure. If `c` is `null`, the function returns `x = y = z = 0`.\n\n#### `slice_compute_data_size?`\n\n```func\n(int, int, int, int) slice_compute_data_size?(slice s, int max_cells) asm \"SDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT\";\n```\n\nIt works similarly to `compute_data_size?` but takes a `slice s` instead of a `cell`. The result `x` does not include the cell that contains the slice `s`, but `y` and `z` account for the data bits and cell references inside `s`.\n\n#### `compute_data_size`\n\n```func\n(int, int, int) compute_data_size(cell c, int max_cells) impure asm \"CDATASIZE\";\n```\n\nA strict version of `compute_data_size?` that throws a cell overflow exception (8) if the computation fails.\n\n#### `slice_compute_data_size`\n\n```func\n(int, int, int) slice_compute_data_size(slice s, int max_cells) impure asm \"SDATASIZE\";\n```\n\nA strict version of `slice_compute_data_size?` that throws a cell overflow exception (8) if the computation fails.\n\n### Persistent storage save and load\n\n#### `get_data`\n\n```func\ncell get_data() asm \"c4 PUSH\";\n```\n\nReturns the persistent contract storage cell, which can be later parsed or modified using slice and builder functions.\n\n#### `set_data`\n\n```func\n() set_data(cell c) impure asm \"c4 POP\";\n```\n\nSets cell `c` as persistent contract data. You can update the persistent contract storage with this primitive.\n\n### Continuation primitives\n\n#### `get_c3`\n\n```func\ncont get_c3() impure asm \"c3 PUSH\";\n```\n\nThe `c3` register typically holds a continuation set up by the contract code.\nIt is used for function calls.\nThe primitive returns the current value of `c3`.\n\n#### `set_c3`\n\n```func\n() set_c3(cont c) impure asm \"c3 POP\";\n```\n\nUpdates the `c3` value to modify the contract’s execution code at runtime. The current code and function call stack remain unchanged, but future function calls use the updated code.\n\n#### `bless`\n\n```func\ncont bless(slice s) impure asm \"BLESS\";\n```\n\nConverts a `slice s` into a basic continuation `c`, where `c.code = s`, an empty stack and a savelist.\n\n### Gas related primitives\n\n#### `accept_message`\n\n```func\n() accept_message() impure asm \"ACCEPT\";\n```\n\nThis function sets the current gas limit `gl` to its maximum possible value `gm` and resets the gas credit `gc` to zero.\nAt the same time, it deducts the previous gas credit `gc` from the remaining gas reserve `gr`.\nSimply put, the smart contract agrees to purchase gas to complete the transaction.\nThis function is required when processing external messages that do not carry any value and do not provide gas.\n\n{/* NOTE: Accept message effects. */}\n\n#### `set_gas_limit`\n\n```func\n() set_gas_limit(int limit) impure asm \"SETGASLIMIT\";\n```\n\nThis function sets the gas limit `gl` to the smaller of two values: the provided `limit` or the maximum allowed gas `gm`.\nIt also resets the gas credit `gc` to zero. If the contract already uses more gas than this new limit `gl`, including the current instruction, an out-of-gas exception is triggered before the new limit is applied.\n\nRemember that if the `limit` is `2^63 − 1` or higher, calling `set_gas_limit` works the same as calling `accept_message`.\n\n{/* NOTE: Accept message effects. */}\n\n#### `commit`\n\n```func\n() commit() impure asm \"COMMIT\";\n```\n\nSaves the current state of persistent storage `c4` and action registers `c5`, ensuring execution succeeds with these stored values,\neven if an exception occurs later.\n\n#### `buy_gas`\n\n```func\n() buy_gas(int gram) impure asm \"BUYGAS\";\n```\n\n<Aside\n  type=\"caution\"\n>\n  The `BUYGAS` opcode is currently not implemented.\n</Aside>\n\nThis function calculates how much gas can be purchased for the `gram` nanotoncoins and updates the gas limit `gl` accordingly,\nsimilar to `set_gas_limit`.\n\n### Actions primitives\n\n#### `raw_reserve`\n\n```func\n() raw_reserve(int amount, int mode) impure asm \"RAWRESERVE\";\n```\n\nThe `raw_reserve` function creates an output action\nthat reserves a specific amount of nanotoncoins from the account’s remaining balance.\nThe behavior depends on the `mode` parameter:\n\n- If `mode = 0`, exactly the `amount` of nanotoncoins is reserved.\n- If `mode = 2`, up to the `amount` of nanotoncoins is reserved.\n- If `mode = 1` or `mode = 3`, all but the `amount` of nanotoncoins is reserved.\n\nThis process is equivalent to generating an outbound message that transfers the `amount` of nanotoncoins or `b − amount` nanotoncoins,\nwhere `b` represents the remaining balance, to the sender. This ensures that subsequent output actions cannot exceed the remaining funds.\n\n**Mode Flags**\n\n- **Bit +2** in `mode`: prevents failure if the specified `amount` cannot be reserved. Instead, the entire remaining balance is reserved.\n- **Bit +8** in `mode`: negates `amount` (`amount <- -amount`) before executing further actions.\n- **Bit +4** in `mode`: increases `amount` by the original balance of the current account before the compute phase,\n  including all extra currencies, before performing any other checks and actions.\n\n**Constraints**\n\n- The `amount` must be a non-negative integer.\n- `mode` must be within the range `0..15`.\n\n#### `raw_reserve_extra`\n\n```func\n() raw_reserve_extra(int amount, cell extra_amount, int mode) impure asm \"RAWRESERVEX\";\n```\n\nSimilar to `raw_reserve`, but it also supports an `extra_amount` dictionary.\nThis dictionary, given as a `cell` or `null`, allows reserving currencies other than Toncoin.\n\n#### `send_raw_message`\n\n```func\n() send_raw_message(cell msg, int mode) impure asm \"SENDRAWMSG\";\n```\n\nThis function sends a raw message stored in `msg`. This message must contain a properly serialized `Message X` object, with a few exceptions.\nThe source address can have a dummy value `addr_none`, which the current smart contract address will automatically replace. The fields `ihr_fee`, `fwd_fee`, `created_lt`, and `created_at` can hold arbitrary values, as they will be updated with the correct ones during the action phase of the transaction. The integer parameter `mode` specifies the flags.\n\nCurrently, there are **3 modes** and **4 flags** available for messages.\nA single mode can be combined with multiple flags or none to form the desired `mode`.\nThe combination is achieved by **summing** their values. The table below provides descriptions of the available modes and flags.\n\n| Mode  | Description                                                                                                     |\n| :---- | :-------------------------------------------------------------------------------------------------------------- |\n| `0`   | Sends an ordinary message.                                                                                      |\n| `64`  | Transfers the full remaining value of the inbound message and the initially specified amount.                   |\n| `128` | Transfers the entire remaining balance of the current smart contract instead of the initially specified amount. |\n\n| Flag  | Description                                                                                              |\n| :---- | :------------------------------------------------------------------------------------------------------- |\n| `+1`  | Pays transfer fees separately from the message value.                                                    |\n| `+2`  | Ignores certain errors that occur while processing the message during the action phase (see note below). |\n| `+16` | Bounces the transaction if the action fails. Has no effect if `+2` is used.                              |\n| `+32` | Destroys the current account if its resulting balance is zero (commonly used with `mode = 128`).         |\n\n<Aside\n  title=\"+2 flag\"\n>\n  The `+2` flag ignores specific errors that may occur while processing a message during the action phase. These include:\n\n  1. Insufficient Toncoin:\n     - Not enough value to transfer with the message (the entire inbound message value has been used).\n     - Insufficient funds to process the message.\n     - Not enough attached value to cover forwarding fees.\n     - Insufficient extra currency to send with the message.\n     - Not enough funds to pay for an outbound external message.\n  1. Message exceeds size limits, see the [maximum message bit and cell size](/foundations/limits#message-and-transaction-limits) for details.\n  1. Excessive Merkle depth in the message.\n\n  However, the `+2` flag does not ignore errors in the following cases:\n\n  1. The message format is invalid.\n  1. Both `64` and `128` modes are used simultaneously.\n  1. The outbound message contains invalid libraries in [`StateInit`](/foundations/messages/deploy).\n  1. The external message is not ordinary or includes the `+16` or `+32` flag.\n</Aside>\n\n<Aside\n  type=\"caution\"\n>\n  1. **+16 flag** should not be used in external messages (e.g., to wallets), as there is no sender to receive the bounced message.\n  1. **+2 flag** is important in external messages (e.g., to wallets).\n</Aside>\n\n#### `set_code`\n\n```func\n() set_code(cell new_code) impure asm \"SETCODE\";\n```\n\nGenerates an output action to update the smart contract's code to the one provided in the `new_code` cell.\nThis change occurs only after the smart contract completes its current execution.\nSee also [set\\_c3](/languages/func/stdlib#set_c3).\n\n### Random number generator primitives\n\nThe pseudo-random number generator relies on a random seed, a 256-bit unsigned integer, and sometimes additional data stored in [c7].\n\nBefore a smart contract executes in the TON Blockchain, its initial random seed is derived from a hash of the smart contract address and the global block random seed. If the same smart contract runs multiple times within a block, each run will use the same random seed. This can be adjusted by calling `randomize_ltbefore` using the pseudo-random number generator for the first time.\n\n<Aside\n  type=\"caution\"\n>\n  Remember that the random numbers generated by the functions below can be predicted unless additional techniques are used.\n</Aside>\n\n#### `random`\n\n```func\nint random() impure asm \"RANDU256\";\n```\n\nGenerates a new pseudo-random 256-bit unsigned integer `x`. The process works as follows:\n\n- Let `r` be the previous random seed, a 32-byte array constructed from the big-endian representation of a 256-bit unsigned integer.\n- Compute `sha512(r)`.\n- The first 32 bytes of the hash become the new seed `r'`.\n- The remaining 32 bytes are returned as the new random value `x`.\n\n#### `rand`\n\n```func\nint rand(int range) impure asm \"RAND\";\n```\n\nGenerates a new pseudo-random integer `z` in the range `0..range−1` (or `range..−1` if `range < 0`). More precisely, an unsigned random value `x` is generated as in `random`; then `z := x * range / 2^256` is\ncomputed.\n\nProduces a pseudo-random integer `z` within the range `0..range−1` (or `range..−1` if `range < 0`).\n\n- First, an unsigned random value `x` is generated using `random()`.\n- Then, `z := x * range / 2^256` is calculated.\n\n#### `get_seed`\n\n```func\nint get_seed() impure asm \"RANDSEED\";\n```\n\nReturns the current random seed as a 256-bit unsigned integer.\n\n#### `set_seed`\n\n```func\nint set_seed(int seed) impure asm \"SETRAND\";\n```\n\nSets the random seed to a specified 256-bit unsigned integer `seed`.\n\n#### `randomize`\n\n```func\n() randomize(int x) impure asm \"ADDRAND\";\n```\n\nMixes an unsigned 256-bit integer `x` into a random seed `r` by setting the random seed to sha256 of the concatenation of two 32-byte strings: the first with a big-endian representation of the old seed `r`, and the second with a big-endian representation of `x`.\n\nMixes a 256-bit unsigned integer `x` into the random seed `r` by updating`r` to `sha256(r || x)`, where:\n\n- `r` is the previous seed, represented as a 32-byte big-endian array.\n- `x` is also converted into a 32-byte big-endian array.\n  T- he new seed is the SHA-256 hash of their concatenation.\n\n#### `randomize_lt`\n\n```func\n() randomize_lt() impure asm \"LTIME\" \"ADDRAND\";\n```\n\nEquivalent to calling `randomize(cur_lt());`.\n\n### Address manipulation primitives\n\nThe functions below handle the serialization and deserialization of values based on the following TL-B scheme.\n\n```func\naddr_none$00 = MsgAddressExt;\n\naddr_extern$01 len:(## 8) external_address:(bits len)\n             = MsgAddressExt;\n\nanycast_info$_ depth:(#<= 30) { depth >= 1 }\n  rewrite_pfx:(bits depth) = Anycast;\n\naddr_std$10 anycast:(Maybe Anycast)\n  workchain_id:int8 address:bits256 = MsgAddressInt;\n\naddr_var$11 anycast:(Maybe Anycast) addr_len:(## 9)\n  workchain_id:int32 address:(bits addr_len) = MsgAddressInt;\n_ _:MsgAddressInt = MsgAddress;\n_ _:MsgAddressExt = MsgAddress;\n\nint_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool\n  src:MsgAddress dest:MsgAddressInt\n  value:CurrencyCollection ihr_fee:Grams fwd_fee:Grams\n  created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed;\n\next_out_msg_info$11 src:MsgAddress dest:MsgAddressExt\n  created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed;\n```\n\n- `addr_none` is represented by `t = (0)`, i.e., a tuple containing exactly\n  one integer that equals zero\n- `addr_extern` is represented by `t = (1, s)`, where slice `s` contains the\n  field `external_address`. In other words, `t` is a pair (a tuple consisting of two entries), containing an integer equal to one and slice `s`\n- `addr_std` is represented by `t = (2, u, x, s)`, where `u` is either `null` (if `anycast` is absent) or a slice `s'` containing `rewrite_pfx` (if `anycast` is present). Next, integer `x` is the `workchain_id`, and slice `s` contains the address\n- `addr_var` is represented by `t = (3, u, x, s)`, where `u`, `x`, and `s` have the same meaning as for `addr_std`\n\nA deserialized `MsgAddress`cis represented as a tuple `t` with the following structure:\n\n- `addr_none` is represented as `t = (0)`, a single-element tuple where the integer is zero.\n- `addr_extern` is represented as `t = (1, s)`, where `s` is a slice containing `external_address`. In other words, `t` is a pair with the first element being `1` and the second being `s`.\n- `addr_std` is represented as `t = (2, u, x, s)`, where:\n  - `u` is `null` if `anycast` is absent or a slice `s'` containing `rewrite_pfx` if `anycast` is present.\n  - `x` is the `workchain_id`.\n  - `s` is a slice containing the address.\n- `addr_var` is represented as `t = (3, u, x, s)`, where `u`, `x,` and `s` follow the same structure as `addr_std`.\n\n#### `load_msg_addr`\n\n```func\n(slice, slice) load_msg_addr(slice s) asm( -> 1 0) \"LDMSGADDR\";\n```\n\nExtracts a valid `MsgAddress` prefix from `slice s` and returns the extracted prefix `s'` and the remaining part `s''`.\n\n#### `parse_addr`\n\n```func\ntuple parse_addr(slice s) asm \"PARSEMSGADDR\";\n```\n\nSplits `slice s`, which holds a valid `MsgAddress`, into tuple `t`, separating its fields. If `s` is invalid, a cell deserialization exception is raised.\n\n#### `parse_std_addr`\n\n```func\n(int, int) parse_std_addr(slice s) asm \"REWRITESTDADDR\";\n```\n\nExtracts a valid `MsgAddressInt`, typically `msg_addr_std`, from `slice s`, modifies the address prefix if `anycast` is present, and returns the workchain and 256-bit address as integers. A cell `deserialization` exception is triggered if the address isn't 256-bit\nor `s` isn't a valid `MsgAddressInt` serialization.\n\n#### `parse_var_addr`\n\n```func\n(int, slice) parse_var_addr(slice s) asm \"REWRITEVARADDR\";\n```\n\nA modified version of `parse_std_addr` that returns the modified address as `slice s`,\neven if its length is not exactly 256 bits, as in `msg_addr_var`.\n\n### Debug primitives\n\nDebug primitives help inspect the state of various variables while running tests or executing console scripts.\n\n#### `~dump`\n\n```func\nforall X -> () ~dump(X value) impure asm \"s0 DUMP\";\n```\n\nPrints the given value. Multiple values can be output as a tuple, e.g.,`~dump([v1, v2, v3])`.\n\n#### `~strdump`\n\n```func\n() ~strdump(slice str) impure asm \"STRDUMP\";\n```\n\nPrints a string. The bit length of the slice parameter must be a multiple of 8.\n\n#### `dump_stack`\n\n```func\n() dump_stack() impure asm \"DUMPSTK\";\n```\n\nPrints the current stack up to the top 255 values and displays the total stack depth.\n\n### Slice primitives\n\nA primitive _loads_ data when it returns both the extracted data and the remainder of the slice.\nIt can be used as a [modifying method](/languages/func/statements#modifying-methods).\nA primitive _preloads_ data when it returns only the extracted data, leaving the original slice unchanged. It can be used as a [non-modifying method](/languages/func/statements#non-modifying-methods).\nUnless specified otherwise, loading and preloading primitives read data from the beginning of the slice.\n\n#### `begin_parse`\n\n```func\nslice begin_parse(cell c) asm \"CTOS\";\n```\n\nConverts a `cell` into a `slice`. The input `c` must be either an ordinary or exotic cell.\nSee [TVM.pdf](https://ton.org/tvm.pdf), 3.1.2. If `c` is exotic, it is automatically converted into an ordinary cell `c'`\nbefore being transformed into a `slice`.\n\n#### `end_parse`\n\n```func\n() end_parse(slice s) impure asm \"ENDS\";\n```\n\nChecks if the `slice s` is empty. It throws an exception if it is not.\n\n#### `load_ref`\n\n```func\n(slice, cell) load_ref(slice s) asm( -> 1 0) \"LDREF\";\n```\n\nLoads the first reference from a slice.\n\n#### `preload_ref`\n\n```func\ncell preload_ref(slice s) asm \"PLDREF\";\n```\n\nPreloads the first reference from a slice.\n\n#### `load_int`\n\n```func\n;; (slice, int) ~load_int(slice s, int len) asm(s len -> 1 0) \"LDIX\";\n```\n\nLoads a signed `len`-bit integer from a slice.\n\n#### `load_uint`\n\n```func\n;; (slice, int) ~load_uint(slice s, int len) asm( -> 1 0) \"LDUX\";\n```\n\nLoads an unsigned `len`-bit integer from a slice.\n\n#### `preload_int`\n\n```func\n;; int preload_int(slice s, int len) asm \"PLDIX\";\n```\n\nPreloads a signed `len`-bit integer from a slice.\n\n#### `preload_uint`\n\n```func\n;; int preload_uint(slice s, int len) asm \"PLDUX\";\n```\n\nPreloads an unsigned `len`-bit integer from a slice.\n\n#### `load_bits`\n\n```func\n;; (slice, slice) load_bits(slice s, int len) asm(s len -> 1 0) \"LDSLICEX\";\n```\n\nLoads the first `0 ≤ len ≤ 1023` bits from `slice s` into a new slice `s''`.\n\n#### `preload_bits`\n\n```func\n;; slice preload_bits(slice s, int len) asm \"PLDSLICEX\";\n```\n\nPreloads the first `0 ≤ len ≤ 1023` bits from `slice s` into a new slice `s''`.\n\n#### `load_coins`\n\n```func\n(slice, int) load_coins(slice s) asm( -> 1 0) \"LDGRAMS\";\n```\n\nLoads serialized amount of Toncoin, which is an unsigned integer up to `2^120 - 1`.\n\n#### `skip_bits`\n\n```func\nslice skip_bits(slice s, int len) asm \"SDSKIPFIRST\";\n(slice, ()) ~skip_bits(slice s, int len) asm \"SDSKIPFIRST\";\n```\n\nReturns all bits of `s` except for the first `len` bits, where `0 ≤ len ≤ 1023`.\n\n#### `first_bits`\n\n```func\nslice first_bits(slice s, int len) asm \"SDCUTFIRST\";\n```\n\nReturns the first `len` bits of `s`, where `0 ≤ len ≤ 1023`.\n\n#### `skip_last_bits`\n\n```func\nslice skip_last_bits(slice s, int len) asm \"SDSKIPLAST\";\n(slice, ()) ~skip_last_bits(slice s, int len) asm \"SDSKIPLAST\";\n```\n\nReturns all bits of `s` except for the last `len` bits, where `0 ≤ len ≤ 1023`.\n\n#### `slice_last`\n\n```func\nslice slice_last(slice s, int len) asm \"SDCUTLAST\";\n```\n\nReturns the last `len` bits of `s`, where `0 ≤ len ≤ 1023`.\n\n#### `load_dict`\n\n```func\n(slice, cell) load_dict(slice s) asm( -> 1 0) \"LDDICT\";\n```\n\nLoads a dictionary `D` from slice `s`. It can be used for dictionaries or to values of arbitrary `Maybe ^Y` types (returns `null` if the `nothing` constructor is used).\n\n#### `preload_dict`\n\n```func\ncell preload_dict(slice s) asm \"PLDDICT\";\n```\n\nPreloads a dictionary `D` from slice `s`.\n\n#### `skip_dict`\n\n```func\nslice skip_dict(slice s) asm \"SKIPDICT\";\n```\n\nLoads a dictionary as `load_dict` but returns only the remainder of the slice.\n\n### Slice size primitives\n\n#### `slice_refs`\n\n```func\nint slice_refs(slice s) asm \"SREFS\";\n```\n\nReturns the number of references in slice `s`.\n\n#### `slice_bits`\n\n```func\nint slice_bits(slice s) asm \"SBITS\";\n```\n\nReturns the number of data bits in slice `s`.\n\n#### `slice_bits_refs`\n\n```func\n(int, int) slice_bits_refs(slice s) asm \"SBITREFS\";\n```\n\nReturns both the number of data bits and the number of references in `s`.\n\n#### `slice_empty?`\n\n```func\nint slice_empty?(slice s) asm \"SEMPTY\";\n```\n\nChecks whether slice `s` is empty (i.e., contains no bits of data and no cell references).\n\n#### `slice_data_empty?`\n\n```func\nint slice_data_empty?(slice s) asm \"SDEMPTY\";\n```\n\nChecks whether slice `s` has no bits of data.\n\n#### `slice_refs_empty?`\n\n```func\nint slice_refs_empty?(slice s) asm \"SREMPTY\";\n```\n\nChecks whether slice `s` has no references.\n\n#### `slice_depth`\n\n```func\nint slice_depth(slice s) asm \"SDEPTH\";\n```\n\nReturns the depth of slice `s`.\nIf `s` has no references, it returns `0`;\notherwise, the returned value is one plus the maximum depths of cells referred to from `s`.\n\n### Builder primitives\n\nA primitive _stores_ a value `x` in a builder `b` by returning a modified version `b'` with `x` added at the end. It can also be used as a [non-modifying method](/languages/func/statements#non-modifying-methods).\nEach of the following primitives first checks for enough space in the `builder` and then verifies the range of the serialized value.\n\n#### `begin_cell`\n\n```func\nbuilder begin_cell() asm \"NEWC\";\n```\n\nCreates a new empty `builder`.\n\n#### `end_cell`\n\n```func\ncell end_cell(builder b) asm \"ENDC\";\n```\n\nConverts a `builder` into a standard `cell`.\n\n#### `store_ref`\n\n```func\nbuilder store_ref(builder b, cell c) asm(c b) \"STREF\";\n```\n\nStores a reference to cell `c` in builder `b`.\n\n#### `store_uint`\n\n```func\nbuilder store_uint(builder b, int x, int len) asm(x b len) \"STUX\";\n```\n\nStores an unsigned `len`-bit integer `x` in `b`, where `0 ≤ len ≤ 256`.\n\n#### `store_int`\n\n```func\nbuilder store_int(builder b, int x, int len) asm(x b len) \"STIX\";\n```\n\nStores a signed `len`-bit integer `x` in `b`, where `0 ≤ len ≤ 257`.\n\n#### `store_slice`\n\n```func\nbuilder store_slice(builder b, slice s) asm \"STSLICER\";\n```\n\nStores slice `s` in builder `b`.\n\n#### `store_grams`\n\n```func\nbuilder store_grams(builder b, int x) asm \"STGRAMS\";\n```\n\n#### `store_coins`\n\n```func\nbuilder store_coins(builder b, int x) asm \"STGRAMS\";\n```\n\nSerializes an integer `x` in the range `0..2^120 − 1` into builder `b`. The serialization consists of:\n\n- A 4-bit unsigned big-endian integer `l`, the smallest `l ≥ 0` such that `x < 2^8l`.\n- An `8l`-bit unsigned big-endian representation of `x`.\n\nA range check exception is thrown if `x` is outside the supported range.\n\nThis is the standard way of storing Toncoin.\n\n#### `store_dict`\n\n```func\nbuilder store_dict(builder b, cell c) asm(c b) \"STDICT\";\n```\n\nStores a dictionary `D` represented by cell `c` or `null` into builder `b`. Stores a 1-bit and a reference to `c` if `c` is not `null`; otherwise, stores a 0-bit.\n\n#### `store_maybe_ref`\n\n```func\nbuilder store_maybe_ref(builder b, cell c) asm(c b) \"STOPTREF\";\n```\n\nThe same as `store_dict`.\n\n### Builder size primitives\n\n#### `builder_refs`\n\n```func\nint builder_refs(builder b) asm \"BREFS\";\n```\n\nReturns the number of cell references currently stored in builder `b`.\n\n#### `builder_bits`\n\n```func\nint builder_bits(builder b) asm \"BBITS\";\n```\n\nReturns the number of data bits currently stored in builder `b`.\n\n#### `builder_depth`\n\n```func\nint builder_depth(builder b) asm \"BDEPTH\";\n```\n\nReturns the depth of builder `b`. If `b` contains no cell references, it returns `0`. Otherwise, it returns `1` plus the maximum depth among the referenced cells.\n\n### Cell primitives\n\n#### `cell_depth`\n\n```func\nint cell_depth(cell c) asm \"CDEPTH\";\n```\n\nReturns the depth of the given `cell c`. If `c` has no references, the function returns `0`. Otherwise, it returns `1` plus the maximum depth among all cells referenced by `c`. If `c` is `null` instead of a cell, the function returns `0`.\n\n#### `cell_null?`\n\n```func\nint cell_null?(cell c) asm \"ISNULL\";\n```\n\nChecks whether the given `cell c` is `null`. In most cases, a `null` cell represents an empty dictionary. FunC also includes a polymorphic `null?` built-in function. See [built-in](/languages/func/built-ins#other-primitives) for more details.\n\n## Dictionaries primitives\n\n<Aside\n  type=\"caution\"\n>\n  The dictionary primitives below are low-level and do not verify whether the cell structure matches the expected operation.\n  Using a dictionary operation on a \"non-dictionary\" cell results in **undefined behavior**. The same applies when using keys of different lengths or types, such as writing to a dictionary using an 8-bit signed key and a 7-bit unsigned key.\n\n  In most cases, this will cause an exception. However, in rare cases, it may lead to incorrect values being written or read. Developers should avoid such code.\n</Aside>\n\nAs stated in [TVM.pdf](https://ton.org/tvm.pdf):\n\n> Dictionaries can be represented in two different ways as TVM stack values:\n>\n> 1. **As a slice `s`** containing the serialized TL-B value of type `HashmapE(n, X)`. In simpler terms, `s` consists either of a single `0` bit if the dictionary is empty or a `1` bit followed by a reference to a cell containing the binary tree's root — essentially, a serialized value of type `Hashmap(n, X)`.\n>\n> 1. **As a `Maybe cell (c^?)`**, which is either a cell that contains a serialized `Hashmap(n, X)` same as above or `null`, indicating an empty dictionary. See [null values](/languages/func/types#null-values) for details. When using this format, the dictionary is typically referred to as `D`.\n>\n> Most dictionary-related operations use the second format because it is easier to manipulate on the stack. However, when dictionaries are serialized within larger TL-B objects, they follow the first representation.\n\nIn FunC, dictionaries are also represented as `cells` with the implicit assumption that they can be `null`. There are no separate types for dictionaries with different key lengths or value types — after all, this is FunC, not FunC++.\n\n### Taxonomy note\n\nA dictionary primitive interprets dictionary keys in one of three ways:\n\n1. Unsigned `l`-bit integers (denoted by **u**);\n1. Signed `l`-bit integers (denoted by **i**);\n1. `l`-bit slices (**no prefix**).\n\nThe naming convention of dictionary primitives reflects these distinctions. For example:\n\n- `udict_set` is a set-by-key function for dictionaries with unsigned integer keys.\n- `idict_set` is the equivalent function for signed integer keys.\n- `dict_set` applies to dictionaries with slice keys.\n\nIn function titles, an **empty prefix** indicates slice keys.\nAdditionally, some primitives have counterparts prefixed with `~`, enabling them to be used as [modifying methods](/languages/func/statements#modifying-methods).\n\n### Dictionary values\n\nValues in a dictionary can be stored in two ways:\n\n1. As a **subslice** within an inner dictionary cell.\n1. As a **reference** to a separate cell.\n\nIn the first case, even if a value is small enough to fit within a cell, it may not fit within the dictionary.\nThis is because a segment of the corresponding key may already occupy part of the inner cell’s space.\n\nThe second method, while ensuring storage, is less efficient regarding gas consumption.\nStoring a value this way is functionally equivalent to inserting a slice with no data bits and a single reference to the value,\nas in the first method.\n\n#### `dict_set`\n\n```func\ncell udict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) \"DICTUSET\";\ncell idict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) \"DICTISET\";\ncell dict_set(cell dict, int key_len, slice index, slice value) asm(value index dict key_len) \"DICTSET\";\n(cell, ()) ~udict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) \"DICTUSET\";\n(cell, ()) ~idict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) \"DICTISET\";\n(cell, ()) ~dict_set(cell dict, int key_len, slice index, slice value) asm(value index dict key_len) \"DICTSET\";\n```\n\nThis function updates the dictionary `dict` by setting the value corresponding to the `key_len`-bit key `index` to `value`, a slice, and returns the updated dictionary.\n\n#### `dict_set_ref`\n\n```func\ncell idict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) \"DICTISETREF\";\ncell udict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) \"DICTUSETREF\";\n(cell, ()) ~idict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) \"DICTISETREF\";\n(cell, ()) ~udict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) \"DICTUSETREF\";\n```\n\nThis is similar to `dict_set`, but it sets the value to a reference of cell `value`.\n\n#### `dict_get?`\n\n```func\n(slice, int) idict_get?(cell dict, int key_len, int index) asm(index dict key_len) \"DICTIGET\" \"NULLSWAPIFNOT\";\n(slice, int) udict_get?(cell dict, int key_len, int index) asm(index dict key_len) \"DICTUGET\" \"NULLSWAPIFNOT\";\n```\n\nSearches for the key `index` in the `dict` dictionary with `key_len`-bit keys. It retrieves the associated value as a `slice` and returns a success flag of `-1` if found. If not found, it returns `(null, 0)`.\n\n#### `dict_get_ref?`\n\n```func\n(cell, int) idict_get_ref?(cell dict, int key_len, int index) asm(index dict key_len) \"DICTIGETREF\";\n(cell, int) udict_get_ref?(cell dict, int key_len, int index) asm(index dict key_len) \"DICTUGETREF\";\n```\n\nSimilar to`dict_get?`, but it returns the first reference of the found value.\n\n#### `dict_get_ref`\n\n```func\ncell idict_get_ref(cell dict, int key_len, int index) asm(index dict key_len) \"DICTIGETOPTREF\";\n```\n\nThis variant of `dict_get_ref?` returns `null` if the key `index` is absent in the dictionary `dict`.\n\n#### `dict_set_get_ref`\n\n```func\n(cell, cell) idict_set_get_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) \"DICTISETGETOPTREF\";\n(cell, cell) udict_set_get_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) \"DICTUSETGETOPTREF\";\n```\n\nThis function sets the value associated with the `index` to `value`. If the `value` is `null`, the key is deleted.\nIt then returns the old value or `null` if it wasn't present.\n\n#### `dict_delete?`\n\n```func\n(cell, int) idict_delete?(cell dict, int key_len, int index) asm(index dict key_len) \"DICTIDEL\";\n(cell, int) udict_delete?(cell dict, int key_len, int index) asm(index dict key_len) \"DICTUDEL\";\n```\n\nThis function deletes the `key_len`-bit key `index` from the dictionary `dict`. It returns the modified dictionary and a success flag of `-1` if successful.\nIf the key is not found, it returns the original dictionary and `0`.\n\n#### `dict_delete_get?`\n\n```func\n(cell, slice, int) idict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) \"DICTIDELGET\" \"NULLSWAPIFNOT\";\n(cell, slice, int) udict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) \"DICTUDELGET\" \"NULLSWAPIFNOT\";\n(cell, (slice, int)) ~idict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) \"DICTIDELGET\" \"NULLSWAPIFNOT\";\n(cell, (slice, int)) ~udict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) \"DICTUDELGET\" \"NULLSWAPIFNOT\";\n```\n\nDeletes the `key_len`-bit key `index` from the dictionary `dict`. If the key is found, it returns the modified dictionary, the original value associated with the key as a Slice, and the success flag `-1`. If the key is not found, it returns `(dict, null, 0)`.\n\n#### `dict_add?`\n\n```func\n(cell, int) udict_add?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) \"DICTUADD\";\n(cell, int) idict_add?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) \"DICTIADD\";\n```\n\nThis `add` operation is similar to `dict_set` but only sets the value if the key `index` does not already exist in the dictionary `dict`. It returns the modified dictionary and a success flag of `-1` or `(dict, 0)`.\n\n#### `dict_replace?`\n\n```func\n(cell, int) udict_replace?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) \"DICTUREPLACE\";\n(cell, int) idict_replace?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) \"DICTIREPLACE\";\n```\n\nThis `replace` operation works like `dict_set`, but it only updates the value for the `index` if the key is already present in the dictionary `dict`. It returns the modified dictionary and a success flag of `-1` or `(dict, 0)`.\n\n### Builder counterparts\n\nThe following primitives accept a builder as the new value instead of a slice, making them more convenient when the value needs to be serialized from multiple components computed on the stack. Functionally, this is equivalent to converting the builder into a slice and executing the corresponding primitive listed above.\n\n#### `dict_set_builder`\n\n```func\ncell udict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) \"DICTUSETB\";\ncell idict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) \"DICTISETB\";\ncell dict_set_builder(cell dict, int key_len, slice index, builder value) asm(value index dict key_len) \"DICTSETB\";\n(cell, ()) ~idict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) \"DICTISETB\";\n(cell, ()) ~udict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) \"DICTUSETB\";\n(cell, ()) ~dict_set_builder(cell dict, int key_len, slice index, builder value) asm(value index dict key_len) \"DICTSETB\";\n```\n\nIt works similarly to `dict_set` but takes a builder as input.\n\n#### `dict_add_builder?`\n\n```func\n(cell, int) udict_add_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) \"DICTUADDB\";\n(cell, int) idict_add_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) \"DICTIADDB\";\n```\n\nSimilar to `dict_add?`, but uses a builder.\n\n#### `dict_replace_builder?`\n\n```func\n(cell, int) udict_replace_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) \"DICTUREPLACEB\";\n(cell, int) idict_replace_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) \"DICTIREPLACEB\";\n```\n\nSimilar to`dict_replace?`, but uses a builder.\n\n#### `dict_delete_get_min`\n\n```func\n(cell, int, slice, int) udict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) \"DICTUREMMIN\" \"NULLSWAPIFNOT2\";\n(cell, int, slice, int) idict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) \"DICTIREMMIN\" \"NULLSWAPIFNOT2\";\n(cell, slice, slice, int) dict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) \"DICTREMMIN\" \"NULLSWAPIFNOT2\";\n(cell, (int, slice, int)) ~idict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) \"DICTIREMMIN\" \"NULLSWAPIFNOT2\";\n(cell, (int, slice, int)) ~udict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) \"DICTUREMMIN\" \"NULLSWAPIFNOT2\";\n(cell, (slice, slice, int)) ~dict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) \"DICTREMMIN\" \"NULLSWAPIFNOT2\";\n```\n\nFinds the smallest key `k` in the dictionary `dict`, removes it, and returns `(dict', k, x, -1)`, where `dict'` is the updated dictionary and `x` is the value associated with `k`. If the dictionary is empty, it returns `(dict, null, null, 0)`.\n\nNote: The key returned by `idict_delete_get_min` may differ from that returned by `dict_delete_get_min` and `udict_delete_get_min`.\n\n#### `dict_delete_get_max`\n\n```func\n(cell, int, slice, int) udict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) \"DICTUREMMAX\" \"NULLSWAPIFNOT2\";\n(cell, int, slice, int) idict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) \"DICTIREMMAX\" \"NULLSWAPIFNOT2\";\n(cell, slice, slice, int) dict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) \"DICTREMMAX\" \"NULLSWAPIFNOT2\";\n(cell, (int, slice, int)) ~udict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) \"DICTUREMMAX\" \"NULLSWAPIFNOT2\";\n(cell, (int, slice, int)) ~idict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) \"DICTIREMMAX\" \"NULLSWAPIFNOT2\";\n(cell, (slice, slice, int)) ~dict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) \"DICTREMMAX\" \"NULLSWAPIFNOT2\";\n```\n\nFinds the largest key `k` in the dictionary `dict`, removes it, and returns `(dict', k, x, -1)`, where `dict'` is the updated dictionary and `x` is the value associated with `k`. If the dictionary is empty, it returns `(dict, null, null, 0)`.\n\n#### `dict_get_min?`\n\n```func\n(int, slice, int) udict_get_min?(cell dict, int key_len) asm (-> 1 0 2) \"DICTUMIN\" \"NULLSWAPIFNOT2\";\n(int, slice, int) idict_get_min?(cell dict, int key_len) asm (-> 1 0 2) \"DICTIMIN\" \"NULLSWAPIFNOT2\";\n```\n\nFinds the smallest key `k` in the dictionary `dict` and returns `(k, x, -1)`, where `x` is the value associated with `k`. If the dictionary is empty, it returns `(null, null, 0)`.\n\n#### `dict_get_max?`\n\n```func\n(int, slice, int) udict_get_max?(cell dict, int key_len) asm (-> 1 0 2) \"DICTUMAX\" \"NULLSWAPIFNOT2\";\n(int, slice, int) idict_get_max?(cell dict, int key_len) asm (-> 1 0 2) \"DICTIMAX\" \"NULLSWAPIFNOT2\";\n```\n\nFinds the largest key `k` in the dictionary `dict` and returns `(k, x, -1)`, where `x` is the value associated with `k`. If the dictionary is empty, it returns `(null, null, 0)`.\n\n#### `dict_get_min_ref?`\n\n```func\n(int, cell, int) udict_get_min_ref?(cell dict, int key_len) asm (-> 1 0 2) \"DICTUMINREF\" \"NULLSWAPIFNOT2\";\n(int, cell, int) idict_get_min_ref?(cell dict, int key_len) asm (-> 1 0 2) \"DICTIMINREF\" \"NULLSWAPIFNOT2\";\n```\n\nSame as `dict_get_min?` but it returns a reference.\n\n#### `dict_get_max_ref?`\n\n```func\n(int, cell, int) udict_get_max_ref?(cell dict, int key_len) asm (-> 1 0 2) \"DICTUMAXREF\" \"NULLSWAPIFNOT2\";\n(int, cell, int) idict_get_max_ref?(cell dict, int key_len) asm (-> 1 0 2) \"DICTIMAXREF\" \"NULLSWAPIFNOT2\";\n```\n\nSame as `dict_get_max?` but it returns a reference.\n\n#### `dict_get_next?`\n\n```func\n(int, slice, int) udict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) \"DICTUGETNEXT\" \"NULLSWAPIFNOT2\";\n(int, slice, int) idict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) \"DICTIGETNEXT\" \"NULLSWAPIFNOT2\";\n```\n\nFinds the smallest key `k` in `dict` that is greater than the `pivot`. Returns `k`, associated value, and a success flag. If the dictionary is empty, it returns `(null, null, 0)`.\n\n#### `dict_get_nexteq?`\n\n```func\n(int, slice, int) udict_get_nexteq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) \"DICTUGETNEXTEQ\" \"NULLSWAPIFNOT2\";\n(int, slice, int) idict_get_nexteq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) \"DICTIGETNEXTEQ\" \"NULLSWAPIFNOT2\";\n```\n\nSimilar to `dict_get_next?`, but instead finds the smallest key `k` that is greater than or equal to the `pivot`.\n\n#### `dict_get_prev?`\n\n```func\n(int, slice, int) udict_get_prev?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) \"DICTUGETPREV\" \"NULLSWAPIFNOT2\";\n(int, slice, int) idict_get_prev?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) \"DICTIGETPREV\" \"NULLSWAPIFNOT2\";\n```\n\nSimilar to `dict_get_next?`, but instead finds the largest key `k` that is less than the `pivot`.\n\n#### `dict_get_preveq?`\n\n```func\n(int, slice, int) udict_get_preveq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) \"DICTUGETPREVEQ\" \"NULLSWAPIFNOT2\";\n(int, slice, int) idict_get_preveq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) \"DICTIGETPREVEQ\" \"NULLSWAPIFNOT2\";\n```\n\nSimilar to `dict_get_prev?`, but instead finds the largest key `k` that is less than or equal to the `pivot`.\n\n#### `new_dict`\n\n```func\ncell new_dict() asm \"NEWDICT\";\n```\n\nCreates an empty dictionary, which is represented as a `null` value — a special case of `null()`.\n\n#### `dict_empty?`\n\n```func\nint dict_empty?(cell c) asm \"DICTEMPTY\";\n```\n\nChecks whether a dictionary is empty. Equivalent to `cell_null?`.\n\n### Prefix dictionaries primitives\n\nTVM supports dictionaries with non-fixed length keys that follow a prefix code structure, meaning no key is a prefix of another key. Learn more in the [TVM instruction](/tvm/instructions) section.\n\n#### `pfxdict_get?`\n\n```func\n(slice, slice, slice, int) pfxdict_get?(cell dict, int key_len, slice key) asm(key dict key_len) \"PFXDICTGETQ\" \"NULLSWAPIFNOT2\";\n```\n\nSearches for the unique prefix of a slice `key` in the prefix code dictionary `dict`. If found, returns `(s', x, s'', -1)`, where:\n\n- `s'` is the matching prefix of `s`,\n- `x` is the corresponding value (a slice),\n- `s''` is the remaining part of `s`,\n- `-1` indicates success.\n\nIf no matching prefix is found, returns `(null, null, s, 0)`, where `s` remains unchanged and `0` indicates failure.\n\n#### `pfxdict_set?`\n\n```func\n(cell, int) pfxdict_set?(cell dict, int key_len, slice key, slice value) asm(value key dict key_len) \"PFXDICTSET\";\n```\n\nWorks like `dict_set` but fails if the given key is a prefix of an existing key in dict. Returns a flag indicating success.\n\n#### `pfxdict_delete?`\n\n```func\n(cell, int) pfxdict_delete?(cell dict, int key_len, slice key) asm(key dict key_len) \"PFXDICTDEL\";\n```\n\nSimilar to `dict_delete?`.\n\n## Special primitives\n\n### `null`\n\n```func\nforall X -> X null() asm \"PUSHNULL\";\n```\n\nIn TVM, the `Null` type in FunC represents the absence of a value for any atomic type, meaning `null` can take on any atomic type.\n\n## `~impure_touch`\n\n```func\nforall X -> (X, ()) ~impure_touch(X x) impure asm \"NOP\";\n```\n\nMarks a variable as used, ensuring the code generated isn't removed during optimization, even if it's not impure. See [Impure specifier](/languages/func/functions#impure-specifier) section.\n\n## Other primitives\n\n### `min`\n\n```func\nint min(int x, int y) asm \"MIN\";\n```\n\nComputes the minimum of two integers `x` and `y`.\n\n### `max`\n\n```func\nint max(int x, int y) asm \"MAX\";\n```\n\nComputes the maximum of two integers `x` and `y`.\n\n### `minmax`\n\n```func\n(int, int) minmax(int x, int y) asm \"MINMAX\";\n```\n\nReturns `(min(x, y), max(x, y))`, sorting two integers.\n\n### `abs`\n\n```func\nint abs(int x) asm \"ABS\";\n```\n\nComputes the absolute value of `x`.\n\n[c7]: /tvm/overview\n"
  },
  {
    "path": "languages/func/types.mdx",
    "content": "---\ntitle: \"FunC types\"\nsidebarTitle: \"Types\"\nnoindex: \"true\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nFunC offers a range of built-in types covering all the types the TVM has. On the other hand, FunC has no custom user-defined types like records or classes.\n\n## Atomic types\n\nEach of these types occupies a single entry on the [TVM stack](/tvm/overview#tvm-state).\n\n|           |                                                                                                                                                                                                                                                                                 |\n| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `int`     | a 257-bit signed integer type. Overflow checks are enabled by default and trigger an exception.                                                                                                                                                                                 |\n| `cell`    | a [TVM cell type](/foundations/serialization/cells) for persistent data storage on TON Blockchain. Data is organized in a [bag of cells](/foundations/serialization/boc), with each cell containing up to 1023 bits of arbitrary data and up to four references to other cells. |\n| `slice`   | a read-only view of a cell that allows sequential access to its data and references. A cell can be converted into a slice, extracting stored bits and references without modifying the original cell.                                                                           |\n| `builder` | a mutable structure used to construct cells by adding data and references before finalizing them into a new cell.                                                                                                                                                               |\n| `tuple`   | an ordered collection of up to 255 elements, each capable of holding a value of any type.                                                                                                                                                                                       |\n| `cont`    | a [TVM continuation](/tvm/continuations) employed for execution flow management in [TVM instructions](/tvm/instructions).                                                                                                                                                       |\n\n### Special null value\n\nAny atomic type allows the special value `null` which represents the absence of an actual value of that type. For example, a function that searches the position of an integer in a list may return `null` to signify that it could not find the integer.\n\nThe `null` value can be obtained by calling the function [`null()`](/languages/func/stdlib#null). For example, in this snippet, an integer variable is declared and initialized with `null`:\n\n```func\nint a = null();   ;; a has value null\n```\n\nSince `null` is a valid value for any atomic type, keep the following in mind when working with functions:\n\n- Functions that return an atomic type may return `null`.\n- Functions that expect an atomic type as input could also accept `null`.\n- For [library functions](/languages/func/stdlib) specifications explicitly indicate when `null` is acceptable as a valid input or output.\n\nExample: [`cell_depth(cell c)`](/languages/func/stdlib#cell-depth) receives a `cell` as input, and its specification states that if the input cell is `null`, the function returns `0`.\n\n### No boolean type\n\nFunC does not have a boolean type. Instead, booleans are represented as integers:\n\n- `false` is `0`, `true` is `-1`, a 257-bit integer with all bits set to `1`.\n- Logical operations are performed using [bitwise operations](/languages/func/operators).\n- In [conditional statements](/languages/func/statements#conditional-statements), [loops](/languages/func/statements#loops), and [conditional expressions](/languages/func/operators#ternary%2C-%3F%3A) any nonzero integer is regarded as `true`.\n\n## Typed holes\n\nFunC supports type inference through the type holes: `_` and `var` serve as placeholders resolved during type checking; `_` is for functions, and `var` is for variables.\n\nExample:\n\n```func\nvar x = 2;\n```\n\nThe type checker determines that `x` is of type `int` since `2` is an `int`.\n\nAs another example, in the following function declaration:\n\n```func\n_ someFunction(int a) {\n  return a + 1;\n}\n```\n\nthe type checker infers that `_` has type `int`, as the return expression `a + 1` is of type `int`.\n\nSee [Function declarations](/languages/func/functions#function-declaration) for more details.\n\n## Composite types\n\nTo represent non-atomic, composite types, simpler types can be combined with the following three operations.\n\n### Function type\n\nA functional type is written in the form `A -> B`, where:\n\n- `A` is the input type, which is called domain.\n- `B` is the output type, which is called codomain.\n\nFor example, the type `int -> cell` represents a function that:\n\n- Takes an integer as input.\n- Returns a cell as output.\n\nLike in functional programming, it is possible to declare function types which have in their domain and codomain other function types. For example, `(int -> int) -> int` is a function with domain `int -> int` and codomain `int`. Similarly, `cell -> (slice -> slice)` is a function with domain `cell` and codomain `slice -> slice`\n\n### Tuple type\n\nTuple types in FunC are written in the form `[A, B, ...]` and represent TVM tuples with fixed length and known component types at compile time. A tuple occupies one entry on the TVM stack, even if it is a zero-length tuple.\n\nFor example, `[int, cell]` defines a tuple with exactly two elements:\n\n- The first element is an integer.\n- The second element is a cell.\n\nThe type `[]` represents an empty tuple. There is only one value of this type, the empty tuple, which is also written as `[]`.\n\n<Aside>\n  The empty tuple `[]` occupies one stack entry.\n</Aside>\n\n### Tensor type\n\nTensor types represent ordered collections of values and are written in the form `(A, B, ...)`. These types occupy multiple TVM stack entries, unlike atomic types, which use a single entry.\n\n**Example:**\n\nA function `foo` of type `int -> (int, int)` takes one integer as input and returns two integers as output, each one occupying a stack entry.\n\nExample call:\n\n```func\n(int a, int b) = foo(42);\n```\n\nInternally, the function consumes one stack entry and produces two.\n\n**Type representation:**\n\nValues `(2, (3, 9))` of type `(int, (int, int))` and `(2, 3, 9)` of type `(int, int, int)` are stored identically as three stack entries containing the values `2`, `3`, and `9`, respectively. However, FunC treats `(int, (int, int))` and `(int, int, int)` as distinct types. The following code **will not compile**:\n\n```func\n(int a, int b, int c) = (2, (3, 9));\n```\n\nHowever, this code will compile correctly:\n\n```func\n(int a, (int b, int c)) = (2, (3, 9));\n```\n\nFunC enforces strict type consistency, so only matching tensor structures are allowed.\n\n<Aside>\n  Exception: a type of the form `(A)` is considered by the type checker as the same type as `A`.\n</Aside>\n\n**Special case: unit type`()`**\n\nThe unit type `()` is used to indicate that:\n\n- A function does not return a value, or\n- A function takes no arguments\n\nThe unit type `()` has a single value, also written as `()`, occupying **zero** stack entries.\n\n**Examples**\n\n- `print_int` has the type `int -> ()`, meaning it takes an integer but returns nothing.\n- `random` has the type `() -> int`, meaning it takes no arguments but returns an integer.\n\n## Polymorphism with type variables\n\nFunC supports [polymorphic functions](https://en.wikipedia.org/wiki/Parametric_polymorphism).\n\nExample:\n\n```func\nforall X -> (X, X) duplicate(X value) {\n  return (value, value);\n}\n```\n\nHere, `X` is a type variable that allows the function to operate on values of any type. Type variables are declared between `forall` and `->`.\n\nThe function receives a value of type `X`, and duplicates this value to return a value of type `(X, X)`.\n\nFor example,\n\n- Calling `duplicate(6)` produces `(6, 6)`.\n- Calling `duplicate([])` produces two copies of an empty tuple: `([], [])`.\n\n<Aside>\n  Type variables in polymorphic functions cannot be instantiated with tensor types. The only exception is a tensor of a single element `(a)`, where `a` is not a tensor type itself. The compiler treats `(a)` as equivalent to `a`.\n</Aside>\n\nFor more details, see the [Polymorphism with forall](/languages/func/functions#polymorphism-with-forall) section.\n\n## User-defined types\n\nFunC does not support defining custom types beyond the type constructions described above.\n\n## Type width\n\nEvery value in FunC occupies a certain number of stack entries. If this number is consistent for all values of a given type, it is called the **type width**.\n\nFor example, all [atomic types](#atomic-types) have a type width of 1, because all their values occupy a single stack entry. The tensor type `(int, int)` has type width 2, because all its values occupy 2 stack entries.\n"
  },
  {
    "path": "languages/tact.mdx",
    "content": "---\ntitle: \"Tact language\"\nsidebarTitle: \"Tact\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside>\n  The official language of TON Blockchain is [Tolk](/languages/tolk), and all other languages are deemed **legacy**. They are not necessarily outdated or deprecated, so you can still use them and contribute to their development, tooling, or documentation.\n</Aside>\n\nTact is a fresh programming language for TON Blockchain, focused on efficiency and ease of development. It is a good fit for complex smart contracts, quick onboarding and rapid prototyping.\n\nDeveloped by [TON Studio](https://tonstudio.io), powered by the community — at the start of 2025, the number of _unique code_[^1] contracts deployed on the mainnet reached almost 28 thousand, of which about 33% were written in Tact. You can view some selected projects here: [Tact in production](#tact-in-production).\n\n[^1]: The \"unique code\" means that each contract in the data sample has at least one TVM instruction that differs from the other contracts, excluding many preprocessed wallets with everything inlined — even seqno and a public key for signature verification!\n\nTact has undergone a comprehensive security audit by [Trail of Bits](https://www.trailofbits.com), a leading Web3 security firm.\n\n<Columns cols={3}>\n  <Card\n    title=\"Try it online!\"\n    arrow=\"true\"\n    href=\"https://ide.ton.org/\"\n  />\n\n  <Card\n    title=\"Tact documentation\"\n    arrow=\"true\"\n    href=\"https://docs.tact-lang.org/\"\n  />\n\n  <Card\n    title=\"Awesome Tact\"\n    arrow=\"true\"\n    href=\"https://github.com/tact-lang/awesome-tact\"\n  />\n</Columns>\n\n## Features\n\nThe most prominent and distinctive features of Tact are:\n\n- Familiar and user-friendly TypeScript-like syntax.\n- Strong static type system with built-in [Structs], [Messages], and [maps], among others.\n- First-class [maps] support, with many methods and a convenient [`foreach` statement][foreach] for traversing.\n- Automatic (de)serialization of incoming messages and data structures.\n- Automatic routing of [internal, external, and bounced messages][recvfun].\n- Automatic handling of message types, including [binary, text, and fallback slices][recv].\n- No boilerplate functions for [sending messages] and deploying child contracts.\n- Reusable behaviors through [traits].\n- Support for low-level programming with [`asm` functions][asmfun].\n- Generation of [single-file TypeScript wrappers] for convenient interactions with compiled contracts, which include:\n  - Type definitions for [Structs] and [Messages] are observable in the [compilation report].\n  - Corresponding `storeStructureName()` and `loadStructureName()` functions for (de)serialization.\n  - All global and contract-level constants.\n  - Bi-directional records of exit codes: from their names to numbers and vice versa.\n  - Opcodes of all [Messages].\n  - A contract wrapper class with various helper functions for initialization, deployment, and message exchange.\n- Rich [standard library][stdlib].\n- Extensive [documentation].\n- Robust [tooling](#tooling).\n- ...and there's much more to come!\n\n[Structs]: https://docs.tact-lang.org/book/structs-and-messages#structs\n[Messages]: https://docs.tact-lang.org/book/structs-and-messages#messages\n[maps]: https://docs.tact-lang.org/book/maps\n[foreach]: https://docs.tact-lang.org/book/statements#foreach-loop\n[recv]: https://docs.tact-lang.org/book/receive/\n[recvfun]: https://docs.tact-lang.org/book/contracts/#receiver-functions\n[sending messages]: https://docs.tact-lang.org/book/send/#message-sending-functions\n[traits]: https://docs.tact-lang.org/book/types/#traits\n[asmfun]: https://docs.tact-lang.org/book/assembly-functions/\n[single-file TypeScript wrappers]: https://docs.tact-lang.org/book/compile/#wrap\n[compilation report]: https://docs.tact-lang.org/book/compile/#report\n[stdlib]: https://docs.tact-lang.org/ref/\n[documentation]: https://docs.tact-lang.org/\n\n## Security\n\n- [Security audit of Tact by the Trail of Bits (2025, PDF)](https://github.com/trailofbits/publications/blob/master/reviews/2025-01-ton-studio-tact-compiler-securityreview.pdf)\n  - Backup link: [PDF Report](https://github.com/tact-lang/website/blob/416073ed4056034639de257cb1e2815227f497cb/pdfs/2025-01-ton-studio-tact-compiler-securityreview.pdf)\n\n## Tact in production\n\nSome selected software and applications based on contracts written in Tact, deployed in production, and consumed by end users:\n\n###### Open source or source available\n\n- [Proof-of-capital](https://github.com/proof-of-capital/TON) - [proof-of-capital](https://proofofcapital.org/) is a market-making smart contract that protects the interests of all holders.\n  - See the [security audit report](https://raw.githubusercontent.com/nowarp/public-reports/master/2025-01-proof-of-capital.pdf) by [Nowarp](https://nowarp.io).\n\n###### Closed source\n\n- [Tradoor](https://tradoor.io) - Fast and social DEX on TON.\n  - See the [security audit report](https://www.tonbit.xyz/reports/Tradoor-Smart-Contract-Audit-Report-Summary.pdf) by TonBit.\n- [PixelSwap](https://www.pixelswap.io) - First modular and upgradeable DEX on TON.\n  - See the [security audit report](https://github.com/trailofbits/publications/blob/master/reviews/2024-12-pixelswap-dex-securityreview.pdf) by Trail of Bits.\n- [GasPump](https://gaspump.tg) - TON memecoin launchpad and trading platform.\n\nSee [Tact in production](https://github.com/tact-lang/awesome-tact#tact-in-production-) on the Awesome Tact list.\n\n## Installation\n\n### Compiler\n\nThe Tact compiler is distributed as an [NPM package](https://www.npmjs.com/package/@tact-lang/compiler) bundled with the [Tact standard library](https://docs.tact-lang.org/ref/).\n\nThe recommended Node.js version is 22 or higher, while the minimum version is 18.\n\nUse your favorite package manager to install it into a Node.js project:\n\n```bash\n# yarn is recommended, but not required\nyarn add @tact-lang/compiler\n\n# you can also use npm\nnpm i @tact-lang/compiler@latest\n\n# or pnpm\npnpm add @tact-lang/compiler\n\n# or bun\nbun add @tact-lang/compiler\n```\n\nAlternatively, you can install it globally as such:\n\n```bash\nnpm i -g @tact-lang/compiler\n```\n\nIt will make the `tact` compiler available on your PATH, as well as:\n\n- a convenient `unboc` disassembler of a contract's code compiled into a [bag of cells](/foundations/serialization/boc) `.boc` format.\n- a formatter `tact-fmt`, which can format or check the formatting of individual Tact files and directories.\n\n### Tooling\n\n###### Extensions and plugins\n\n- [VS Code extension](https://marketplace.visualstudio.com/items?itemName=tonstudio.vscode-tact) - powerful and feature-rich extension for Visual Studio Code (VSCode) and VSCode-based editors like VSCodium, Cursor, Windsurf, and others.\n  - Get it on the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=tonstudio.vscode-tact).\n  - Get it on the [Open VSX Registry](https://open-vsx.org/extension/tonstudio/vscode-tact).\n  - Or install from the [`.vsix` files in nightly releases](https://github.com/tact-lang/tact-language-server/releases).\n- [JetBrains IDEs plugin](https://plugins.jetbrains.com/plugin/27290-tact#) - provides syntax highlighting, code navigation, and more.\n- [Language Server (LSP Server)](https://github.com/tact-lang/tact-language-server) - supports Sublime Text, (Neo)Vim, Helix, and other editors with LSP support.\n- [tact.vim](https://github.com/tact-lang/tact.vim) - Vim 8+ plugin.\n- [tact-sublime](https://github.com/tact-lang/tact-sublime) - Sublime Text 4 package.\n  - Get it on the [Package Control](https://packagecontrol.io/packages/Tact).\n\n###### Security\n\n- [Misti](https://github.com/nowarp/misti) - Static smart contract analyzer.\n- [TON Symbolic Analyzer (TSA)](https://github.com/espritoxyz/tsa) - Static smart contract analysis tool based on symbolic execution.\n\n###### Utility\n\n- Formatter (`tact-fmt`) — The official formatter. It ships with the Tact Language Server, VS Code extension, and as a standalone binary with the compiler. You can invoke it by running `npx tact-fmt` in your Tact projects.\n- BoC Disassembler (`unboc`) — Disassembler for [`.boc`](/foundations/serialization/boc) files. Ships as a standalone binary with the compiler. You can invoke it by running `npx unboc` in your Tact projects.\n\n### Getting started\n\nFor a quick start, read the [\"Let's start!\"](https://docs.tact-lang.org/#start) mini-guide in the Tact documentation. It uses the [Blueprint](https://github.com/ton-community/blueprint) development environment for writing, testing, and deploying smart contracts on TON Blockchain.\n\nIf you want more manual control, use [tact-template](https://github.com/tact-lang/tact-template). It's a ready-to-use template with the development environment set up, including the Tact compiler with TypeScript + Jest, a local TON emulator, AI-based editor support, and examples of how to run tests.\n\n```shell\ngit clone --depth 1 https://github.com/tact-lang/tact-template\n```\n\n## Community\n\nIf you can’t find the answer in the [docs](https://docs.tact-lang.org), or you’ve tried to do some local testing and it still didn’t help, don’t hesitate to reach out to Tact’s flourishing community:\n\n- [`@tactlang` on Telegram](https://t.me/tactlang) - Main community chat and discussion group.\n- [`@tactlang_ru` on Telegram](https://t.me/tactlang_ru) _(Russian)_\n- [`@tact_kitchen` on Telegram](https://t.me/tact_kitchen) - Channel with updates from the team.\n- [`@tact_language` on X/Twitter](https://x.com/tact_language)\n- [`tact-lang` organization on GitHub](https://github.com/tact-lang)\n- [`@ton_studio` on Telegram](https://t.me/ton_studio)\n- [`@thetonstudio` on X/Twitter](https://x.com/thetonstudio)\n\n## Contributing\n\nContributions are welcome! To help develop the compiler, see the [contributing guide](https://github.com/tact-lang/tact/blob/main/dev-docs/CONTRIBUTING.md).\n"
  },
  {
    "path": "languages/tl-b/complex-and-non-trivial-examples.mdx",
    "content": "---\ntitle: \"Complex and non-trivial examples\"\n---\n\n## Unary\n\nThe **unary** functional type is commonly used for dynamic sizing in structures such as [`hml_short`](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb#L29).\n\nUnary supports two main options:\n\n```tlb\nunary_zero$0 = Unary ~0;\nunary_succ$1 {n:#} x:(Unary ~n) = Unary ~(n + 1);\n```\n\nThe `unary_zero` variation is straightforward: if the first bit is `0`, the result of the entire unary deserialization is `0`.\n\nThe `unary_succ` variation, however, is more complex: it is loaded recursively and represents a value of `~(n + 1)`. This means it repeatedly calls itself until it reaches `unary_zero`. In other words, the desired value will equal the number of units in a row.\n\nFor example, consider the serialization of the bitstring `110`.\nThe deserialization call chain is as follows:\n\n```tlb\nunary_succ$1 -> unary_succ$1 -> unary_zero$0\n```\n\nOnce `unary_zero` is reached, the value is returned up the call stack, similar to how values are returned in a recursive function.\n\nTo better visualize the result, let's trace the return path:\n\n`0 -> ~(0 + 1) -> ~(1 + 1) -> 2`\n\nThis shows that the bitstring `110` corresponds to `Unary 2`.\n\n{/*## Snake\n\n  The **Snake** functional type is used to store sequences of bits with a length that is not predetermined. It is often employed in transactions with long comments.\n\n  ```tlb\n  empty#_ b:bits = Snake ~0;\n  cons#_ {n:#} b:bits next:^(Snake ~n) = Snake ~(n + 1);\n  ```\n\n  In this scenario, serialization continues until all links are assembled.\n\n  The `empty` variation just deserializes a string of bits and ends the process if there are no references to other cells.\n\n  The `cons` variation deserializes a string of bits and then follows a reference to another cell, continuing the process until it reaches the `empty` variation.\n  The number of such recursive calls determines the final size of `n`.\n\n  Consider the following tree of cells:\n  ```\n  1[1] -> {\n  2[00] -> {\n    7[1001000] -> {\n      25[1010000010000001100001001]\n    }\n  }\n  }\n  ```\n\n  In this example, the first cell contains a reference. So, `1` is read and then the reference is opened according to `cons` constructor.\n  Next, the `00` is read, and then the next reference is opened. This process continues until there are no links in the next cell. The next two bits, `00`, are part of the `b:bits` field. The remaining bits in this cell are used for the reference to the next cell.\n  */}\n\n## Hashmap\n\nThe Hashmap complex type is used to store dictionaries from FunC smart contract code, i.e., `dict`.\n\nWe need a support structure:\n\n```tlb\nbit$_ (## 1) = Bit;\n```\n\nThe following TL-B structures are used to serialize a Hashmap with a fixed key length:\n\n```tlb\nhm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l n)\n          {n = (~m) + l} node:(HashmapNode m X) = Hashmap n X;\n\nhmn_leaf#_ {X:Type} value:X = HashmapNode 0 X;\nhmn_fork#_ {n:#} {X:Type} left:^(Hashmap n X)\n           right:^(Hashmap n X) = HashmapNode (n + 1) X;\n\nhml_short$0 {m:#} {n:#} len:(Unary ~n) {n <= m} s:(n * Bit) = HmLabel ~n m;\nhml_long$10 {m:#} n:(#<= m) s:(n * Bit) = HmLabel ~n m;\nhml_same$11 {m:#} v:Bit n:(#<= m) = HmLabel ~n m;\n\nunary_zero$0 = Unary ~0;\nunary_succ$1 {n:#} x:(Unary ~n) = Unary ~(n + 1);\n\nhme_empty$0 {n:#} {X:Type} = HashmapE n X;\nhme_root$1 {n:#} {X:Type} root:^(Hashmap n X) = HashmapE n X;\n```\n\nThis root structure is `HashmapE n X` that can be in one of the two possible states: either `hme_empty` or `hme_root`.\n\n### Hashmap parsing example\n\nAs an example, consider the following cell, represented in binary form:\n\n```\n[1] -> {\n  [00] -> {\n    [1001000] -> {\n      [1010000010000001100001001],\n      [1010000010000000001101111]\n    },\n    [1011100000000000001100001001]\n  }\n}\n```\n\nThis cell uses the `HashmapE` structure with an 8-bit key size, and its values are represented using the `uint16` type—that is, `HashmapE 8 uint16`.\n\nThe `HashmapE` structure utilizes three distinct key types:\n\n```\n1 = 777\n17 = 111\n128 = 777\n```\n\nTo parse this Hashmap, we must first determine which structure type to use: either `hme_empty` or `hme_root`. This is decided by identifying the `correct prefix`. The `hme_empty` variation is indicated by a single bit `0` (`hme_empty$0`), while the `hme_root` variation is indicated by a single bit `1` (`hme_root$1`). After reading the first bit, if it is `1` (`1[1]`), we know it is the `hme_root` variation.\n\nNext, we can populate the structure variables with known values. The initial result is:\n\n`hme_root$1 {n:#} {X:Type} root:^(Hashmap 8 uint16) = HashmapE 8 uint16;`\n\nHere, the one-bit prefix is already read. The curly braces `{}` indicate conditions that need not be read. Specifically:\n\n- `{n:#}` indicates that `n` is any `uint32` number.\n- `{X:Type}` means that `X` can be any type.\n\nThe next portion to read is `root:^(Hashmap 8 uint16)`, where the `^` symbol denotes a link that must be loaded.\n\n```\n[00] -> {\n    [1001000] -> {\n      [1010000010000001100001001],\n      [1010000010000000001101111]\n    },\n    [1011100000000000001100001001]\n  }\n```\n\n#### Initiating branch parsing\n\nAccording to our schema, this is the correct `Hashmap 8 uint16` structure. Next, we populate it with known values, resulting in the following:\n\n```tlb\nhm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l 8)\n          {8 = (~m) + l} node:(HashmapNode m uint16) = Hashmap 8 uint16;\n```\n\nAs shown above, conditional variables `{l:#}` and `{m:#}` have appeared, but both values are unknown at this stage. After reading the corresponding `label`, we can deduce that `n` is part of the equation `{n = (~m) + l}`. This means we must calculate both `l` and `m`, where the sign indicates the resulting value of `~`.\n\nTo determine the value of `l`, we need to load the `label:(HmLabel ~l uint16)` sequence. Below, we outline the 3 basic structural options for `HmLabel`:\n\n```tlb\nhml_short$0 {m:#} {n:#} len:(Unary ~n) {n <= m} s:(n * Bit) = HmLabel ~n m;\nhml_long$10 {m:#} n:(#<= m) s:(n * Bit) = HmLabel ~n m;\nhml_same$11 {m:#} v:Bit n:(#<= m) = HmLabel ~n m;\n```\n\nEach option is determined by its corresponding prefix. Our root cell comprises 2 zero bits, displayed as (`2[00]`). Therefore, the only logical option is `hml_short$0`, which starts with a prefix of `0`.\n\nNext, let's fill in the `hml_short` structure with known values:\n\n```tlb\nhml_short$0 {m:#} {n:#} len:(Unary ~n) {n <= 8} s:(n * Bit) = HmLabel ~n 8\n```\n\nAt this point, we don't know the value of `n`. However, since it includes a `~` character, we can calculate it. To do so, we load `len:(Unary ~n)`;  [more about unary here](#unary).\n\nStarting with `2[00]`, only one bit remains after defining the `HmLabel` type.\n\nWe load this final bit and observe that its value is `0`, which indicates that the `unary_zero$0` variation is used. This means that the `n` value for the `HmLabel` variation is zero.\n\nNow, we can complete the `hml_short` structure by using the calculated `n` value:\n\n```tlb\nhml_short$0 {m:#} {n:#} len:0 {n <= 8} s:(0 * Bit) = HmLabel 0 8\n```\n\nWe have an empty `HmLabel`, denoted by `s = 0`, which means there is nothing to load.\n\nNext, we complete our structure by incorporating the calculated value of `l`, as follows:\n\n```tlb\nhm_edge#_ {n:#} {X:Type} {l:0} {m:#} label:(HmLabel 0 8)\n          {8 = (~m) + 0} node:(HashmapNode m uint16) = Hashmap 8 uint16;\n```\n\nNow that we have calculated the value of `l`, we can also calculate `m` using the equation `n = (~m) + 0`, which simplifies to `m = n - 0`. Therefore, `m = n = 8`.\n\nWith all unknown values determined, we can load the `node:(HashmapNode 8 uint16)`.\n\nRegarding the HashmapNode, we have several options:\n\n```tlb\nhmn_leaf#_ {X:Type} value:X = HashmapNode 0 X;\nhmn_fork#_ {n:#} {X:Type} left:^(Hashmap n X)\n           right:^(Hashmap n X) = HashmapNode (n + 1) X;\n```\n\nIn this case, we determine the option not by using the prefix but by examining the parameter. Specifically, if `n = 0`, the correct result will be either `hmn_leaf` or `hmn_fork`.\nSince, in this example, `n = 8`, we use the `hmn_fork` variation. Now, we can fill in the known values as follows:\n\n```tlb\nhmn_fork#_ {n:#} {X:uint16} left:^(Hashmap n uint16)\n           right:^(Hashmap n uint16) = HashmapNode (n + 1) uint16;\n```\n\nAfter entering the known values, we must calculate the `HashmapNode (n + 1) uint16`. This means that the resulting value of `n` must be equal to our parameter, i.e., 8. To calculate the local value of `n`, we use the following formula:\n\n`n = (n_local + 1)` -> `n_local = (n - 1)` -> `n_local = (8 - 1)` -> `n_local = 7`.\n\n```tlb\nhmn_fork#_ {n:#} {X:uint16} left:^(Hashmap 7 uint16)\n           right:^(Hashmap 7 uint16) = HashmapNode (7 + 1) uint16;\n```\n\nNow that we know the formula, obtaining the final result is straightforward.\nNext, we load the left and right branches, and for each subsequent branch, [the process is repeated](#initiating-branch-parsing).\n\n#### Analyzing loaded hashmap values\n\nContinuing the previous example, let's examine how loading branches work for dictionary values. For instance, given the bitstring: `28[1011100000000000001100001001]`.\n\nThe result is once again `hm_edge`, and the next step is to fill in the sequence with the correct known values as follows:\n\n```tlb\nhm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l 7)\n          {7 = (~m) + l} node:(HashmapNode m uint16) = Hashmap 7 uint16;\n```\n\nNext, the `HmLabel` response is loaded using the `HmLabel` variation, as the prefix is `10`.\n\n```tlb\nhml_long$10 {m:#} n:(#<= m) s:(n * Bit) = HmLabel ~n m;\n```\n\nNow, let's fill in the sequence:\n\n```tlb\nhml_long$10 {m:#} n:(#<= 7) s:(n * Bit) = HmLabel ~n 7;\n```\n\nThe new construction, `n:(#<= 7)`, clearly denotes a sizing value that corresponds to the number 7, which is, in fact, the `log2` of the number `+ 1`. For simplicity, however, we can count the number of bits required to represent the number 7.\nIn binary, the number 7 is written as `111`, which means 3 bits are needed. Therefore, the value for `n = 3`.\n\n```tlb\nhml_long$10 {m:#} n:(## 3) s:(n * Bit) = HmLabel ~n 7;\n```\n\nNext, we load `n` into the sequence, which results in `111`. As noted earlier, this coincidentally equals 7. Then, we load `s` into the sequence, which consists of 7 bits: `0000000`. Remember, `s` is part of the key.\n\nAfterward, we return to the top of the sequence and fill in the resulting `l`:\n\n```tlb\nhm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel 7 7)\n          {7 = (~m) + 7} node:(HashmapNode m uint16) = Hashmap 7 uint16;\n```\n\nThen we calculate the value of `m`: `m = 7 - 7`, which gives us `m = 0`.\nSince `m = 0`, the structure is ideally suited for use with a `HashmapNode`:\n\n```tlb\nhmn_leaf#_ {X:Type} value:X = HashmapNode 0 X;\n```\n\nNext, we substitute our `uint16` type and load the value. When converted to decimal, the remaining 16 bits, `0000001100001001`, give us the value `777`.\n\nNow, let's restore the key. We need to combine all the parts of the key that were computed previously. Each related key part is combined with one bit, depending on the branch type used. A `1` bit is added for the right branch, and a `0` bit is added for the left branch. If a full `HmLabel` exists above, its bits are added to the key.\n\nIn this specific case, 7 bits are taken from the `HmLabel 0000000`, and a `1` bit is added before the sequence of zeros because the value was obtained from the right branch. The final result is 8 bits, or `10000000`, which means the key value equals `128`.\n\n## Other hashmap types\n\nNow that we have discussed hashmaps and how to load the standardized Hashmap type, let's explain how the additional hashmap types function.\n\n### HashmapAugE\n\n```tlb\nahm_edge#_ {n:#} {X:Type} {Y:Type} {l:#} {m:#}\n  label:(HmLabel ~l n) {n = (~m) + l}\n  node:(HashmapAugNode m X Y) = HashmapAug n X Y;\n\nahmn_leaf#_ {X:Type} {Y:Type} extra:Y value:X = HashmapAugNode 0 X Y;\n\nahmn_fork#_ {n:#} {X:Type} {Y:Type} left:^(HashmapAug n X Y)\n  right:^(HashmapAug n X Y) extra:Y = HashmapAugNode (n + 1) X Y;\n\nahme_empty$0 {n:#} {X:Type} {Y:Type} extra:Y\n          = HashmapAugE n X Y;\n\nahme_root$1 {n:#} {X:Type} {Y:Type} root:^(HashmapAug n X Y)\n  extra:Y = HashmapAugE n X Y;\n```\n\nThe primary distinction between the `HashmapAugE` and the regular `Hashmap` is the presence of an `extra:Y` field in each node (not just in leaf nodes containing values).\n\n### PfxHashmap\n\n```tlb\nphm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l n)\n           {n = (~m) + l} node:(PfxHashmapNode m X)\n           = PfxHashmap n X;\n\nphmn_leaf$0 {n:#} {X:Type} value:X = PfxHashmapNode n X;\nphmn_fork$1 {n:#} {X:Type} left:^(PfxHashmap n X)\n            right:^(PfxHashmap n X) = PfxHashmapNode (n + 1) X;\n\nphme_empty$0 {n:#} {X:Type} = PfxHashmapE n X;\nphme_root$1 {n:#} {X:Type} root:^(PfxHashmap n X)\n            = PfxHashmapE n X;\n```\n\nThe key difference between the `PfxHashmap` and the regular `Hashmap` lies in its ability to store keys of varying lengths due to the inclusion of the `phmn_leaf$0` and `phmn_fork$1` nodes.\n\n### VarHashmap\n\n```tlb\nvhm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l n)\n           {n = (~m) + l} node:(VarHashmapNode m X)\n           = VarHashmap n X;\nvhmn_leaf$00 {n:#} {X:Type} value:X = VarHashmapNode n X;\nvhmn_fork$01 {n:#} {X:Type} left:^(VarHashmap n X)\n             right:^(VarHashmap n X) value:(Maybe X)\n             = VarHashmapNode (n + 1) X;\nvhmn_cont$1 {n:#} {X:Type} branch:Bit child:^(VarHashmap n X)\n            value:X = VarHashmapNode (n + 1) X;\n\n// nothing$0 {X:Type} = Maybe X;\n// just$1 {X:Type} value:X = Maybe X;\n\nvhme_empty$0 {n:#} {X:Type} = VarHashmapE n X;\nvhme_root$1 {n:#} {X:Type} root:^(VarHashmap n X)\n            = VarHashmapE n X;\n```\n\nSimilarly, the main difference between the `VarHashmap` and the regular `Hashmap` is its ability to accommodate different key lengths, attributed to the presence of the `vhmn_leaf$00` and `vhmn_fork$01` nodes. Additionally, the `VarHashmap` can form a common value prefix (child map) by utilizing the `vhmn_cont$1` node.\n\n## BinTree\n\n```tlb\nbta_leaf$0 {X:Type} {Y:Type} extra:Y leaf:X = BinTreeAug X Y;\nbta_fork$1 {X:Type} {Y:Type} left:^(BinTreeAug X Y)\n           right:^(BinTreeAug X Y) extra:Y = BinTreeAug X Y;\n```\n\nThe binary tree key generation mechanism operates similarly to the standardized Hashmap framework but without using labels; instead, it relies on branch prefixes.\n\n## VmTuple\n\n```tlb\nvm_tupref_nil$_ = VmTupleRef 0;\nvm_tupref_single$_ entry:^VmStackValue = VmTupleRef 1;\nvm_tupref_any$_ {n:#} ref:^(VmTuple (n + 2)) = VmTupleRef (n + 2);\nvm_tuple_nil$_ = VmTuple 0;\nvm_tuple_tcons$_ {n:#} head:(VmTupleRef n) tail:^VmStackValue = VmTuple (n + 1);\nvm_stk_tuple#07 len:(## 16) data:(VmTuple len) = VmStackValue;\n```\n\nTuple is an _actual_ tuple of elements that is written in FunC as `[a, b, c]`. VmTuple is used internally in [VmStack](https://github.com/ton-blockchain/ton/blob/05bea13375448a401d8e07c6132b7f709f5e3a32/crypto/block/block.tlb#L862)\nfor tuple serialization, which is outputted from a contract's methods.\n\nLet's consider a serialization of the following tuple: \\[44, `Cell{00B5BD3EB0}`, -1].\nWhen disassembled, it looks as follows:\n\n```\n[070003] -> {\n   [] -> {\n      [01000000000000002C],\n      [03] -> {\n         [00B5BD3EB0]\n      }\n   },\n   [01FFFFFFFFFFFFFFFF]\n}\n```\n\nThe root cell will be parsed using the constructor `vm_stk_tuple`, since its prefix is `0x07`. The next 2 bytes are `len:(## 16)` that equals `0003 == 3`.\n\nNext comes `data:(VmTuple 3)`. There are two variants of parsing of `VmTuple`: `VmTuple (n + 1)` and  `VmTuple 0`. Since `n > 0`, `VmTuple (n + 1)` is used.\n\nThe first field is `head:(VmTupleRef 2=(3-1))`. There are three variants of parsing: `0`, `1`, and `n+2`. Our `n` equals `2`, so the third variant is used.\n\nThe only field is `ref:^(VmTuple (n + 2))`, i.e. `ref:^(VmTuple 2)`.\n\nOur `n` equals `2`, so the variant `(n + 1)` is chosen. Next read `head:(VmTupleRef n)` -> `head:(VmTupleRef 1=(2-1))`. In `VmTupleRef 1`, there is only one field: `entry:^VmStackValue`.\nEssentially, this field is the value,`01 000000000000002C`.\n\nWe read the `head` and reached the end, now we go in the opposite direction and read the `tail:^VmStackValue`. Going up, the first tail is `03` with a link to the cell.\n`0x03` on the stack means a cell; we just read this link and save it as the value,`00B5BD3EB0`. Then go up a level and read another `tail`, this is `01 FFFFFFFFFFFFFFFF`, i.e., int equal to `-1`.\n\nAfter we have reached the end, the parsing is completed, and we add all the received elements into the array in the order in which we received them.\n\n## References\n\n[Link to the original article](https://github.com/xssnick/ton-deep-doc/blob/master/TL-B.md) - _Oleg Baranov._\n"
  },
  {
    "path": "languages/tl-b/overview.mdx",
    "content": "---\ntitle: \"Overview\"\n---\n\nThe _Type Language Binary (TL-B)_ for TON Blockchain is a domain-specific language designed to describe the structure of data in the TON Blockchain.\n\nIt is used to define how data is serialized and deserialized, ensuring consistency and interoperability across different components of the TON ecosystem.\n\nSpecial _TL-B parsers_ can read schemes to deserialize binary data into different objects.\n\nIn fact, TL-B is a variant of the original [Type Language (TL)](https://core.telegram.org/mtproto/TL) developed for the [Telegram Messenger](https://telegram.org/?setln=en) and adapted to the specific needs of the TON Blockchain.\n\nIt is recommended to start by studying the [syntax and semantics of TL-B](/languages/tl-b/syntax-and-semantics), simultaneously exploring each example through a convenient [TL-B online editor](https://ton-community.github.io/tlb-editor/#/main). To further your understanding, we recommend referring to [the page](/languages/tl-b/complex-and-non-trivial-examples) that describes the most complex examples of TL-B schemes.\n"
  },
  {
    "path": "languages/tl-b/simple-examples.mdx",
    "content": "---\ntitle: \"Simple examples\"\n---\n\n## Maybe\n\n```tlb\nnothing$0 {X:Type} = Maybe X;\njust$1 {X:Type} value:X = Maybe X;\n```\n\nThe `Maybe` combinator is used to represent optional values. In this case, the first bit indicates a value. If the bit is `0`, the value is not serialized and skipped. If the bit is `1`, the value follows and is serialized.\n\n## Either\n\n```tlb\nleft$0 {X:Type} {Y:Type} value:X = Either X Y;\nright$1 {X:Type} {Y:Type} value:Y = Either X Y;\n```\n\nThe `Either` type is used when one of two possible result types may be present. The choice of type depends on the prefix bit. If the prefix bit is `0`, then the left type is serialized. If it is `1`, the right type is serialized.\n\nThis construct is used, for example, when serializing messages, where the body is either included directly in the main cell or stored in a separate referenced cell.\n\n## Both\n\n```tlb\npair$_ {X:Type} {Y:Type} first:X second:Y = Both X Y;\n```\n\nThe `Both` type variation is used exclusively with regular pairs, where both types are serialized sequentially without any conditions.\n\n## VarUInteger n\n\n```tlb\nvar_uint$_ {n:#} len:(#< n) value:(uint (len * 8)) = VarUInteger n;\n```\n\nThe combinator is parameterized by a natural number `n`, represented in curly brackets. For a given `n`, `VarUInteger n` describes the serialization of a natural number `m`, which in its binary representation contains no more than `(n - 1) * 8` bits.\n\nFirst, the number of bytes required for writing `m`, that is called `len`, is serialized into $\\lceil \\log_{2}n \\rceil$ bits as an unsigned big-endian integer. Then `m` itself is serialized as a `uint` on `len*8` bits. Thus, the size of the serialization of a particular `m` through the combinator `VarUInteger n` depends on `m`.\n\nFor example, `VarUInteger 32` is used to represent the amount of a certain extra currency on an account. We can store in that type values up to `2**248 - 1`. Let's serialize the `value = 27583` according to that type.\n\nThe binary representation of `value` is `110101110111111`. It requires `15` bits to write it as an unsigned integer, so we need `len = 2` bytes. The `len` is serialized as `00010` (into $\\lceil \\log_{2} 32 \\rceil = 5$ bits). Then, the `value` is serialized as `0110101110111111` into `len * 8 = 16` bits. Thus, the complete serialization of `27583` through `VarUInteger 32` type description is `00010 0110101110111111`.\n\nAnother important example is `VarUInteger 16`, which is used to represent account's balance. We can store in that type values up to `2**120 - 1`. According to that type, the `value = 27583` will be serialized as `0010 0110101110111111`, because `len = 2` is serialized into $\\lceil \\log_{2} 16 \\rceil = 4$ bits.\n"
  },
  {
    "path": "languages/tl-b/syntax-and-semantics.mdx",
    "content": "---\ntitle: \"Syntax and semantics\"\n---\n\nimport { Image } from '/snippets/image.jsx';\n\n## Syntax\n\nEach line of a TL-B file is either a TL-B scheme (i.e., type declaration), a comment, or a blank line.\n\n### TL-B Scheme\n\nThe TL-B scheme describes how to serialize a certain algebraic data structure into a binary format. Here are some examples:\n\n<Image\n  src=\"/resources/images/tlb-scheme.png\"\n  darkSrc=\"/resources/images/tlb-scheme-dark.png\"\n  alt=\"General syntax of TL-B schemas\"\n/>\n\nIn general, each TL-B scheme has the following structure:\n\n- **Constructor** that consists of\n  - optional constructor name;\n  - tag: empty, `$` or `#`;\n  - prefix code or `_`.\n\n```tlb\nbool_true$1;\ntransfer#5fcc3d14;\nsome#_;\n_#_.\n```\n\n- **Fields definitions**, each of which consists of\n  - optional field name (`ident`);\n  - type expression (type-expr).\n\n```tlb\nval:(## 32);\nsrc:MsgAddressInt;\n```\n\n- **Constraints**: optional expressions that restrict values which are instances of the `Nat` type.\n\n```tlb\n{ n <= 100 };\n{ ~b = a + 10 };\n{ anycast = 0 };\n{ b >= c }.\n```\n\n- **Parameters declarations**: declare fields of types `#` (natural numbers) or `Type` (types of types) that may be used as parameters for parameterized types.\n  Always framed by curly `{}` brackets.\n\n```tlb\n_ {x:#} my_val:(## x) = A x;\n_ {X:Type} my_val:(## 32) next_val:X = A X;\n```\n\n- **Combinator name**: the right side of the TL-B scheme that represents the name of the defined combinator. Could be parameterized.\n\n```tlb\n... = MsgAddrSmpl;\n// parameterized combinators\n... = Maybe X;\n... = Hashmap n X.\n```\n\n### Comments\n\nThe comments follow the same conventions as in C++.\n\n```\n/*\nThis is\na comment\n*/\n\n// This is a single-line comment\n```\n\n## Semantics\n\nFrom a high-level perspective, the **right-hand side** of each _scheme_ is a type, either simple (such as `Bit` or `True`) or parametrized (such as `Hashmap n X`) and\nthe **left-hand side** describes a way to define, or even to serialize, a value of the type indicated in the right-hand side.\n\nBelow, we gradually describe each component of TL-B schemes.\n\n### Constructors\n\nConstructors define a combinator's type, including its state during serialization. Each constructor begins with the (possibly empty `_`) string name,\nsuch as a `message` or `bool_true`, immediately followed by an optional constructor tag, such as `#_` or `$10`, which describes the\nbitstring used to encode (serialize) the constructor in question.\n\nTags may be given in either **binary** (after a dollar sign) or **hexadecimal** notation (after a hash sign).\nIf a tag is not explicitly provided, the TL-B parser must compute a default 32-bit constructor tag by hashing with\nthe [CRC32 algorithm](https://en.wikipedia.org/wiki/Cyclic_redundancy_check) the text of the scheme with `| 0x80000000` defining this constructor in a certain fashion. Therefore,\nempty tags must be explicitly provided by `#_` or `$_`.\n\nAll constructor names must be distinct, and constructor tags for the same combinator must constitute a [prefix code](https://en.wikipedia.org/wiki/Prefix_code#:~:text=A%20prefix%20code%20is%20a,code%20word%20in%20the%20system.)\n(otherwise the deserialization would not be unique), i.e., no tag can be a prefix of any other.\n\nAlso, there are size limitations:\n\n- maximum number of constructors per type: `64`;\n- maximum number of bits for a tag: `63`.\n\nFor example, each address in TON could be either an **internal** message or an **external**, see [general info page](/foundations/addresses/overview).\nAddresses are serialized according to the following TL-B schemes:\n\n```tlb\naddr_none$00 = MsgAddressExt;\naddr_extern$01 ... = MsgAddressExt;\naddr_std$10 ...  = MsgAddressInt;\naddr_var$11 ... = MsgAddressInt;\n...\n\n_ _:MsgAddressInt = MsgAddress;\n_ _:MsgAddressExt = MsgAddress;\n```\n\nWhen parsing the binary string `10...` that should be an instance of `MsgAddress` combinator, the parser extracts the initial two bits that determine the tag.\nIt then understands that this address is further serialized as `add_std` and continues to parse our string relative to the fields defined in this constructor.\n\nAll main variations of constructors are presented in the following table:\n\n| Constructor                 | Serialization                                   |\n| --------------------------- | ----------------------------------------------- |\n| `some#3f5476ca`             | A 32-bit `uint` is serialized from a hex value. |\n| `some#5fe`                  | A 12-bit `uint` is serialized from a hex value. |\n| `some$0101` or `_$0101`     | Serialize the `0101` raw bits.                  |\n| `some` or `some#`           | Serialize `crc32(equation) \\| 0x80000000`.      |\n| `some#_` or `some$_` or `_` | Serialize nothing.                              |\n\nIn addition to the standard hex tag definition, a hexadecimal number may be followed by an underscore `_` character.\nThis indicates that the tag should be interpreted as the hexadecimal value with the [least significant bit (LSB)](https://en.wikipedia.org/wiki/Bit_numbering#Least_significant_bit) removed.\nFor example, consider the following schema, which represents a stack integer value:\n\n```tlb\nvm_stk_int#0201_ ... = VmStackValue;\n```\n\nIn this case, the tag is not equal to `0x0201`. To compute the actual tag, remove the LSB from the binary representation of `0x0201`:\n\n```\n0000001000000001 -> 000000100000000\n```\n\nThe resulting tag is the 15-bit binary number `0b000000100000000`.\n\n### Field definitions\n\nField definitions follow each constructor and its optional tag. A field definition has the format `ident:type-expr`, where:\n\n- `ident` is the field's name. If you don't want to assign a specific name to the field, just leave it as `_`.\n- `type-expr` is the field's type. It can be a simple type, a parameterized type with appropriate arguments, or a more complex expression.\n\n**Note: the total size of all fields in a type must not exceed the limits of a single cell:  `1023` bits and `4` references**.\n\nTL-B schemes define types. At the same time, the previously defined types can be used in other schemes in fields.\nTherefore, in order to properly understand what types can be assigned to fields, we need to simultaneously figure out how to define the types themselves.\n\n### Types\n\n#### Simple\n\nFields that are simple types are just examples of some previously defined or built-in types. They do not contain parameterization or any conditions.\n\nFor example, **Tick** and **Tock** transactions are designated for special system smart contracts that must be automatically invoked in every block.\nTick transactions are executed at the start of each masterchain block, while Tock transactions are initiated at the end. Here is how they are represented in TL-B:\n\n```tlb\ntrans_tick_tock$001 is_tock:Bool storage_ph:TrStoragePhase\n    compute_ph:TrComputePhase action:(Maybe ^TrActionPhase)\n    aborted:Bool destroyed:Bool = TransactionDescr;\n```\n\nSo, `is_tock`, `storage_ph`, `compute_ph`, `aborted`, and `destroyed` are fields with simple types.\n\nBelow are all the built-in types that can be used in defining fields:\n\n- `#`: 32-bit unsigned integer;\n- `## x`: unsigned integer with `x` bits;\n- `#< x`: unsigned integer less than `x` bits, stored as `lenBits(x - 1)` bits up to 31 bits;\n- `#<= x`: unsigned integer less than or equal to `x` bits, stored as `lenBits(x)` bits up to 32 bits;\n- `Any` or `Cell`: remaining bits and references;\n- `uint1`: `uint256` - 1 - 256 bits;\n- `int1`: `int257` - 1 - 257 bits;\n- `bits1`: `bits1023` - 1 - 1023 bits.\n\n#### Contained complex expressions\n\n- **Multiplicative expression for tuple creation**. The expression `x * T` creates a tuple of the natural length `x`, where each element is of type `T`.\n\n```tlb\na$_ a:(## 32) = A;\nb$_ b:(2 * A) = PairOf32-bits-uints;\n```\n\n- **Serialization in the ref cell**: `^[ ... ]` means that the fields inside the brackets are serialized in a separate cell, which is referenced from the current cell.\n\n```tlb\n_ a:(## 32) ^[ b:(## 32) c:(## 32) d:(## 32)] = A;\n```\n\nChains of references are also allowed. In the following example, each variable (`a`, `b`, `c`) is stored in a separate cell, resulting in a chain of three referenced cells:\n\n```tlb\n_ ^[ a:(## 32) ^[ b:(## 32) ^[ c:(## 32) ] ] ] = A;\n```\n\nOther complex type expressions are related to the `Nat` type only. The `Nat` type is a built-in type that represents natural numbers.\nThe types `#`, `## x`, `#< x`, and `#<= x` together constitute the `Nat` type. In TL-B schemes, the `+` and `*` operations can be performed on `Nat`.\n\n- **Constraints**: `Nat = Nat | Nat <= Nat | Nat < Nat | Nat >= Nat | Nat > Nat`. Each constraint must be enclosed in curly braces `{}`, and the variables used inside must be defined earlier.\n\n```tlb\n_ flag1:(## 10) flag2:# { flag1 + flag2 <= 100 } = Flag;\n```\n\nThis constraint means that the sum of the flags fields must be less than or equal to `100`.\n\n- **Condition operator**: `Nat?Type` means that if the natural number is positive, then the field has the type `T`. Otherwise, the field is omitted.\n\n```tlb\n_ a:(## 1) b:a?(## 32) = Example;\n```\n\nIn the `Example` type, the field `b` is serialized only if the `a` field is equal to `1`.\n\n- **Bit selector**: The expression `E . B` means to take bit `B` from the `Nat` value `E`.\n\n```tlb\n_ a:(## 2) b:(a . 1)?(## 32) = CondExample;\n```\n\nSimilarly, in the `CondExample` type, the variable `b` is serialized only if the **second bit** of `a` is `1`.\n\nFor the real-world example, one may consider the following `McStateExtra` combinator that describes data stored in each masterchain block.\n\n```tlb\nmasterchain_state_extra#cc26\n  shard_hashes:ShardHashes\n  config:ConfigParams\n  ^[ flags:(## 16) { flags <= 1 }\n     validator_info:ValidatorInfo\n     prev_blocks:OldMcBlocksInfo\n     after_key_block:Bool\n     last_key_block:(Maybe ExtBlkRef)\n     block_create_stats:(flags . 0)?BlockCreateStats ]\n  global_balance:CurrencyCollection\n= McStateExtra;\n```\n\n#### Parameterized\n\n**Parameterized types** are patterns in which other types are parameters. Such parameters are declared in curly brackets `{}` or must be declared previously\nas a combinator's field. Only identifiers of the `Nat` and `Type` types can be parameters.\n\nA simple example of a parameterized type is the following definition of a type `A` that is parameterized by a natural number `x`:\n\n```tlb\n_ {x:#} my_val:(## x) = A x;\n```\n\nDuring the deserialization process, it fetches an x-bit unsigned integer. For example:\n\n```\n_ value:(A 32) = My32UintValue;\n```\n\nDuring the deserialization process of `My32UintValue`, it fetches a 32-bit unsigned integer, as specified by the `32` natural parameter in the `A` type.\n\nLet's consider another example where a combinator `A` parameterized by a type variable `X` is defined:\n\n```tlb\n_ {X:Type} my_val:(## 32) next_val:X = A X;\n```\n\nDuring the deserialization process, we will first fetch a 32-bit unsigned integer and then parse the bits and references of the X type.\n\nAn example usage of such a parameterized type can be:\n\n```tlb\n_ bit:(## 1) = Bit;\n_ 32intwbit:(A Bit) = 32IntWithBit;\n```\n\nIn this example, the `Bit` type is passed to `A` as a parameter.\n\nThere is a possibility to use partial applications with such parameterized types:\n\n```tlb\n_ {X:Type} {Y:Type} v1:X v2:Y = A X Y;\n_ bit:(## 1) = Bit;\n_ {X:Type} bits:(A Bit X) = BitA X;\n```\n\nOr even apply partial application to parameterized types themselves:\n\n```tlb\n_ {X:Type} v1:X = A X;\n_ {X:Type} d1:X = B X;\n_ {X:Type} bits:(A (B X)) = AB X;\n```\n\nIt is also possible to use fields defined previously as parameters to types. The serialization will be determined at runtime.\n\n```tlb\n_ a:(## 8) b:(## a) = A;\n```\n\nThis means that the size of the `b` field is stored inside the `a` field. When serializing type `A`, we first load the 8-bit unsigned integer from the `a` field and then use this value to determine the size of the `b` field.\n\nThis strategy also works for parameterized types:\n\n```tlb\n_ {input:#} c:(## input) = B input;\n_ a:(## 8) c_in_b:(B a) = A;\n```\n\nSince parameters can be natural numbers, one can use arithmetic operations on them:\n\n```tlb\n_ {x:#} value:(## x) = ExampleMult (x * 2);\n_ _:(ExampleMult 4) = 2BitInteger;\n\n_ {x:#} value:(## x) = ExampleSum (x + 3);\n_ _:(ExampleSum 4) = 1BitInteger;\n```\n\nThe good real-world example of parameterized types is the definition of TVM tuples:\n\n```tlb\nvm_tupref_nil$_ = VmTupleRef 0;\nvm_tupref_single$_ entry:^VmStackValue = VmTupleRef 1;\nvm_tupref_any$_ {n:#} ref:^(VmTuple (n + 2)) = VmTupleRef (n + 2);\nvm_tuple_nil$_ = VmTuple 0;\nvm_tuple_tcons$_ {n:#} head:(VmTupleRef n) tail:^VmStackValue = VmTuple (n + 1);\nvm_stk_tuple#07 len:(## 16) data:(VmTuple len) = VmStackValue;\n```\n\nFor a detailed explanation of how it works, see the [complex and non-trivial examples page](/languages/tl-b/complex-and-non-trivial-examples).\n\n#### Special\n\nCurrently, TVM allows the following types of cells:\n\n- Ordinary\n- PrunedBranch\n- Library\n- MerkleProof\n- MerkleUpdate\n\nBy default, all cells are classified and parsed as `Ordinary`. This applies to all cells described in the TL‑B as well.\n\nTo enable the loading of special types in the constructor, prepend `!` before the constructor.\n\n**Example**\n\n```tlb\n!merkle_update#02 {X:Type} old_hash:bits256 new_hash:bits256\n  old:^X new:^X = MERKLE_UPDATE X;\n\n!merkle_proof#03 {X:Type} virtual_hash:bits256 depth:uint16 virtual_root:^X = MERKLE_PROOF X;\n```\n\nThis technique allows code generation to mark `SPECIAL` cells when printing a structure and ensures proper validation of structures with special cells.\n\n### Implicit fields and the negate operator (`~`)\n\nSome fields may be **implicit**. These fields are defined within curly brackets `{}`, as constraints and parameters of the parametrized types,\nindicating that they are not directly serialized. Instead, their values must be deduced from other data, usually the parameters of the type being serialized.\n\nSome occurrences of the indicators already defined earlier in a scheme are prefixed by a tilde `~`. This indicates that the indicator's occurrence is used\noppositely from the default behavior. On the left-hand side of the equation, it means that the indicator is deduced (computed) based on this occurrence,\nrather than substituting its type's defined value. Conversely, on the right-hand side, the indicator is not deduced from\nthe serialized type but instead computed during the deserialization process. In other words,\na `~` transforms an _input argument_ into an _output argument_ or vice versa.\n\nA simple example of the negate operator is the definition of the implicit indicator `b` based on another indicator `a`:\n\n```tlb\n_ a:(## 32) { b:# } { ~b = a + 100 } = B_Calc_Example;\n```\n\nSo, after deserialization of `a`, the value of `b` is computed as `a + 100`. After this definition, you can use the new indicator as input for `Nat` types:\n\n```tlb\n_ a:(## 8) { b:# } { ~b = a + 10 }\n  example_dynamic_var:(## b) = B_Calc_Example;\n```\n\nThe size of `example_dynamic_var` is computed at runtime when we load `a` and use its value to determine the size of `example_dynamic_var`.\n\nAlternatively, it can be applied to other types:\n\n```tlb\n_ {X:Type} a:^X = PutToRef X;\n_ a:(## 32) { b:# } { ~b = a + 100 }\n  my_ref: (PutToRef b) = B_Calc_Example;\n```\n\n#### Negate operator (`~`) in type definition\n\n```tlb\n_ {m:#} n:(## m) = Define ~n m;\n_ {n_from_define:#} defined_val:(Define ~n_from_define 8) real_value:(## n_from_define) = Example;\n```\n\nAssume we have a class `Define ~n m` that takes `m` and computes `n` by loading it from an `m`-bit unsigned integer.\n\nIn the `Example` type, we store the variable computed by the `Define` type into `n_from_define`. We also know it's an `8`-bit unsigned integer because we apply the `Define` type with `Define ~n_from_define 8`. Now, we can use the `n_from_define` variable for other kinds to determine the serialization process.\n\nThis technique leads to more complex type definitions, such as **Unions** that represent dynamic chains of some type.\n\n```tlb\nunary_zero$0 = Unary ~0;\nunary_succ$1 {n:#} x:(Unary ~n) = Unary ~(n + 1);\n_ u:(Unary Any) = UnaryChain;\n```\n\nand **Hashmaps**.\n\n```tlb\nhm_edge#_ {n:#} {X:Type} {l:#} {m:#} label:(HmLabel ~l n)\n          {n = (~m) + l} node:(HashmapNode m X) = Hashmap n X;\n\nhmn_leaf#_ {X:Type} value:X = HashmapNode 0 X;\nhmn_fork#_ {n:#} {X:Type} left:^(Hashmap n X)\n           right:^(Hashmap n X) = HashmapNode (n + 1) X;\n\nhml_short$0 {m:#} {n:#} len:(Unary ~n) {n <= m} s:(n * Bit) = HmLabel ~n m;\nhml_long$10 {m:#} n:(#<= m) s:(n * Bit) = HmLabel ~n m;\nhml_same$11 {m:#} v:Bit n:(#<= m) = HmLabel ~n m;\n\nunary_zero$0 = Unary ~0;\nunary_succ$1 {n:#} x:(Unary ~n) = Unary ~(n + 1);\n\nhme_empty$0 {n:#} {X:Type} = HashmapE n X;\nhme_root$1 {n:#} {X:Type} root:^(Hashmap n X) = HashmapE n X;\n```\n\nFor a detailed explanation of how these combinators are deserialized, see the [complex and non-trivial examples page](/languages/tl-b/complex-and-non-trivial-examples).\n\n## References\n\n- [A description of an older version of TL](https://core.telegram.org/mtproto/TL);\n- [`block.tlb`](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb): the main TL-B file that describes all basic TON blockchain structures.\n"
  },
  {
    "path": "languages/tl-b/tep-examples.mdx",
    "content": "---\ntitle: \"TEP examples\"\n---\n\nThe purpose of this article is to explain common TL-B examples that you encounter when reading our standards.\n\n## NFT\n\nThe [NFT collection and each NFT item](/standard/tokens/nft/overview) are separate smart contracts in TON Blockchain. Each specific implementation must\ncomply with the [TEP 0062](https://github.com/ton-blockchain/TEPs/blob/master/text/0062-nft-standard.md) standard.\n\nWhen reading this TEP, you encounter a TL-B schema that describes the serialization of a\nmessage that transfers the rights of a given NFT item to another user.\n\n```tlb\ntransfer#5fcc3d14 query_id:uint64 new_owner:MsgAddress\nresponse_destination:MsgAddress custom_payload:(Maybe ^Cell)\nforward_amount:(VarUInteger 16) forward_payload:(Either Cell ^Cell)\n= InternalMsgBody;\n```\n\nThus, a cell corresponds to this TL-B scheme if it sequentially contains:\n\n- 32-bits that represents the hexadecimal number `0x5fcc3d14`.\n- An arbitrary request number that is an unsigned 64-bit integer in binary form.\n- An address of the new owner of the NFT item that is a sequence of bits corresponding to the\n  `MsgAddress` TL-B scheme (see the [address](/foundations/addresses/overview) page for details).\n- An address where to send a response with confirmation of a successful transfer and the rest of the incoming message coins. It is\n  serialized as the previous field.\n- Optional custom data. For the description of how the `Maybe` type works,\n  see [simple examples page](/languages/tl-b/simple-examples).\n- The amount of nanotons to be sent to the new owner. For the explanation of how `VarUInteger n` works, see\n  [simple examples page](/languages/tl-b/simple-examples).\n- The optional custom data that should be sent to the new owner. For the description of how the `Either` type works,\n  see [simple examples page](/languages/tl-b/simple-examples).\n\nThe knowledge gained from analyzing the TL-B schemes above is sufficient to understand all the schemes that\nyou will encounter when analyzing the [Jetton](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md#summary),\n[NFT Royalty](https://github.com/ton-blockchain/TEPs/blob/master/text/0066-nft-royalty-standard.md),\n[SBT](https://github.com/ton-blockchain/TEPs/blob/master/text/0085-sbt-standard.md),\n[Jetton wallet](https://github.com/ton-blockchain/TEPs/blob/master/text/0089-jetton-wallet-discovery.md) standards.\n\n## Jetton\n\nIt was mentioned above that an example of the TL-B scheme related to NFTs is sufficient to understand all schemes related to Jettons.\nHowever, as Jetton transactions are among the most common on the TON blockchain, we will analyze relevant schemes separately.\n\nA standard interface for _Jettons (TON fungible tokens)_ is specified in [TEP 0074](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md).\n\nTo transfer tokens from one wallet to another, it is required to send a message to the sender's\njetton-wallet corresponding to the following TL-B scheme. For the description of how data types `VarUInteger n`, `Maybe`, and `Either` work, see\n[simple examples page](/languages/tl-b/simple-examples).\n\n```tlb\ntransfer#0f8a7ea5 query_id:uint64 amount:(VarUInteger 16) destination:MsgAddress\n                 response_destination:MsgAddress custom_payload:(Maybe ^Cell)\n                 forward_ton_amount:(VarUInteger 16) forward_payload:(Either Cell ^Cell)\n                 = InternalMsgBody;\n```\n\nThus, a cell corresponds to this TL-B scheme if it sequentially contains:\n\n- 32-bits that represents the hexadecimal number `0x0f8a7ea5`.\n- An arbitrary request number that is an unsigned 64-bit integer in binary form.\n- An amount of transferred jettons in elementary units.\n- An address of the new owner of jettons, which is a sequence of bits corresponding to the\n  `MsgAddress` TL-B scheme (see the [address](/foundations/addresses/overview) page for details).\n- An address to which to send a response with confirmation of a successful transfer and the rest of the incoming message coins. It is\n  serialized as the previous field.\n- Optional custom data.\n- The amount of nanotons to be sent to the new owner.\n- Optional custom data that should be sent to the `destination` address.\n\nIf `forward_amount > 0`, the receiver's jetton-wallet should send a message to the `destination` address with\n`forward_amount` nanotons attached and with the following TL-B schema.\n\n```tlb\ntransfer_notification#7362d09c query_id:uint64 amount:(VarUInteger 16)\n                              sender:MsgAddress forward_payload:(Either Cell ^Cell)\n                              = InternalMsgBody;\n```\n\nThus, a cell corresponds to this TL-B scheme if it sequentially contains:\n\n- 32 bits that represent the hexadecimal number `0x7362d09c`.\n- An arbitrary request number that is an unsigned 64-bit integer in binary form.\n- An amount of transferred jettons in elementary units.\n- An address of the previous owner of transferred jettons.\n- Optional custom data that should be sent to the destination address.\n\nThe rest of the TL-B schemes corresponding to the Jettons can be examined in a similar way.\n\n## DNS\n\n_TON DNS_ is a service for translating human-readable domain names (such as test.ton or mysite.temp.ton) into TON smart contract addresses.\nIt is specified in [TEP 0081](https://github.com/ton-blockchain/TEPs/blob/master/text/0081-dns-standard.md).\n\nLet's consider TL-B schemes of _DNS Records_ values:\n\n```tlb\nproto_http#4854 = Protocol;\n\nproto_list_nil$0 = ProtoList;\nproto_list_next$1 head:Protocol tail:ProtoList = ProtoList;\n\n\ncap_is_wallet#2177 = SmcCapability;\n\ncap_list_nil$0 = SmcCapList;\ncap_list_next$1 head:SmcCapability tail:SmcCapList = SmcCapList;\n\ndns_smc_address#9fd3 smc_addr:MsgAddressInt flags:(## 8) { flags <= 1 }\n  cap_list:flags . 0?SmcCapList = DNSRecord;\ndns_next_resolver#ba93 resolver:MsgAddressInt = DNSRecord;\ndns_adnl_address#ad01 adnl_addr:bits256 flags:(## 8) { flags <= 1 }\n  proto_list:flags . 0?ProtoList = DNSRecord;\ndns_storage_address#7473 bag_id:bits256 = DNSRecord;\n\n_ (HashmapE 256 ^DNSRecord) = DNS_RecordSet;\n```\n\nThe first thing you need to pay attention to: how lists of arbitrary length are formed.\nFor instance, `ProtoList` combinator consists of two constructors: `proto_list_nil` that indicates the end of a list and\n`proto_list_next` that indicates that there is a record of protocol followed by the next record or the end of a list.\n\nWhen deserializing data of the `ProtoList` type, the prefix `1` or `0` is read first. If the prefix is `0`, then we have reached the end\nof the list and there is nothing more to read. Otherwise, the protocol entry is read, followed by a prefix\nindicating whether the next protocol entry will be followed or the end of the list. The same applies to the `SmcCapList` type.\n\nNext, pay attention to the `DNSRecord` type. The constructors `dns_next_resolver` and `dns_storage_address` are simple.\nLet's deal with the `dns_adnl_address`constructor:\n\n- first comes the `0xad01` prefix;\n- then 256 bits representing ADNL address;\n- next, the 8-bit flag, which is currently bounded by `1`;\n- finally, if the first bit of the flag is `1`, the serialization continued with `ProtoList` type;\n- if the first bit of the flag is `0`, then serialization is completed.\n\nThe serialization of `dns_smc_address` follows the same logic.\n"
  },
  {
    "path": "languages/tl-b/tooling.mdx",
    "content": "---\ntitle: \"Tooling\"\n---\n\n## TL-B parsers\n\nTL-B libraries provide serializers and parsers for basic [TL-B types](/languages/tl-b/syntax-and-semantics) and can serialize to and deserialize from the corresponding binary format.\n\n| Language   | SDK                                                                       | Social                                |\n| ---------- | ------------------------------------------------------------------------- | ------------------------------------- |\n| Kotlin     | [`ton-kotlin`](https://github.com/ton-community/ton-kotlin/tree/main/tlb) | [`tonkotlin`](https://t.me/tonkotlin) |\n| Go         | [`tonutils`](https://github.com/xssnick/tonutils-go/tree/master/tlb)      | [`tonutils`](https://t.me/tonutils)   |\n| Go         | [`tongo`](https://github.com/tonkeeper/tongo/tree/master/tlb)             | [`tongo_lib`](https://t.me/tongo_lib) |\n| TypeScript | [`tlb-parser`](https://github.com/ton-community/tlb-parser)               | -                                     |\n| Python     | [`tonpy`](https://github.com/disintar/tonpy)                              | [`dtontech`](https://t.me/dtontech)   |\n\n## TL-B generators\n\nThe [`tlb-codegen`](https://github.com/ton-community/tlb-codegen) package generates TypeScript code for serializing and deserializing structures based on a provided TL-B scheme.\n\nThe [`tonpy`](https://github.com/disintar/tonpy) package also supports code generation in Python for serializing and deserializing structures according to a given TL-B scheme.\n\n## TL-B online editors\n\nThe convenient [TL-B online editor](https://ton-community.github.io/tlb-editor/#/main) allows you to write TL-B schemes and immediately see the results of parsing and serialization.\n"
  },
  {
    "path": "languages/tolk/basic-syntax.mdx",
    "content": "---\ntitle: \"Basic syntax\"\nsidebarTitle: \"Basic syntax\"\n---\n\n## Imports\n\n[Imports](/languages/tolk/syntax/imports) must appear at the top of the file:\n\n```tolk\nimport \"another-file\"\n\n// Symbols from `another-file.tolk` become available in this file.\n```\n\nIn most workflows, the IDE adds imports automatically. For example, when selecting an item from auto-completion.\n\nThe entire file is imported. There are no modules or exports; all symbols must have unique names within the project.\n\n## Structures\n\nA [struct](/languages/tolk/syntax/structures-fields) `Point` holding two 8-bit integers:\n\n```tolk\nstruct Point {\n    x: int8\n    y: int8\n}\n\nfun demo() {\n    // create an object\n    val p1: Point = { x: 10, y: 20 };\n\n    // the same, type of p2 is auto-inferred\n    val p2 = Point { x: 10, y: 20 };\n}\n```\n\n- Methods are declared as `fun Point.method(self)`.\n- Fields can use any [types](/languages/tolk/types/list-of-types): numeric, cell, union, and others.\n- Fields can define default values: `x: int8 = 0`.\n- Fields can be `private` and `readonly`.\n- Structs can be generic: `struct Wrapper<T> { ... }`.\n\nIf all fields are serializable, a struct can be [automatically serialized](/languages/tolk/features/auto-serialization):\n\n```tolk\n// makes a cell containing hex \"0A14\"\nval c = p1.toCell();\n// back to { x: 10, y: 20 }\nval p3 = Point.fromCell(c);\n```\n\n## Functions\n\nA [function](/languages/tolk/syntax/functions-methods) that returns the sum of two integers:\n\n```tolk\nfun sum(a: int, b: int): int {\n    return a + b;\n}\n```\n\n- Parameter types are mandatory.\n- The return type can be omitted: it is auto-inferred.\n- Parameters can define default values: `fun f(b: int = 0)`\n- Statements in a block are separated by semicolons `;`.\n- Generic functions are supported: `fun f<T>(value: T) { ... }`\n- Assembler functions are supported: `fun f(...): int asm \"...\"`\n\n## Methods\n\nA function declared as `fun <receiver>.name(...)` is a [method](/languages/tolk/syntax/functions-methods).\n\n- If the first parameter is `self`, it's an instance method.\n- If the first parameter is not `self`, it's a static method.\n\n```tolk\n// `self` — instance method (invoked on a value)\nfun Point.sumCoords(self) {\n    return sum(self.x, self.y);\n}\n\n// not `self` — static method\nfun Point.createZero(): Point {\n    return { x: 0, y: 0 };\n}\n\nfun demo() {\n    val p = Point.createZero();    // { 0, 0 }\n    return p.sumCoords();          // 0\n}\n```\n\nBy default, `self` is immutable; `mutate self` allows modifying the object.\n\nMethods can be declared for any type, including primitives:\n\n```tolk\nfun int.isNegative(self) {\n    return self < 0\n}\n```\n\n## Variables\n\nWithin functions, [variables](/languages/tolk/syntax/variables) are declared with `val` or `var` keywords. The `val` keyword declares an immutable variable that can be assigned only once:\n\n```tolk\nval coeff = 5;\n// cannot change its value, `coeff += 1` is an error\n```\n\nThe `var` keyword declares a variable that can be reassigned:\n\n```tolk\nvar x = 5;\nx += 1;      // now 6\n```\n\nA variable’s type can be specified after its name:\n\n```tolk\nvar x: int8 = 5;\n```\n\nDeclaring variables at the top level, outside functions, is supported using the `global` keyword.\n\n## Constants\n\nConstants can be declared only at the top level, not inside functions:\n\n```tolk\nconst ONE = 1\nconst MAX_AMOUNT = ton(\"0.05\")\nconst ADMIN_ADDRESS = address(\"EQ...\")\n```\n\nTo group integer constants, [enums](/languages/tolk/types/enums) are useful.\n\n## Value semantics\n\nTolk follows value semantics: assignments create independent copies, and function calls do not [mutate](/languages/tolk/syntax/mutability) arguments unless explicitly specified.\n\n```tolk\nvar a = Point { x: 1, y: 2 };\nvar b = a;   // `b` is a copy\nb.x = 99;    // `a.x` remains 1\nsomeFn(a);   // pass a copy; `a` will not change\n\n// but there can be mutating functions, called this way:\nanotherFn(mutate a);\n```\n\n## Semicolons\n\n- Semicolons are optional at the top level, after imports, aliases, etc.\n- Semicolons are required between statements in a function.\n- After the last statement in a block, a semicolon is optional.\n\n```tolk\n// optional at the top-level\nconst ONE = 1\ntype UserId = int\n\n// required inside functions\nfun demo() {\n    val x = 5;\n    val y = 6;\n    return x + y    // optional after the last statement\n}\n```\n\n## Comments\n\nTolk supports single-line or end-of-line and multi-line or block comments:\n\n```tolk\n// This is a single-line comment\n\n/* This is a block comment\n   across multiple lines. */\n\nconst TWO = 1 /* + 100 */ + 1    // 2\n```\n\n## Conditional operators\n\nIn [conditions](/languages/tolk/syntax/conditions-loops), `if` is a statement. `else if` and `else` blocks are optional.\n\n```tolk\nfun sortNumbers(a: int, b: int) {\n    if (a > b) {\n        return (b, a)\n    } else {\n        return (a, b)\n    }\n}\n```\n\nA ternary operator is also available:\n\n```tolk\nval sign = a > 0 ? 1 : a < 0 ? -1 : 0;\n```\n\n## Union types and matching\n\n[Union types](/languages/tolk/types/unions) allow a variable to hold one of possible types. They are typically handled by `match`:\n\n```tolk\nfun processValue(value: int | slice) {\n    match (value) {\n        int => {\n            value * 2\n        }\n        slice => {\n            value.loadUint(8)\n        }\n    }\n}\n```\n\nAlternatively, test a union with `is` or `!is` operators:\n\n```tolk\nfun processValue(value: int | slice) {\n    if (value is slice) {\n        // call methods for `slice`\n        return;\n    }\n    // value is `int`\n    return value * 2;\n}\n```\n\nUnion types are commonly used when [handling incoming messages](/languages/tolk/features/message-handling).\n\n## While loop\n\nTolk does not have a `for` loop; use [`while` loop](/languages/tolk/syntax/conditions-loops) for repeated execution.\n\n```tolk\nwhile (i > 0) {\n    // ...\n    i -= 1;\n}\n```\n\n## Assert and throw\n\nThe `try-catch` statement is supported for [exceptions](/languages/tolk/syntax/exceptions), although it is not commonly used in contracts.\n\n```tolk\nconst ERROR_NO_BALANCE = 403;\n\n// in some function\nthrow ERROR_NO_BALANCE;\n\n// or conditional throw\nassert (balance > 0) throw ERROR_NO_BALANCE;\n```\n\n## Iterate over a map\n\nTo iterate, [maps](/languages/tolk/types/maps) can be used:\n\n```tolk\nfun iterateOverMap(m: map<int32, Point>) {\n    var r = m.findFirst();\n    while (r.isFound) {\n        // ...\n        r = m.iterateNext(r);\n    }\n}\n```\n\n## Send a message to another contract\n\nTo [construct and send a message](/languages/tolk/features/message-sending), a message body is typically represented by a structure. For example, `RequestedInfo`:\n\n```tolk\nval reply = createMessage({\n    bounce: BounceMode.NoBounce,\n    value: ton(\"0.05\"),\n    dest: someAddress,\n    body: RequestedInfo { ... }\n});\nreply.send(SEND_MODE_REGULAR);\n```\n\n## Contract getters\n\n[Contract getters](/languages/tolk/features/contract-getters) or get-methods are declared with `get fun`:\n\n```tolk\nget fun currentOwner() {\n    val storage = lazy Storage.load();\n    return storage.ownerAddress;\n}\n```\n"
  },
  {
    "path": "languages/tolk/changelog.mdx",
    "content": "---\ntitle: \"Changelog\"\n---\n\n## [v1.2](https://github.com/ton-blockchain/ton/pull/1886)\n\n1. Introduced `address` as \"internal only\".\n1. Delivered rich bounces: return the full body instead of 256 bits.\n1. Provided low-cost builder-to-slice, `StateInit`, and address composition.\n1. Improved compilation errors.\n1. Added support for anonymous functions.\n1. Added the borrow checker and related undefined-behavior checks.\n\n## v1.1\n\n1. Added `map<K, V>` — a wrapper over TVM dictionaries.\n1. Added `enum` — group numeric constants into a distinct type.\n1. Added `private` and `readonly` fields in structures.\n1. Enhanced overload resolution and partial specialization.\n\n## v1.0\n\n1. Added the `lazy` keyword.\n1. Added auto-detect and inline functions at the compiler level.\n1. Added various peephole optimizations for gas efficiency.\n1. Added `onInternalMessage` and `onBouncedMessage`, TVM 11 support.\n1. Added custom pack and unpack serializers for custom types.\n\n## v0.99\n\n1. Added `createMessage`.\n1. Added `createExternalLogMessage`.\n1. Added sharding support for calculating addresses \"close to another contract\".\n\n## v0.13\n\n1. Added auto-packing `to` and `from` `cells`, `builders`, and `slices`.\n1. Added type `address`.\n1. Added Lateinit variables.\n1. Added defaults for parameters.\n\n## v0.12\n\n1. Added structures `struct A { ... }`.\n1. Added generics `struct<T>` and `type<T>`.\n1. Added methods `fun Point.getX(self)`.\n1. Renamed stdlib functions to short methods.\n\n## v0.11\n\n1. Added type aliases `type NewName = <existing type>`.\n1. Added union types `T1 | T2 | ...`.\n1. Added pattern matching for types.\n1. Added the `is` and `!is` operators.\n1. Added pattern matching for expressions.\n1. Allowed the semicolon to be omitted for the last statement in a block.\n\n## [v0.10](https://github.com/ton-blockchain/ton/pull/1559)\n\n1. Added fixed-width integers such as `int32` and `uint64`.\n1. Added the `coins` type and the `ton(\"0.05\")` function.\n1. Added `bytesN` and `bitsN` types backed by slices at the TVM level.\n1. Replaced `\"...\"c` postfixes with `stringCrc32(\"...\")` functions.\n1. Added support `0b...` number literals in addition to `0x...`.\n1. Added support trailing commas.\n\n## v0.9\n\n1. Added nullable types `int?`, `cell?`, and others; introduce null safety.\n1. Updated the standard library, including`asm` definitions, to support nullability.\n1. Introduced smart casts, like in TypeScript and Kotlin.\n1. Added the `!` operator (non-null assertion).\n1. Treated code after `throw` as unreachable.\n1. Added the `never` type.\n\n## v0.8\n\n1. Introduced syntax `tensorVar.0` and `tupleVar.0` for reading and writing.\n1. Allowed `cell`, `slice`, and similar terms to be used as valid identifiers rather than keywords.\n\n## v0.7\n\n1. Refactored compiler internals and introduce an AST-level semantic analysis kernel.\n1. Changed the type system to static typing.\n1. Provided clear and readable error messages for type mismatch.\n1. Added generic functions `fun f<T>(...)` and instantiations such as `f<int>(...)`.\n1. Added `bool` type and type casting through `value as T`.\n\n## v0.6\n\nThe first public release.\n\nTolk is a fork of FunC with iterative improvements. In 2024, a pull request for [FunC v0.5.0](https://github.com/ton-blockchain/ton/pull/1026) was submitted together with a roadmap for further development. Instead of merging it, it was forked.\n\nTolk was first announced at [TON Gateway](https://www.youtube.com/watch?v=Frq-HUYGdbI) in 2024.\nThe released version was marked v0.6, indicating its relation to the FunC v0.5.\n"
  },
  {
    "path": "languages/tolk/examples.mdx",
    "content": "---\ntitle: \"Tolk contract examples\"\nsidebarTitle: \"Examples\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\nimport { FileTree } from '/snippets/filetree.jsx';\n\nBasic jetton and NFT contract examples from [`ton-blockchain/tolk-bench`](https://github.com/ton-blockchain/tolk-bench), extracted from commit [`cb9648b`](https://github.com/ton-blockchain/tolk-bench/tree/cb9648bdf936f88eb9d773d9058405f74a1e24d9), appear here as accordions by source file.\n\n<Aside\n  type=\"caution\"\n>\n  All examples are given for educational purposes only. Never apply them directly in production without prior testing.\n</Aside>\n\n## Jetton\n\nSource directory: [`contracts_Tolk/01_jetton`](https://github.com/ton-blockchain/tolk-bench/tree/cb9648bdf936f88eb9d773d9058405f74a1e24d9/contracts_Tolk/01_jetton).\n\n<FileTree\n  items={[{\n    kind: \"folder\",\n    name: \"01_jetton/\",\n    items: [\"errors.tolk\", \"fees-management.tolk\", \"storage.tolk\", \"messages.tolk\", \"jetton-utils.tolk\", \"jetton-minter-contract.tolk\", \"jetton-wallet-contract.tolk\"]\n  }]}\n/>\n\nSome files in the source directory are not runnable on their own and depend on others. Keep all the listed files together.\n\n<AccordionGroup>\n  <Accordion\n    title=\"errors.tolk\"\n  >\n    ```tolk\n    const ERR_INVALID_OP = 709\n    const ERR_NOT_FROM_ADMIN = 73\n    const ERR_UNAUTHORIZED_BURN = 74\n    const ERR_NOT_ENOUGH_AMOUNT_TO_RESPOND = 75\n    const ERR_NOT_FROM_OWNER = 705\n    const ERR_NOT_ENOUGH_TON = 709\n    const ERR_NOT_ENOUGH_GAS = 707\n    const ERR_INVALID_WALLET = 707\n    const ERR_WRONG_WORKCHAIN = 333\n    const ERR_NOT_ENOUGH_BALANCE = 706\n    const ERR_INVALID_PAYLOAD = 708\n    ```\n  </Accordion>\n\n  <Accordion\n    title=\"fees-management.tolk\"\n  >\n    ```tolk\n    // 6905(computational_gas_price) * 1000(cur_gas_price) = 6905000 ~= 0.01 TON\n    const MINIMAL_MESSAGE_VALUE_BOUND = ton(\"0.01\")\n    const MIN_TONS_FOR_STORAGE = ton(\"0.01\")\n    const JETTON_WALLET_GAS_CONSUMPTION = ton(\"0.015\")\n    ```\n  </Accordion>\n\n  <Accordion\n    title=\"storage.tolk\"\n  >\n    ```tolk\n    struct WalletStorage {\n        jettonBalance: coins\n        ownerAddress: address\n        minterAddress: address\n    }\n\n    struct MinterStorage {\n        totalSupply: coins\n        adminAddress: address\n        content: cell\n        jettonWalletCode: cell\n    }\n\n\n    fun MinterStorage.load() {\n        return MinterStorage.fromCell(contract.getData())\n    }\n\n    fun MinterStorage.save(self) {\n        contract.setData(self.toCell())\n    }\n\n\n    fun WalletStorage.load() {\n        return WalletStorage.fromCell(contract.getData())\n    }\n\n    fun WalletStorage.save(self) {\n        contract.setData(self.toCell())\n    }\n    ```\n  </Accordion>\n\n  <Accordion\n    title=\"messages.tolk\"\n  >\n    ```tolk\n    type ForwardPayloadRemainder = RemainingBitsAndRefs\n\n    struct (0x0f8a7ea5) AskToTransfer {\n        queryId: uint64\n        jettonAmount: coins\n        transferRecipient: address\n        sendExcessesTo: address?\n        customPayload: cell?\n        forwardTonAmount: coins\n        forwardPayload: ForwardPayloadRemainder\n    }\n\n    struct (0x7362d09c) TransferNotificationForRecipient {\n        queryId: uint64\n        jettonAmount: coins\n        transferInitiator: address?\n        forwardPayload: ForwardPayloadRemainder\n    }\n\n    struct (0x178d4519) InternalTransferStep {\n        queryId: uint64\n        jettonAmount: coins\n        // is null when minting (not initiated by another wallet)\n        transferInitiator: address?\n        sendExcessesTo: address?\n        forwardTonAmount: coins\n        forwardPayload: ForwardPayloadRemainder\n    }\n\n    struct (0xd53276db) ReturnExcessesBack {\n        queryId: uint64\n    }\n\n    struct (0x595f07bc) AskToBurn {\n        queryId: uint64\n        jettonAmount: coins\n        sendExcessesTo: address?\n        customPayload: cell?\n    }\n\n    struct (0x7bdd97de) BurnNotificationForMinter {\n        queryId: uint64\n        jettonAmount: coins\n        burnInitiator: address\n        sendExcessesTo: address?\n    }\n\n    struct (0x2c76b973) RequestWalletAddress {\n        queryId: uint64\n        ownerAddress: address\n        includeOwnerAddress: bool\n    }\n\n    struct (0xd1735400) ResponseWalletAddress {\n        queryId: uint64\n        jettonWalletAddress: address?\n        ownerAddress: Cell<address>?\n    }\n\n    struct (0x00000015) MintNewJettons {\n        queryId: uint64\n        mintRecipient: address\n        tonAmount: coins\n        internalTransferMsg: Cell<InternalTransferStep>\n    }\n\n    struct (0x00000003) ChangeMinterAdmin {\n        queryId: uint64\n        newAdminAddress: address\n    }\n\n    struct (0x00000004) ChangeMinterContent {\n        queryId: uint64\n        newContent: cell\n    }\n    ```\n  </Accordion>\n\n  <Accordion\n    title=\"jetton-utils.tolk\"\n  >\n    ```tolk\n    import \"storage\"\n\n    fun calcDeployedJettonWallet(\n        ownerAddress: address,\n        minterAddress: address,\n        jettonWalletCode: cell,\n    ): AutoDeployAddress {\n        val emptyWalletStorage: WalletStorage = {\n            jettonBalance: 0,\n            ownerAddress,\n            minterAddress,\n        };\n\n        return {\n            stateInit: {\n                code: jettonWalletCode,\n                data: emptyWalletStorage.toCell(),\n            }\n        }\n    }\n\n    fun calcAddressOfJettonWallet(\n        ownerAddress: address,\n        minterAddress: address,\n        jettonWalletCode: cell,\n    ) {\n        val jwDeployed = calcDeployedJettonWallet(\n            ownerAddress,\n            minterAddress,\n            jettonWalletCode,\n        );\n        return jwDeployed.calculateAddress()\n    }\n    ```\n  </Accordion>\n\n  <Accordion\n    title=\"jetton-minter-contract.tolk\"\n  >\n    ```tolk\n    import \"@stdlib/gas-payments\"\n    import \"errors\"\n    import \"jetton-utils\"\n    import \"messages\"\n    import \"storage\"\n    import \"fees-management\"\n\n    type AllowedMessageToMinter =\n        | MintNewJettons\n        | BurnNotificationForMinter\n        | RequestWalletAddress\n        | ChangeMinterAdmin\n        | ChangeMinterContent\n\n    fun onInternalMessage(in: InMessage) {\n        val msg = lazy AllowedMessageToMinter.fromSlice(in.body);\n\n        match (msg) {\n            BurnNotificationForMinter => {\n                var storage = lazy MinterStorage.load();\n                assert (in.senderAddress ==\n                    calcAddressOfJettonWallet(\n                        msg.burnInitiator,\n                        contract.getAddress(),\n                        storage.jettonWalletCode,\n                    )) throw ERR_UNAUTHORIZED_BURN;\n\n                storage.totalSupply -= msg.jettonAmount;\n                storage.save();\n\n                if (msg.sendExcessesTo == null) {\n                    return;\n                }\n\n                val excessesMsg = createMessage({\n                    bounce: BounceMode.NoBounce,\n                    dest: msg.sendExcessesTo,\n                    value: 0,\n                    body: ReturnExcessesBack {\n                        queryId: msg.queryId\n                    }\n                });\n                excessesMsg.send(\n                    SEND_MODE_IGNORE_ERRORS +\n                    SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE\n                );\n            }\n\n            RequestWalletAddress => {\n                assert (in.valueCoins >\n                    in.originalForwardFee + MINIMAL_MESSAGE_VALUE_BOUND)\n                    throw ERR_NOT_ENOUGH_AMOUNT_TO_RESPOND;\n\n                var respondOwnerAddress: Cell<address>? = msg.includeOwnerAddress\n                    ? msg.ownerAddress.toCell()\n                    : null;\n\n                var walletAddress: address? = null;\n                if (msg.ownerAddress.getWorkchain() == BASECHAIN) {\n                    var storage = lazy MinterStorage.load();\n                    walletAddress = calcAddressOfJettonWallet(\n                        msg.ownerAddress,\n                        contract.getAddress(),\n                        storage.jettonWalletCode,\n                    );\n                }\n\n                val respondMsg = createMessage({\n                    bounce: BounceMode.Only256BitsOfBody,\n                    dest: in.senderAddress,\n                    value: 0,\n                    body: ResponseWalletAddress {\n                        queryId: msg.queryId,\n                        jettonWalletAddress: walletAddress,\n                        ownerAddress: respondOwnerAddress,\n                    }\n                });\n                respondMsg.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE);\n            }\n\n            MintNewJettons => {\n                var storage = lazy MinterStorage.load();\n                assert (in.senderAddress == storage.adminAddress)\n                    throw ERR_NOT_FROM_ADMIN;\n\n                var internalTransferMsg = lazy msg.internalTransferMsg.load();\n                storage.totalSupply += internalTransferMsg.jettonAmount;\n                storage.save();\n\n                val deployMsg = createMessage({\n                    bounce: BounceMode.Only256BitsOfBody,\n                    dest: calcDeployedJettonWallet(\n                        msg.mintRecipient,\n                        contract.getAddress(),\n                        storage.jettonWalletCode,\n                    ),\n                    value: msg.tonAmount,\n                    // a newly-deployed wallet contract will immediately handle it\n                    body: msg.internalTransferMsg,\n                });\n                deployMsg.send(SEND_MODE_PAY_FEES_SEPARATELY);\n            }\n\n            ChangeMinterAdmin => {\n                var storage = lazy MinterStorage.load();\n                assert (in.senderAddress == storage.adminAddress)\n                    throw ERR_NOT_FROM_ADMIN;\n                storage.adminAddress = msg.newAdminAddress;\n                storage.save();\n            }\n\n            ChangeMinterContent => {\n                var storage = lazy MinterStorage.load();\n                assert (in.senderAddress == storage.adminAddress)\n                    throw ERR_NOT_FROM_ADMIN;\n                storage.content = msg.newContent;\n                storage.save();\n            }\n\n            else => {\n                // ignore empty messages, \"wrong opcode\" for others\n                assert (in.body.isEmpty()) throw 0xFFFF\n            }\n        }\n    }\n\n    struct JettonDataReply {\n        totalSupply: int\n        mintable: bool\n        adminAddress: address\n        jettonContent: cell\n        jettonWalletCode: cell\n    }\n\n    get fun get_jetton_data(): JettonDataReply {\n        val storage = lazy MinterStorage.load();\n\n        return {\n            totalSupply: storage.totalSupply,\n            mintable: true,\n            adminAddress: storage.adminAddress,\n            jettonContent: storage.content,\n            jettonWalletCode: storage.jettonWalletCode,\n        }\n    }\n\n    get fun get_wallet_address(ownerAddress: address): address {\n        val storage = lazy MinterStorage.load();\n        return calcAddressOfJettonWallet(\n            ownerAddress,\n            contract.getAddress(),\n            storage.jettonWalletCode,\n        );\n    }\n    ```\n  </Accordion>\n\n  <Accordion\n    title=\"jetton-wallet-contract.tolk\"\n  >\n    ```tolk\n    import \"@stdlib/gas-payments\"\n    import \"errors\"\n    import \"jetton-utils\"\n    import \"messages\"\n    import \"fees-management\"\n    import \"storage\"\n\n    type AllowedMessageToWallet =\n        | AskToTransfer\n        | AskToBurn\n        | InternalTransferStep\n\n    type BounceOpToHandle = InternalTransferStep | BurnNotificationForMinter\n\n    fun onBouncedMessage(in: InMessageBounced) {\n        in.bouncedBody.skipBouncedPrefix();\n\n        val msg = lazy BounceOpToHandle.fromSlice(in.bouncedBody);\n        val restoreAmount = match (msg) {\n            // fetching jettonAmount is safe because\n            // it is at the beginning of the message body\n            InternalTransferStep => msg.jettonAmount,\n            BurnNotificationForMinter => msg.jettonAmount,\n        };\n\n        var storage = lazy WalletStorage.load();\n        storage.jettonBalance += restoreAmount;\n        storage.save();\n    }\n\n    fun onInternalMessage(in: InMessage) {\n        val msg = lazy AllowedMessageToWallet.fromSlice(in.body);\n\n        match (msg) {\n            InternalTransferStep => {\n                var storage = lazy WalletStorage.load();\n                if (in.senderAddress != storage.minterAddress) {\n                    assert (in.senderAddress ==\n                        calcAddressOfJettonWallet(\n                            msg.transferInitiator!,\n                            storage.minterAddress,\n                            contract.getCode(),\n                        )) throw ERR_INVALID_WALLET;\n                }\n                storage.jettonBalance += msg.jettonAmount;\n                storage.save();\n\n                var msgValue = in.valueCoins;\n                var tonBalanceBeforeMsg = contract.getOriginalBalance() - msgValue;\n                var storageFee = MIN_TONS_FOR_STORAGE - min(\n                    tonBalanceBeforeMsg,\n                    MIN_TONS_FOR_STORAGE,\n                );\n                msgValue -= (storageFee + JETTON_WALLET_GAS_CONSUMPTION);\n\n                if (msg.forwardTonAmount) {\n                    msgValue -= (msg.forwardTonAmount + in.originalForwardFee);\n\n                    val notifyOwnerMsg = createMessage({\n                        // cause receiver can have uninitialized contract\n                        bounce: BounceMode.NoBounce,\n                        dest: storage.ownerAddress,\n                        value: msg.forwardTonAmount,\n                        body: TransferNotificationForRecipient {\n                            queryId: msg.queryId,\n                            jettonAmount: msg.jettonAmount,\n                            transferInitiator: msg.transferInitiator,\n                            forwardPayload: msg.forwardPayload\n                        }\n                    });\n                    notifyOwnerMsg.send(SEND_MODE_PAY_FEES_SEPARATELY);\n                }\n\n                if (msg.sendExcessesTo != null & (msgValue > 0)) {\n                    val excessesMsg = createMessage({\n                        bounce: BounceMode.NoBounce,\n                        dest: msg.sendExcessesTo!,\n                        value: msgValue,\n                        body: ReturnExcessesBack {\n                            queryId: msg.queryId\n                        }\n                    });\n                    excessesMsg.send(SEND_MODE_IGNORE_ERRORS);\n                }\n            }\n\n            AskToTransfer => {\n                assert (msg.forwardPayload.remainingBitsCount())\n                    throw ERR_INVALID_PAYLOAD;\n                assert (msg.transferRecipient.getWorkchain() == BASECHAIN)\n                    throw ERR_WRONG_WORKCHAIN;\n\n                var storage = lazy WalletStorage.load();\n                assert (in.senderAddress == storage.ownerAddress)\n                    throw ERR_NOT_FROM_OWNER;\n                assert (storage.jettonBalance >= msg.jettonAmount)\n                    throw ERR_NOT_ENOUGH_BALANCE;\n                storage.jettonBalance -= msg.jettonAmount;\n                storage.save();\n\n                var forwardedMessagesCount = msg.forwardTonAmount ? 2 : 1;\n                assert (in.valueCoins >\n                    msg.forwardTonAmount +\n                    // 3 messages: wal1->wal2,  wal2->owner, wal2->response\n                    // but last one is optional (it is ok if it fails)\n                    forwardedMessagesCount * in.originalForwardFee +\n                    (2 * JETTON_WALLET_GAS_CONSUMPTION + MIN_TONS_FOR_STORAGE)\n                ) throw ERR_NOT_ENOUGH_TON;\n\n                val deployMsg = createMessage({\n                    bounce: BounceMode.Only256BitsOfBody,\n                    dest: calcDeployedJettonWallet(\n                        msg.transferRecipient,\n                        storage.minterAddress,\n                        contract.getCode(),\n                    ),\n                    value: 0,\n                    body: InternalTransferStep {\n                        queryId: msg.queryId,\n                        jettonAmount: msg.jettonAmount,\n                        transferInitiator: storage.ownerAddress,\n                        sendExcessesTo: msg.sendExcessesTo,\n                        forwardTonAmount: msg.forwardTonAmount,\n                        forwardPayload: msg.forwardPayload,\n                    }\n                });\n                deployMsg.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE);\n            }\n\n            AskToBurn => {\n                var storage = lazy WalletStorage.load();\n                assert (in.senderAddress == storage.ownerAddress)\n                    throw ERR_NOT_FROM_OWNER;\n                assert (storage.jettonBalance >= msg.jettonAmount)\n                    throw ERR_NOT_ENOUGH_BALANCE;\n                storage.jettonBalance -= msg.jettonAmount;\n                storage.save();\n\n                val notifyMinterMsg = createMessage({\n                    bounce: BounceMode.Only256BitsOfBody,\n                    dest: storage.minterAddress,\n                    value: 0,\n                    body: BurnNotificationForMinter {\n                        queryId: msg.queryId,\n                        jettonAmount: msg.jettonAmount,\n                        burnInitiator: storage.ownerAddress,\n                        sendExcessesTo: msg.sendExcessesTo,\n                    }\n                });\n                notifyMinterMsg.send(\n                    SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE\n                    | SEND_MODE_BOUNCE_ON_ACTION_FAIL\n                );\n            }\n\n            else => {\n                // ignore empty messages, \"wrong opcode\" for others\n                assert (in.body.isEmpty()) throw 0xFFFF\n            }\n        }\n    }\n\n    struct JettonWalletDataReply {\n        jettonBalance: coins\n        ownerAddress: address\n        minterAddress: address\n        jettonWalletCode: cell\n    }\n\n    get fun get_wallet_data(): JettonWalletDataReply {\n        val storage = lazy WalletStorage.load();\n\n        return {\n            jettonBalance: storage.jettonBalance,\n            ownerAddress: storage.ownerAddress,\n            minterAddress: storage.minterAddress,\n            jettonWalletCode: contract.getCode(),\n        }\n    }\n    ```\n  </Accordion>\n</AccordionGroup>\n\n## NFT\n\nSource directory: [`contracts_Tolk/02_nft`](https://github.com/ton-blockchain/tolk-bench/tree/cb9648bdf936f88eb9d773d9058405f74a1e24d9/contracts_Tolk/02_nft).\n\n<FileTree\n  items={[{\n    kind: \"folder\",\n    name: \"02_nft/\",\n    items: [\"errors.tolk\", \"fees-management.tolk\", \"storage.tolk\", \"messages.tolk\", \"nft-collection-contract.tolk\", \"nft-item-contract.tolk\"]\n  }]}\n/>\n\nSome files in the source directory are not runnable on their own and depend on others. Keep all the listed files together.\n\n<AccordionGroup>\n  <Accordion\n    title=\"errors.tolk\"\n  >\n    ```tolk\n    const ERROR_NOT_FROM_ADMIN = 401\n    const ERROR_NOT_FROM_OWNER = 401\n    const ERROR_NOT_FROM_COLLECTION = 405\n    const ERROR_BATCH_LIMIT_EXCEEDED = 399\n    const ERROR_INVALID_ITEM_INDEX = 402\n    const ERROR_INCORRECT_FORWARD_PAYLOAD = 708\n    const ERROR_INVALID_WORKCHAIN = 333\n    const ERROR_TOO_SMALL_REST_AMOUNT = 402\n    ```\n  </Accordion>\n\n  <Accordion\n    title=\"fees-management.tolk\"\n  >\n    ```tolk\n    const MIN_TONS_FOR_STORAGE = ton(\"0.05\")\n    ```\n  </Accordion>\n\n  <Accordion\n    title=\"storage.tolk\"\n  >\n    ```tolk\n    // SnakeString describes a (potentially long) string inside a cell;\n    // short strings are stored as-is, like \"my-picture.png\";\n    // long strings are nested refs, like \"xxxx\".ref(\"yyyy\".ref(\"zzzz\"))\n    type SnakeString = slice\n\n    fun SnakeString.unpackFromSlice(mutate s: slice) {\n        // SnakeString can be only the last — it's just the remainder;\n        // For correctness, it's better to validate it has no more refs:\n        //   assert (s.remainingRefsCount() <= 1) throw 5;\n        // Since it is matching the original FunC implementation,\n        // checks are not kept\n        val snakeRemainder = s;\n        s = createEmptySlice();     // no more left to read\n        return snakeRemainder\n    }\n\n    fun SnakeString.packToBuilder(self, mutate b: builder) {\n        b.storeSlice(self)\n    }\n\n    struct RoyaltyParams {\n        numerator: uint16\n        denominator: uint16\n        royaltyAddress: address\n    }\n\n    struct NftCollectionStorage {\n        adminAddress: address\n        nextItemIndex: uint64\n        content: Cell<CollectionContent>\n        nftItemCode: cell\n        royaltyParams: Cell<RoyaltyParams>\n    }\n\n    struct CollectionContent {\n        collectionMetadata: cell\n        commonContent: Cell<SnakeString>\n    }\n\n    struct NftItemStorage {\n        itemIndex: uint64\n        collectionAddress: address\n        ownerAddress: address\n        content: Cell<SnakeString>\n    }\n\n    struct NftItemStorageNotInitialized {\n        itemIndex: uint64\n        collectionAddress: address\n    }\n\n    fun NftCollectionStorage.load() {\n        return NftCollectionStorage.fromCell(contract.getData())\n    }\n\n    fun NftCollectionStorage.save(self) {\n        contract.setData(self.toCell())\n    }\n\n    // Actual storage of an NFT item is tricky: it's either initialized or not;\n    // After NFT has been inited, it's represented as `NftItemStorage`;\n    // Before initialization, it has only itemIndex and collectionAddress;\n    // Hence, detect whether it's inited or not during parsing.\n    struct NftItemStorageMaybeNotInitialized {\n        contractData: slice\n    }\n\n    // how do we detect whether it's initialized or not?\n    // the answer: when \"inited\", we store `content` (cell),\n    // so, we have a ref, and for uninited, we don't have a ref\n    fun NftItemStorageMaybeNotInitialized.isInitialized(self) {\n        val hasContent = self.contractData.remainingRefsCount();\n        return hasContent\n    }\n\n    fun NftItemStorageMaybeNotInitialized.parseNotInitialized(self) {\n        return NftItemStorageNotInitialized.fromSlice(self.contractData)\n    }\n\n    fun NftItemStorageMaybeNotInitialized.parseInitialized(self) {\n        return NftItemStorage.fromSlice(self.contractData)\n    }\n\n    fun startLoadingNftItemStorage(): NftItemStorageMaybeNotInitialized {\n        return {\n            contractData: contract.getData().beginParse()\n        }\n    }\n\n    fun NftItemStorage.save(self) {\n        contract.setData(self.toCell())\n    }\n\n    fun calcDeployedNftItem(\n        itemIndex: uint64,\n        collectionAddress: address,\n        nftItemCode: cell,\n    ): AutoDeployAddress {\n        val emptyNftItemStorage: NftItemStorageNotInitialized = {\n            itemIndex,\n            collectionAddress,\n        };\n\n        return {\n            stateInit: {\n                code: nftItemCode,\n                data: emptyNftItemStorage.toCell()\n            }\n        }\n    }\n    ```\n  </Accordion>\n\n  <Accordion\n    title=\"messages.tolk\"\n  >\n    ```tolk\n    import \"storage\"\n\n    struct NftItemInitAtDeployment {\n        ownerAddress: address\n        content: Cell<SnakeString>\n    }\n\n    struct (0x693d3950) RequestRoyaltyParams {\n        queryId: uint64\n    }\n\n    struct (0xa8cb00ad) ResponseRoyaltyParams {\n        queryId: uint64\n        royaltyParams: RoyaltyParams\n    }\n\n    struct (0x00000001) DeployNft {\n        queryId: uint64\n        itemIndex: uint64\n        attachTonAmount: coins\n        initParams: Cell<NftItemInitAtDeployment>\n    }\n\n    struct (0x00000002) BatchDeployNfts {\n        queryId: uint64\n        deployList: map<uint64, BatchDeployDictItem>\n    }\n\n    struct BatchDeployDictItem {\n        attachTonAmount: coins\n        initParams: Cell<NftItemInitAtDeployment>\n    }\n\n    struct (0x00000003) ChangeCollectionAdmin {\n        queryId: uint64\n        newAdminAddress: address\n    }\n\n    struct (0x2fcb26a2) RequestStaticData {\n        queryId: uint64\n    }\n\n    struct (0x8b771735) ResponseStaticData {\n        queryId: uint64\n        itemIndex: uint256\n        collectionAddress: address\n    }\n\n    struct (0x05138d91) NotificationForNewOwner {\n        queryId: uint64\n        oldOwnerAddress: address\n        payload: RemainingBitsAndRefs\n    }\n\n    struct (0xd53276db) ReturnExcessesBack {\n        queryId: uint64\n    }\n\n    struct (0x5fcc3d14) AskToChangeOwnership {\n        queryId: uint64\n        newOwnerAddress: address\n        sendExcessesTo: address?\n        customPayload: dict\n        forwardTonAmount: coins\n        forwardPayload: RemainingBitsAndRefs\n    }\n    ```\n  </Accordion>\n\n  <Accordion\n    title=\"nft-collection-contract.tolk\"\n  >\n    ```tolk\n    import \"errors\"\n    import \"storage\"\n    import \"messages\"\n\n    fun deployNftItem(\n        itemIndex: int,\n        nftItemCode: cell,\n        attachTonAmount: coins,\n        initParams: Cell<NftItemInitAtDeployment>,\n    ) {\n        val deployMsg = createMessage({\n            bounce: BounceMode.Only256BitsOfBody,\n            dest: calcDeployedNftItem(\n                itemIndex,\n                contract.getAddress(),\n                nftItemCode,\n            ),\n            value: attachTonAmount,\n            body: initParams,\n        });\n        deployMsg.send(SEND_MODE_PAY_FEES_SEPARATELY);\n    }\n\n    type AllowedMessageToNftCollection =\n        | RequestRoyaltyParams\n        | DeployNft\n        | BatchDeployNfts\n        | ChangeCollectionAdmin\n\n    fun onInternalMessage(in: InMessage) {\n        val msg = lazy AllowedMessageToNftCollection.fromSlice(in.body);\n\n        match (msg) {\n            DeployNft => {\n                var storage = lazy NftCollectionStorage.load();\n                assert (in.senderAddress == storage.adminAddress)\n                    throw ERROR_NOT_FROM_ADMIN;\n                assert (msg.itemIndex <= storage.nextItemIndex)\n                    throw ERROR_INVALID_ITEM_INDEX;\n\n                var isLast = msg.itemIndex == storage.nextItemIndex;\n                deployNftItem(\n                    msg.itemIndex,\n                    storage.nftItemCode,\n                    msg.attachTonAmount,\n                    msg.initParams,\n                );\n                if (isLast) {\n                    storage.nextItemIndex += 1;\n                    storage.save();\n                }\n            }\n\n            RequestRoyaltyParams => {\n                val storage = lazy NftCollectionStorage.load();\n                val respondMsg = createMessage({\n                    bounce: BounceMode.NoBounce,\n                    dest: in.senderAddress,\n                    value: 0,\n                    body: ResponseRoyaltyParams {\n                        queryId: msg.queryId,\n                        royaltyParams: storage.royaltyParams.load(),\n                    }\n                });\n                respondMsg.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE);\n            }\n\n            BatchDeployNfts => {\n                var storage = lazy NftCollectionStorage.load();\n                assert (in.senderAddress == storage.adminAddress)\n                    throw ERROR_NOT_FROM_ADMIN;\n\n                var counter = 0;\n                var r = msg.deployList.findFirst();\n                while (r.isFound) {\n                    counter += 1;\n                    // due to limits of action list size\n                    assert (counter < 250) throw ERROR_BATCH_LIMIT_EXCEEDED;\n\n                    val itemIndex = r.getKey();\n                    assert (itemIndex <= storage.nextItemIndex)\n                        throw ERROR_NOT_FROM_ADMIN + counter;\n\n                    val dictItem = r.loadValue();\n                    deployNftItem(\n                        itemIndex,\n                        storage.nftItemCode,\n                        dictItem.attachTonAmount,\n                        dictItem.initParams,\n                    );\n                    if (itemIndex == storage.nextItemIndex) {\n                        storage.nextItemIndex += 1;\n                    }\n\n                    r = msg.deployList.iterateNext(r);\n                }\n                storage.save();\n            }\n\n            ChangeCollectionAdmin => {\n                var storage = lazy NftCollectionStorage.load();\n                assert (in.senderAddress == storage.adminAddress)\n                    throw ERROR_NOT_FROM_ADMIN;\n                storage.adminAddress = msg.newAdminAddress;\n                storage.save();\n            }\n\n            else => {\n                // ignore empty messages, \"wrong opcode\" for others\n                assert (in.body.isEmpty()) throw 0xFFFF\n            }\n        }\n    }\n\n    struct CollectionDataReply {\n        nextItemIndex: int\n        collectionMetadata: cell\n        adminAddress: address\n    }\n\n    struct (0x01) OffchainMetadataReply {\n        string: SnakeString\n    }\n\n    get fun get_collection_data(): CollectionDataReply {\n        val storage = lazy NftCollectionStorage.load();\n        val content = lazy storage.content.load();\n\n        return {\n            nextItemIndex: storage.nextItemIndex,\n            collectionMetadata: content.collectionMetadata,\n            adminAddress: storage.adminAddress,\n        }\n    }\n\n    get fun get_nft_address_by_index(itemIndex: int): address {\n        val storage = lazy NftCollectionStorage.load();\n        val nftDeployed = calcDeployedNftItem(\n            itemIndex,\n            contract.getAddress(),\n            storage.nftItemCode,\n        );\n        return nftDeployed.calculateAddress();\n    }\n\n    get fun royalty_params(): RoyaltyParams {\n        val storage = lazy NftCollectionStorage.load();\n        return storage.royaltyParams.load();\n    }\n\n    get fun get_nft_content(\n        itemIndex: int,\n        individualNftContent: Cell<SnakeString>,\n    ): Cell<OffchainMetadataReply> {\n        val storage = lazy NftCollectionStorage.load();\n        val content = lazy storage.content.load();\n\n        // construct a responce from \"common content\" and \"individual content\";\n        // for example:\n        // common content = \"https://site.org/my-collection/\"\n        // individual nft = \"my-picture-123.png\" (a long, snake-encoded string)\n        return OffchainMetadataReply {\n            string: beginCell()\n                // assume it's short (no refs)\n                .storeSlice(content.commonContent.load())\n                // so, it's the first ref (snake encoding)\n                .storeRef(individualNftContent)\n                .endCell().beginParse()\n        }.toCell()\n    }\n    ```\n  </Accordion>\n\n  <Accordion\n    title=\"nft-item-contract.tolk\"\n  >\n    ```tolk\n    import \"@stdlib/gas-payments\"\n    import \"errors\"\n    import \"storage\"\n    import \"messages\"\n    import \"fees-management\"\n\n    type AllowedMessageToNftItem =\n        | AskToChangeOwnership\n        | RequestStaticData\n\n    fun onInternalMessage(in: InMessage) {\n        var loadingStorage = startLoadingNftItemStorage();\n        if (!loadingStorage.isInitialized()) {\n            val uninitedSt = loadingStorage.parseNotInitialized();\n            assert (in.senderAddress == uninitedSt.collectionAddress)\n                throw ERROR_NOT_FROM_COLLECTION;\n\n            // using a message from collection,\n            // convert \"uninitialized\" to \"initialized\" state\n            val initParams = NftItemInitAtDeployment.fromSlice(in.body);\n            val storage: NftItemStorage = {\n                itemIndex: uninitedSt.itemIndex,\n                collectionAddress: uninitedSt.collectionAddress,\n                ownerAddress: initParams.ownerAddress,\n                content: initParams.content,\n            };\n            storage.save();\n            return;\n        }\n\n        var storage = loadingStorage.parseInitialized();\n\n        val msg = lazy AllowedMessageToNftItem.fromSlice(in.body);\n\n        match (msg) {\n            AskToChangeOwnership => {\n                assert (in.senderAddress == storage.ownerAddress)\n                    throw ERROR_NOT_FROM_OWNER;\n                assert (msg.forwardPayload.remainingBitsCount())\n                    throw ERROR_INCORRECT_FORWARD_PAYLOAD;\n                assert (msg.newOwnerAddress.getWorkchain() == BASECHAIN)\n                    throw ERROR_INVALID_WORKCHAIN;\n\n                val fwdFee = in.originalForwardFee;\n                var restAmount = contract.getOriginalBalance() - MIN_TONS_FOR_STORAGE;\n                if (msg.forwardTonAmount) {\n                    restAmount -= (msg.forwardTonAmount + fwdFee);\n                }\n                if (msg.sendExcessesTo != null) {\n                    assert (msg.sendExcessesTo.getWorkchain() == BASECHAIN)\n                        throw ERROR_INVALID_WORKCHAIN;\n                    restAmount -= fwdFee;\n                }\n\n                // base nft spends fixed amount of gas, will not check for response\n                assert (restAmount >= 0) throw ERROR_TOO_SMALL_REST_AMOUNT;\n\n                if (msg.forwardTonAmount) {\n                    val ownershipMsg = createMessage({\n                        bounce: BounceMode.NoBounce,\n                        dest: msg.newOwnerAddress,\n                        value: msg.forwardTonAmount,\n                        body: NotificationForNewOwner {\n                            queryId: msg.queryId,\n                            oldOwnerAddress: storage.ownerAddress,\n                            payload: msg.forwardPayload,\n                        }\n                    });\n                    ownershipMsg.send(SEND_MODE_PAY_FEES_SEPARATELY);\n                }\n                if (msg.sendExcessesTo != null) {\n                    val excessesMsg = createMessage({\n                        bounce: BounceMode.NoBounce,\n                        dest: msg.sendExcessesTo,\n                        value: restAmount,\n                        body: ReturnExcessesBack {\n                            queryId: msg.queryId,\n                        }\n                    });\n                    excessesMsg.send(SEND_MODE_PAY_FEES_SEPARATELY);\n                }\n\n                storage.ownerAddress = msg.newOwnerAddress;\n                storage.save();\n            }\n\n            RequestStaticData => {\n                val respondMsg = createMessage({\n                    bounce: BounceMode.NoBounce,\n                    dest: in.senderAddress,\n                    value: 0,\n                    // The `itemIndex` was encoded as 256-bit in FunC implementation,\n                    // we do the same here to pass FunC tests;\n                    // As such, response becomes too long (64 + 256 + address),\n                    // and the compiler will create a ref;\n                    // To circumvent that, let's force the compiler to inline the body,\n                    // since it is guaranteed that with value (coins) = 0,\n                    // it will always fit into a message cell directly.\n                    body: UnsafeBodyNoRef {\n                        forceInline: ResponseStaticData {\n                            queryId: msg.queryId,\n                            itemIndex: storage.itemIndex as uint256,\n                            collectionAddress: storage.collectionAddress,\n                        }\n                    }\n                });\n                respondMsg.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE);\n            }\n\n            else => {\n                // ignore empty messages, \"wrong opcode\" for others\n                assert (in.body.isEmpty()) throw 0xFFFF\n            }\n        }\n    }\n\n    struct NftDataReply {\n        isInitialized: bool\n        itemIndex: int\n        collectionAddress: address\n        ownerAddress: address? = null\n        content: Cell<SnakeString>? = null\n    }\n\n    get fun get_nft_data(): NftDataReply {\n        var loadingStorage = startLoadingNftItemStorage();\n        if (!loadingStorage.isInitialized()) {\n            val uninitedSt = loadingStorage.parseNotInitialized();\n            return {\n                isInitialized: false,\n                itemIndex: uninitedSt.itemIndex,\n                collectionAddress: uninitedSt.collectionAddress,\n            }\n        }\n\n        val storage = loadingStorage.parseInitialized();\n        return {\n            isInitialized: true,\n            itemIndex: storage.itemIndex,\n            collectionAddress: storage.collectionAddress,\n            ownerAddress: storage.ownerAddress,\n            content: storage.content,\n        }\n    }\n    ```\n  </Accordion>\n</AccordionGroup>\n\n## See also\n\n- [Tolk language overview](/languages/tolk/overview)\n- [Tolk vs FunC](/languages/tolk/from-func/tolk-vs-func)\n"
  },
  {
    "path": "languages/tolk/features/asm-functions.mdx",
    "content": "---\ntitle: \"Assembler functions\"\n---\n\nFunctions in Tolk can be defined using assembler code. It's a low-level feature that requires understanding of stack layout, [Fift](/languages/fift/overview), and [TVM](/tvm/overview).\n\n## Standard functions\n\nStandard functions are `asm` wrappers. Many functions from the [standard library](/languages/tolk/features/standard-library) are translated to the Fift assembler directly. For example, TVM has a `HASHCU` instruction, which is \"calculate hash of a cell\". It pops a cell from the stack and pushes an integer in the range 0 to 2<sup>256</sup>-1. Therefore, the method `cell.hash` is defined:\n\n```tolk\n@pure\nfun cell.hash(self): uint256\n    asm \"HASHCU\"\n```\n\nThe type system guarantees that when this method is invoked, a TVM `CELL` will be the topmost element (`self`).\n\n## Custom functions\n\n```tolk\n@pure\nfun incThenNegate(v: int): int\n    asm \"INC\" \"NEGATE\"\n```\n\nCustom functions are declared in the same way. A call `incThenNegate(10)` is translated into those commands.\n\nSpecify `@pure` if the body does not modify TVM state or throw exceptions.\n\nThe return type for `asm` functions is mandatory. For regular functions, it's inferred from `return` statements.\n\n## Multi-line `asm`\n\nTo embed a multi-line command, use triple quotes:\n\n```tolk\nfun hashStateInit(code: cell, data: cell): uint256 asm \"\"\"\n    DUP2\n    HASHCU\n    // ...\n    ONE HASHEXT_SHA256\n\"\"\"\n```\n\nIt is treated as a single string and inserted as-is into Fift output. It can contain `//` comments valid for Fift.\n\n## Stack order for multiple slots\n\nWhen calling a function, arguments are pushed in the declared order. The last parameter becomes the topmost stack element.\n\nIf an instruction produces several slots, the resulting type should be a tensor or a struct.\n\nFor example, write a function `abs2` that calculates `abs()` for two values at once: `abs2(-5, -10)` = `(5, 10)`. The comments show the stack layout for each step. The rightmost value represents the top of the stack.\n\n```tolk\nfun abs2(v1: int, v2: int): (int, int)\n    asm             // v1 v2\n        \"ABS\"       // v1 v2_abs\n        \"SWAP\"      // v2_abs v1\n        \"ABS\"       // v2_abs v1_abs\n        \"SWAP\"      // v1_abs v2_abs\n```\n\n## Stack-based argument reordering\n\nSometimes a function accepts parameters in an order different from what a TVM instruction expects. For example, `GETSTORAGEFEE` expects the parameters in the order cells, bits, seconds, and workchain. For a clearer API, the function should take the workchain as its first argument. To reorder stack positions, use the `asm(<INPUT_ORDER>)` syntax:\n\n```tolk\nfun calculateStorageFee(workchain: int8, seconds: int, bits: int, cells: int): coins\n    asm(cells bits seconds workchain) \"GETSTORAGEFEE\"\n```\n\nSimilarly for return values. If multiple slots are returned and must be reordered to match typing, use the `asm(-> <RETURN_ORDER>)` syntax:\n\n```tolk\nfun asmLoadCoins(s: slice): (slice, int)\n    asm(-> 1 0) \"LDVARUINT16\"\n```\n\nBoth the input and output sides can be combined: `asm(<INPUT_ORDER> -> <RETURN_ORDER>)`. Reordering is mostly used with `mutate` variables.\n\n## `mutate` and `self` in assembler functions\n\nThe `mutate` keyword, which makes a parameter [mutable](/languages/tolk/syntax/mutability), implicitly returns updated values through the stack in both regular and `asm` functions.\n\nConsider regular functions first. The compiler applies all transformations automatically.\n\n```tolk\n// transformed to: \"returns (int, void)\"\nfun increment(mutate x: int): void {\n    x += 1;\n    // a hidden \"return x\" is inserted\n}\n\nfun demo() {\n    // transformed to: (newX, _) = increment(x); x = newX\n    increment(mutate x);\n}\n```\n\nTo implement `increment()` using `asm`:\n\n```tolk\nfun increment(mutate x: int): void\n    asm \"INC\"\n```\n\nThe function returns type `void`. The type system treats it as returning no value. However, `INC` leaves a number on the stack — that's a hidden \"return x\" from a manual implementation.\n\nSimilarly, it works for `mutate self`. An `asm` function should place `newSelf` on the stack before the actual result:\n\n```tolk\n// \"TPUSH\" pops (tuple) and pushes (newTuple);\n// so, newSelf = newTuple, and return `void` (syn. \"unit\")\nfun tuple.push<X>(mutate self, value: X): void\n    asm \"TPUSH\"\n\n// \"LDU\" pops (slice) and pushes (int, newSlice);\n// with `asm(-> 1 0)`, make it (newSlice, int);\n// so, newSelf = newSlice, and return `int`\nfun slice.loadMessageFlags(mutate self): int\n    asm(-> 1 0) \"4 LDU\"\n```\n\nTo return `self` for chaining, specify a return type:\n\n```tolk\n// \"STU\" pops (int, builder) and pushes (newBuilder);\n// with `asm(op self)`, put arguments to correct order;\n// so, newSelf = newBuilder, and return `void`;\n// but to make it chainable, `self` instead of `void`\nfun builder.storeMessageOp(mutate self, op: int): self\n    asm(op self) \"32 STU\"\n```\n\n## `asm` is compatible with structures\n\nMethods on structures can be declared in `asm` when their field layout is known. Fields are placed sequentially. For example, a structure with a single field is equivalent to that field.\n\n```tolk\nstruct MyCell {\n    private c: cell\n}\n\n@pure\nfun MyCell.hash(self): uint256\n    asm \"HASHCU\"\n```\n\nStructures can also be used instead of tensors as return types. It appears in `map<K, V>` methods on TVM dictionaries:\n\n```tolk\nstruct MapLookupResult<TValue> {\n    private readonly rawSlice: slice?\n    isFound: bool\n}\n\n@pure\nfun map<K, V>.get(self, key: K): MapLookupResult<V>\n    builtin\n// it produces `DICTGET` and similar, which push\n// (slice -1) or (null 0) — the shape of MapLookupResult\n```\n\n## Generics in `asm` should be single-slot\n\nConsider `tuple.push`. The `TPUSH` instruction pops `(tuple, someVal)` and pushes `(newTuple)`. It works with any `T` that occupies a single stack slot, such as `int`, `int8`, or `slice`.\n\n```tolk\nfun tuple.push<T>(mutate self, value: T): void\n    asm \"TPUSH\"\n```\n\nHow does `t.push(somePoint)` work? It does not compile, because `Point { x, y }` occupies two stack slots rather than one, which breaks the expected the stack.\n\n```ansi\ndev.tolk:6:5: error: can not call `tuple.push<T>` with T=Point, because it occupies 2 stack slots in TVM, not 1\n\n    // in function `main`\n   6 |     t.push(somePoint);\n     |     ^^^^^^\n```\n\nOnly regular and built-in generics support variadic type arguments. `asm` do not.\n\n## Do not use `asm` for micro-optimizations\n\nUse `asm` only for rarely used TVM instructions that are not covered by the standard library, such as manual merkle-proof parsing or extended hash calculations.\n\nUsing `asm` for micro-optimizations is discouraged. The compiler already produces bitcode from clear, structured logic. For example, it automatically inlines simple functions, so one-line helper methods do not add gas overhead.\n\n```tolk\nfun builder.storeFlags(mutate self, flags: int): self {\n    return self.storeUint(32, flags);\n}\n```\n\nA manual `32 STU` sequence provides no advantage in this case. The compiler:\n\n- inlines the function;\n- merges constant `flags` with subsequent stores into `STSLICECONST`.\n"
  },
  {
    "path": "languages/tolk/features/auto-serialization.mdx",
    "content": "---\ntitle: \"Automatic serialization\"\n---\n\nAll data in TON, such as messages, storage, etc., is represented as [cells](/foundations/serialization/cells). The Tolk type system is designed to express cell contents, enabling auto-serialization through `fromCell` and `toCell`:\n\n```tolk\nstruct Point {\n    x: int8\n    y: int8\n}\n\nfun demo() {\n    var value: Point = { x: 10, y: 20 };\n\n    // makes a cell containing \"0A14\" (hex)\n    var c = value.toCell();\n    // back to { x: 10, y: 20 }\n    var p = Point.fromCell(c);\n}\n```\n\n## Type serialization\n\nA `struct` can define [a serialization](/languages/tolk/types/overall-serialization) prefix. 32-bit prefixes are commonly used as opcodes for incoming and outgoing messages:\n\n```tolk\nstruct (0x7362d09c) TransferNotification {\n    queryId: uint64\n    // ...\n}\n```\n\nA prefix is not required to be 32 bits: `0x000F` is a 16-bit prefix, and `0b010` is a 3-bit one.\n\n## Cell references and its types\n\nFields of a struct are serialized one by one. The compiler does not reorder fields or insert implicit references. When data should be stored in a ref, it is done explicitly. A developer controls exactly when each ref is loaded.\n\nThere are two types of references – typed and untyped:\n\n- `Cell<T>` – typed reference; the cell has a known internal structure;\n- `cell` – untyped reference; the cell content is not described.\n\n```tolk\nstruct NftStorage {\n    ownerAddress: address\n    nextItemIndex: uint64\n    content: cell                  // untyped ref\n    royalty: Cell<RoyaltyParams>   // typed ref\n}\n\nstruct RoyaltyParams {\n    numerator: uint16\n    // ...\n}\n```\n\nA call `NftCollectionStorage.fromCell()` is processed as follows:\n\n1. read `address`;\n1. read `uint64`;\n1. read two refs without unpacking them – only their pointers are loaded.\n\n### `Cell<T>`\n\n`Cell<T>` must be loaded to get `T`.\n\nConsider the `royalty` field:\n\n```tolk\nstruct NftStorage {\n    // ...\n    royalty: Cell<RoyaltyParams>\n}\n```\n\nSince it is a cell, `storage.royalty.numerator` is not valid:\n\n```ansi\n// error: `Cell<RoyaltyParams>` has no field `numerator`\nstorage.royalty.numerator;\n                ^^^^^^^^^\n```\n\nTo access `numerator` and other fields, load the reference:\n\n```tolk\nval royalty = storage.royalty.load();   // Cell<T> to T\n// or, alternatively\nval royalty = RoyaltyParams.fromCell(storage.royalty);\n\n// works\nroyalty.numerator;\n```\n\nWhen composing an instance, assign a cell, not an object:\n\n```tolk\nval storage: NftStorage = {\n    // error\n    royalty: RoyaltyParams{ ... }\n    // correct\n    royalty: RoyaltyParams{ ... }.toCell()\n}\n```\n\nSummary:\n\n```tolk\npCell = point.toCell();  // `Point` to `Cell<Point>`\npoint = pCell.load();    // `Cell<Point>` to `Point`\n```\n\n`Cell<address>` or `Cell<int32 | int64>` is supported, `T` is not restricted to structures.\n\n## Custom serializers for custom types\n\nType aliases allow overriding serialization behavior when the required encoding cannot be represented using existing types:\n\n```tolk\ntype MyString = slice\n\nfun MyString.packToBuilder(self, mutate b: builder) {\n    // custom logic\n}\n\nfun MyString.unpackFromSlice(mutate s: slice) {\n    // custom logic\n}\n```\n\nThis mechanism applies only to [type aliases](/languages/tolk/types/overall-serialization#type-aliases). It does not work for structures, enums, etc.\n\n## Behavior with corrupted input\n\n`Point.fromCell(c)` throws an exception if the cell does not contain the required data. The function expects at least 16 bits.\n\n```tolk\nstruct Point {\n    x: int8\n    y: int8\n}\n\nfun demo() {\n    Point.fromCell(createEmptyCell());\n}\n```\n\nTypical failure cases include:\n\n- not enough bits or refs, unless `lazy fromCell` is used;\n- extra data after the expected fields; can be enabled;\n- `address` has an invalid format;\n- `enum` has an invalid value;\n- a mismatched struct prefix;\n- other format inconsistencies.\n\nCommon exception codes:\n\n- [9 – cell underflow](/tvm/exit-codes#9%3A-cell-underflow);\n- [5 – out of range](/tvm/exit-codes#5%3A-integer-out-of-expected-range).\n\nSome behaviors are configurable. For example, to allow extra data:\n\n```tolk\nMyMsg.fromSlice(s, {\n    assertEndAfterReading: false\n})\n```\n\n## Cell packing and unpacking options\n\nBehavior of `fromCell` and `toCell` can be controlled by an option object:\n\n```tolk\nMyMsg.fromCell(c, {\n    // options object\n})\n```\n\nFor deserialization, there are two options:\n\n```tolk\nMyMsg.fromCell(c, {\n    // call `assertEnd` to ensure no remaining data left;\n    // (in other words, the struct describes all data)\n    assertEndAfterReading: true,        // default: true\n\n    // this errCode is thrown if opcode doesn't match,\n    // e.g. for `struct (0x01) A` given input \"88...\",\n    // or for a union type, none of the prefixes match\n    throwIfOpcodeDoesNotMatch: 63,      // default: 63\n})\n```\n\nFor serialization, there is one option:\n\n```tolk\nobj.toCell({\n    // for `bits128` and similar (a slice under the hood),\n    // insert the checks (bits == 128 and refs == 0);\n    // turn off to save gas if you guarantee input is valid;\n    // `intN` are always validated, it's only for `bitsN`\n    skipBitsNValidation: false,         // default: false\n});\n```\n\n### Functions\n\nFunctions such as `fromCell()`, `fromSlice()`, etc., are designed to integrate with low-level features.\n\nFor deserialization, each of the functions can be controlled by `UnpackOptions`:\n\n1. `T.fromCell(c)` parses a cell using `c.beginParse() + fromSlice`:\n\n   ```tolk\n   var storage = NftStorage.fromCell(contract.getData());\n   ```\n\n1. `T.fromSlice(s)` parses a slice; the slice is not mutated:\n\n   ```tolk\n   var msg = CounterIncrement.fromSlice(s);\n   ```\n\n1. `slice.loadAny<T>()` mutates the slice:\n\n   ```tolk\n   var storage = s.loadAny<NftStorage>();\n   var nextNum = s.loadAny<int32>();    // also ok\n   ```\n\n   `options.assertEndAfterReading` is ignored because the function reads from the middle of the slice.\n\n1. `slice.skipAny<T>()`, such as `skipBits()` and similar:\n\n   ```tolk\n   s.skipAny<Point>();    // skips 16 bits\n   ```\n\nFor serialization, each of the functions can be controlled by `PackOptions`.\n\n1. `T.toCell()` works as `beginCell() + serialize + endCell()`:\n\n   ```tolk\n   contract.setData(storage.toCell());\n   ```\n\n1. `builder.storeAny<T>(v)`, such as `storeUint()` and similar:\n\n   ```tolk\n   var b = beginCell()\n          .storeUint(32)\n          .storeAny(msgBody)  // T=MyMsg here\n          .endCell();\n   ```\n\n## `RemainingBitsAndRefs`\n\n`RemainingBitsAndRefs` is a built-in type to get remaining part of a slice when reading. Example:\n\n```tolk\nstruct JettonMessage {\n     // ... some fields\n     forwardPayload: RemainingBitsAndRefs\n}\n```\n\nAfter `JettonMessage.fromCell`, `forwardPayload` contains everything left in the slice after reading the preceding fields. It is an alias for a slice that the compiler treats specially:\n\n```tolk\ntype RemainingBitsAndRefs = slice\n```\n\n## What if data exceeds 1023 bits?\n\nThe Tolk compiler issues a warning if a serializable struct may exceed 1023 bits. This can happen because many types have variable size. For example, `int8?` can be 1 or 9 bits, `coins` can range from 4 to 124 bits, etc. Consider a struct:\n\n```tolk\nstruct MoneyInfo {\n    fixed: bits800\n    wallet1: coins\n    wallet2: coins\n}\n```\n\nSerializing this struct produces a compiler error:\n\n```ansi wrap\nstruct `MoneyInfo` can exceed 1023 bits in serialization (estimated size: 808..1048 bits)\n... (and some instructions)\n```\n\nConsider one of the following actions:\n\n1. Suppress the error.\n\n   If `coins` values are expected to be relatively small and the struct will fit in practice, suppress the error using an annotation:\n\n   ```tolk\n   @overflow1023_policy(\"suppress\")\n   struct MoneyInfo {\n       ...\n   }\n   ```\n\n1. Reorganize the struct by splitting into multiple cells.\n\n   If `coins` values are expected to be relatively large and the data may exceed 1023 bits, extract some fields into a separate cell. For example, store 800 bits as a ref or extract the other two fields:\n\n   ```tolk\n   // extract the first field\n   struct MoneyInfo {\n       fixed: Cell<bits800>\n       wallet1: coins\n       wallet2: coins\n   }\n\n   // or extract the other two fields\n   struct WalletsBalances {\n       wallet1: coins\n       wallet2: coins\n   }\n   struct MoneyInfo {\n       fixed: bits800\n       balances: Cell<WalletsBalances>\n   }\n   ```\n\nFrequently used fields should remain in the struct; less-frequent fields can be moved to a nested ref.\n\n## What if serialization is unavailable?\n\nA common mistake is using `int`. [It cannot be serialized](/languages/tolk/types/numbers#stack-layout-and-serialization); instead, use `int32`, `uint64`, etc.\n\n```tolk\nstruct Storage {\n    owner: address\n    lastTime: int     // mistake is here\n}\n\nfun errDemo() {\n    Storage.fromSlice(\"\");\n}\n```\n\nThe compiler reports:\n\n```ansi\nauto-serialization via fromSlice() is not available for type `Storage`\nbecause field `Storage.lastTime` of type `int` can't be serialized\nbecause type `int` is not serializable, it doesn't define binary width\nhint: replace `int` with `int32` / `uint64` / `coins` / etc.\n```\n\n## Integration with message sending\n\nAuto-serialization can be applied when [sending messages](/languages/tolk/features/message-sending) to other contracts:\n\n```tolk\nval reply = createMessage({\n    // ...\n    body: RequestedInfo {     // auto-serialized\n        // ...\n    }\n});\nreply.send(SEND_MODE_REGULAR);\n```\n\n## `lazy` for deserialization\n\nTolk provides a special keyword [`lazy`](/languages/tolk/features/lazy-loading) for use with auto-deserialization.\nThe compiler loads only the requested fields, rather than the entire struct.\n\n```tolk\nstruct Storage {\n    isSignatureAllowed: bool\n    seqno: uint32\n    subwalletId: uint32\n    publicKey: uint256\n    extensions: cell?\n}\n\nget fun publicKey() {\n    val st = lazy Storage.fromCell(contract.getData());\n    // <-- here \"skip 65 bits, preload uint256\" is inserted\n    return st.publicKey\n}\n```\n"
  },
  {
    "path": "languages/tolk/features/compiler-optimizations.mdx",
    "content": "---\ntitle: \"Compiler optimizations\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nThe Tolk compiler generates bitcode from clear, idiomatic code. Extracting variables or simple methods should not increase gas consumption.\n\n## Constant folding\n\nTolk compiler evaluates constant variables and conditions at compile-time:\n\n```tolk\nfun calcSecondsInAYear() {\n    val days = 365;\n    val minutes = 60 * 24 * days;\n    return minutes * 60;\n}\n```\n\nAll these computations are done statically, resulting in:\n\n```fift\n31536000 PUSHINT\n```\n\nIt works for conditions as well.\n\n- If an `if` condition is statically known to be `false`, only the `else` body remains.\n- If an `assert` is statically proven to fail, the corresponding `throw` remains.\n\n```tolk\nfun demo(s: slice) {\n    var flags = s.loadUint(32);   // definitely >= 0\n    if (flags < 0) {              // always false\n        // ...\n    }\n    return s.remainingBitsCount();\n}\n```\n\nThe compiler removes the entire `IF` construct — both the condition evaluation and its bodies — when the branch is provably unreachable.\n\nDuring compile-time evaluation, arithmetic operations are emulated as they would be at runtime. The compiler also tracks flags such as \"this value is even or non-positive\", which allows it to remove unreachable code.\n\nThis applies not only to plain variables but also to struct fields, tensor items, and across inlining. It runs after the high-level syntax tree is transformed to a low-level intermediate representation.\n\n## Merging constant `builder.storeInt`\n\nWhen building cells manually, there is no need to group the constant `storeUint` into a single number.\n\n```tolk\n// no need for manual grouping anymore\nb.storeUint(4 + 2 + 1, 1 + 4 + 4 + 64 + 32 + 1 + 1 + 1);\n```\n\n`builder.storeInt` are merged automatically:\n\n```tolk\nb.storeUint(0, 1)  // prefix\n .storeUint(1, 1)  // ihr_disabled\n .storeUint(1, 1)  // bounce\n .storeUint(0, 1)  // bounced\n .storeUint(0, 2)  // addr_none\n```\n\nCompiles to:\n\n```fift\nb{011000} STSLICECONST\n```\n\nIt works together with constant folding — with variables and conditions  —  when they turn out to be constant:\n\n```tolk\nfun demo() {\n    var x = 0;\n    var b = beginCell();\n    b.storeUint(x, 4);\n    x += 12;\n    if (x > 0) {\n        x += x;\n    }\n    b.storeUint(x + 2, 8);\n    return b;\n}\n```\n\nCompiles to:\n\n```fift\nNEWC\nx{01a} STSLICECONST\n```\n\nThe same applies to structures and their fields:\n\n```tolk\nstruct Point {\n    x: uint32\n    y: uint32\n}\n\nfun demo() {\n    var p: Point = { x: 10, y: 20 };\n    return p.toCell();\n}\n```\n\nCompiles to:\n\n```fift\nNEWC\nx{0000000a00000014} STSLICECONST\nENDC\n```\n\nFor unions, [createMessage](/languages/tolk/features/message-sending) is lightweight. The compiler generates all `IF-ELSE` and `STU`, but during compile-time analysis, these instructions resolve to constants because all types are known at compile time. The resulting code flattens into `PUSHINT` and `STSLICECONST`.\n\n## Auto-inline functions\n\nTolk inlines functions at the compiler level:\n\n```tolk\nfun Point.create(x: int, y: int): Point {\n    return {x, y}\n}\n\nfun Point.getX(self) {\n    return self.x\n}\n\nfun sum(a: int, b: int) {\n    return a + b\n}\n\nfun main() {\n    var p = Point.create(10, 20);\n    return sum(p.getX(), p.y);\n}\n```\n\nCompiles to:\n\n```fift\nmain PROC:<{\n    30 PUSHINT\n}>\n```\n\nThe compiler automatically determines which functions to inline and also provides manual control.\n\n### How does auto-inline work?\n\n- Simple, small functions are always inlined.\n- Functions called only once are always inlined.\n\nFor every function, the compiler calculates a \"weight\" and the number of usages:\n\n- if `weight < THRESHOLD`, the function is always inlined.\n- if `usages == 1`, the function is always inlined.\n- otherwise, an empirical formula determines inlining.\n\nInlining works with stack operations and supports arguments of any width. It applies to functions and methods, except recursive functions or functions with `return` in the middle.\n\nUtility methods can be created without affecting gas consumption, they are zero-cost.\n\n### How to control inlining manually?\n\n- `@inline` forces inlining for large functions.\n- `@noinline` prevents inlining.\n- `@inline_ref` preserves an inline reference, suitable for rarely executed paths.\n\n### What cannot be auto-inlined?\n\nA function is NOT inlined, even if marked with `@inline`, if:\n\n- contains `return` in the middle; multiple return points are unsupported;\n- participates in a recursive call chain, e.g., `f -> g -> f`;\n- is used as a non-call; e.g., as a reference `val callback = f`.\n\nExample of function that cannot be inlined due to `return` in the middle:\n\n```tolk\nfun executeForPositive(userId: int) {\n    if (userId <= 0) {\n        return;\n    }\n    // ...\n}\n```\n\nCheck preconditions out of the function and keep body linear.\n\n## Peephole and stack optimizations\n\nAfter the code is analyzed and transformed into [IR](https://en.wikipedia.org/wiki/Intermediate_representation), the compiler repeatedly replaces some assembler combinations with equivalent, cheaper ones. Examples include:\n\n- stack permutations: `DUP + DUP` -> `2DUP`, `SWAP + OVER` -> `TUCK`;\n- `N LDU + NIP` -> `N PLDU`;\n- `SWAP + N STU` -> `N STUR`, `SWAP + STSLICE` -> `STSLICER`;\n- `SWAP + EQUAL` -> `EQUAL` and other symmetric like `MUL`, `OR`;\n- `0 EQINT + N THROWIF` -> `N THROWIFNOT` and vice versa;\n- `N EQINT + NOT` -> `N NEQINT` and other `xxx + NOT`.\n\nOther transformations occur semantically in advance when safe:\n\n- replace a ternary operator to `CONDSEL`;\n- evaluate arguments of `asm` functions in the desired stack order;\n- evaluate struct fields of a shuffled object literal to fit stack order.\n\n## `lazy` loading\n\nThe [`lazy` keyword](/languages/tolk/features/lazy-loading) loads only the required fields from a cell or slice:\n\n```tolk\nstruct Storage {\n    // ...\n}\n\nget fun publicKey() {\n    val st = lazy Storage.load();\n    // fields before are skipped; publicKey preloaded\n    return st.publicKey\n}\n```\n\nThe compiler tracks exactly which fields are accessed and unpacks only those fields, skipping the rest.\n\n## Manual optimizations\n\nThe compiler does substantial work automatically, but the gas usage can be reduced.\n\nTo do it, change the evaluation order to minimize stack manipulations. The compiler does not reorder code blocks unless they're constant expressions or pure calls.\n\nExample:\n\n```tolk\nfun demo() {\n    // variable initialization, grouped\n    val v1 = someFormula1();\n    val v2 = someFormula2();\n    val v3 = someFormula3();\n\n    // use them in calls, assertions, etc.\n    someUsage(v1);\n    anotherUsage(v2);\n    assert(v3) throw 123;\n}\n```\n\nAfter the first block, the stack is `(v1 v2 v3)`. Since `v1` is used first, the stack must be rearranged with `SWAP`, `ROT`, `XCPU`, etc. Reordering assignments or usages—for example, moving `assert(v3)` upper—will pop the topmost element. Automatic reordering is unsafe and prohibited, but in some cases business logic might be still valid.\n\nAnother option is using bitwise `&` and `|` instead of logical `&&` and `||`. Logical operators are short-circuit: the right operand is evaluated only if required. They are implemented using runtime conditional branches. In some cases, evaluating both operands directly uses fewer runtime instructions than a dynamic `IF`.\n\nThe last option is using low-level Fift code for certain independent tasks that cannot be expressed imperatively. This includes using TVM instructions such as `NULLROTRIFNOT` or `IFBITJMP`, and overriding the top-level Fift dictionary for `method_id` routing. These techniques are applicable only in a limited set of scenarios, primarily for specialized exercises rather than for real-world use.\n\n<Aside\n  type=\"caution\"\n>\n  Avoid micro-optimizations. Small manual attempts to reduce gas typically yield minimal gains and can reduce code readability. Use Tolk as intended.\n</Aside>\n\n## Fift assembler\n\nThe Tolk compiler outputs the Fift assembler. Fift generates the bitcode. Projects built on [Blueprint](/contract-dev/blueprint/overview) use `tolk-js`, which invokes Tolk and then Fift.\n\n- For command-line users, the Fift assembler is the compiler output.\n- For Blueprint users, it is an intermediate result that can be accessed in the build directory.\n\n  To view Fift assembler in Blueprint, run `npx blueprint build` in the project.\n  After compilation, the `build/` directory is created, containing a folder `build/ContractName/` with a `.fif` file.\n"
  },
  {
    "path": "languages/tolk/features/contract-getters.mdx",
    "content": "---\ntitle: \"Contract getters\"\n---\n\nContract getters or [get methods](/tvm/get-method) are declared using `get fun xxx()`. They typically return data extracted from [storage](/languages/tolk/features/contract-storage):\n\n```tolk\nget fun currentOwner() {\n    val storage = lazy Storage.load();\n    return storage.ownerAddress;\n}\n```\n\n## Return type\n\nThe return type is inferred when omitted. Get methods follow the same behavior as [functions and methods](/languages/tolk/syntax/functions-methods). Specifying the return type explicitly is recommended:\n\n```tolk\nget fun currentOwner(): address {\n    // ...\n}\n```\n\n## Custom name\n\nUse camelCase for naming.\n\n- Recommended: `get fun currentOwner()`\n- Not recommended: `get fun get_current_owner()`\n\nThis convention may be overridden when matching standard TEPs. For example, a jetton wallet should expose a method `get_wallet_data`, as it was named in implementations.\nIn such cases, using `get fun get_wallet_data` is appropriate, even if it does not follow the camelCase convention.\n\n## Structures\n\nWhen a getter returns multiple values, define a [structure](/languages/tolk/types/structures) and return it.\nUsing a structure is acceptable even for a single return. Field names provide explicit metadata for client wrappers, making the structure self-descriptive.\n\n```tolk\nstruct JettonWalletDataReply {\n    jettonBalance: coins\n    ownerAddress: address\n    minterAddress: address\n    jettonWalletCode: cell\n}\n\nget fun get_wallet_data(): JettonWalletDataReply {\n    val storage = lazy WalletStorage.load();\n\n    return {\n        jettonBalance: storage.jettonBalance,\n        ownerAddress: storage.ownerAddress,\n        minterAddress: storage.minterAddress,\n        jettonWalletCode: contract.getCode(),\n    }\n}\n```\n\n## `lazy` loading\n\nUse [`lazy` loading](/languages/tolk/features/lazy-loading) for [contract storage](/languages/tolk/features/contract-storage). Prefer `lazy loadStorage()` instead of `loadStorage()`. Unreferenced fields are skipped automatically.\n\n## Parameters\n\nGet methods can accept parameters. Parameters use the same syntax as regular functions:\n\n```tolk\nget fun get_wallet_address(ownerAddress: address): address {\n    // ...\n}\n```\n\n## Stack-based execution\n\nAny function in TVM takes its arguments from the stack and pushes return values onto it; get methods differ only in that they can be invoked [off-chain](/from-ethereum#on-chain-get-methods). When called off-chain, a get method does not persist state changes.\n\nA getter can return `int`, which is not serializable unlike `intN`. Returning a structure pushes each field onto the stack as a separate value. Client libraries such as [Blueprint](/contract-dev/blueprint/overview) parse get method responses using a tuple reader.\n\nGet methods do not store their names. They are identified by a `method_id = crc16(name) | 0x10000`, avoiding the need to store additional strings on-chain.\n"
  },
  {
    "path": "languages/tolk/features/contract-storage.mdx",
    "content": "---\ntitle: \"Contract storage\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nContract storage is a [`struct`](/languages/tolk/types/structures), serialized into persistent blockchain data. Tolk does not enforce any specific storage layout.\n\n<Aside type=\"tip\">\n  For convenience, place the storage struct and its methods in a separate file, e.g., `storage.tolk`.\n</Aside>\n\n## Common pattern\n\nAdd `load` and `store` methods to `struct Storage`:\n\n```tolk\nstruct Storage {\n    counterValue: int64\n}\n\nfun Storage.load() {\n    return Storage.fromCell(contract.getData())\n}\n\nfun Storage.save(self) {\n    contract.setData(self.toCell())\n}\n```\n\nThe storage can be accessed:\n\n```tolk\nget fun currentCounter() {\n    var storage = lazy Storage.load();\n    return storage.counterValue;\n}\n\nfun demoModify() {\n    var storage = lazy Storage.load();\n    storage.counterValue += 100;\n    storage.save();\n}\n```\n\n- `fun Storage.f(self)` defines an instance [method](/languages/tolk/syntax/functions-methods).\n- `T.fromCell()` deserializes a cell into `T`, and [`obj.toCell()`](/languages/tolk/features/auto-serialization#unpackoptions-and-packoptions) packs it back into a cell.\n- The [`lazy`](/languages/tolk/features/lazy-loading) operator does the parsing on demand.\n- [`contract.getData()`](/languages/tolk/features/standard-library) fetches persistent data.\n\n## Default values\n\nIn TON, a contract’s address depends on its initial storage when it is [created on-chain](/foundations/addresses/derive#on-chain-—-simple). Assign default values to fields that must be defined at deployment:\n\n```tolk\nstruct WalletStorage {\n    // these fields must have these values when deploying\n    // to make the contact's address predictable\n    jettonBalance: coins = 0\n    isFrozen: bool = false\n\n    // these fields must be manually assigned for deployment\n    ownerAddress: address\n    minterAddress: address\n}\n```\n\nTo calculate the contract’s initial address, these two fields are required.\n\n## Multiple contracts\n\nWhen developing multiple contracts in one project simultaneously, for example, a jetton minter and a jetton wallet, each contract has its own storage shape described by a `struct`.\n\nName these structures descriptively, for example, `MinterStorage` and `WalletStorage`. Place these structures in a single file `storage.tolk` along with their methods.\n\nContracts may deploy other contracts, requiring initial storage to be provided at deployment. For example, a minter deploys a wallet, so `WalletStorage` becomes accessible through an `import`:\n\n```tolk\n// all symbols from imported files become visible\nimport \"storage\"\n\nfun deploy(ownerAddress: address, minterAddress: address) {\n    val emptyWalletStorage: WalletStorage = {\n        ownerAddress,\n        minterAddress,\n        // the other two use their defaults\n    };\n    // ...\n}\n```\n\n## Changing storage shape\n\nContracts may start with a storage layout and extend it after deployment. For example:\n\n- At deployment, storage contains only `a`, `b`, `c`.\n- Followed by a message supplying  `d` and `e`, storage becomes `a`, `b`, `c`, `d`, `e`.\n\nThis behavior is not related to [nullable types](/languages/tolk/types/nullable). Nullable values such as `int8?` or `cell?` serialize with an explicit null marker 0 bit. In this case, fields are absent entirely, and no extra bits appear in serialization.\n\nThis pattern is common in NFT contracts. Initially, an NFT contains only `itemIndex` and `collectionAddress`. After initialization, `ownerAddress` and `content` are added to the storage.\n\nSince arbitrary imperative code is allowed, the approach is:\n\n- Define two structures: initialized and uninitialized storages.\n- Start loading using `contract.getData()`.\n- Determine whether the storage is initialized based on its bits and refs counts.\n- Parse into the corresponding struct.\n\nExample:\n\n```tolk expandable\n// two structures representing different storage states\n\nstruct NftItemStorage {\n    itemIndex: uint64\n    collectionAddress: address\n    ownerAddress: address\n    content: cell\n}\n\nstruct NftItemStorageNotInitialized {\n    itemIndex: uint64\n    collectionAddress: address\n}\n\n// instead of the usual `load()` method — `startLoading()`\n\nfun NftItemStorage.startLoading() {\n    return NftItemStorageLoader.fromCell(contract.getData())\n}\n\nfun NftItemStorage.save(self) {\n    contract.setData(self.toCell())\n}\n\n// this helper detects shape of a storage\nstruct NftItemStorageLoader {\n    itemIndex: uint64\n    collectionAddress: address\n    private rest: RemainingBitsAndRefs\n}\n\n// when `rest` is empty, `collectionAddress` is the last field\nfun NftItemStorageLoader.isNotInitialized(self) {\n    return self.rest.isEmpty()\n}\n\n// `endLoading` continues loading when `rest` is not empty\nfun NftItemStorageLoader.endLoading(mutate self): NftItemStorage {\n    return {\n        itemIndex: self.itemIndex,\n        collectionAddress: self.collectionAddress,\n        ownerAddress: self.rest.loadAny(),\n        content: self.rest.loadAny(),\n    }\n}\n```\n\nUsage in `onInternalMessage`:\n\n```tolk\nvar loadingStorage = NftItemStorage.startLoading();\nif (loadingStorage.isNotInitialized()) {\n    // ... probably, initialize and save\n    return;\n}\n\nvar storage = loadingStorage.endLoading();\n// and the remaining logic: lazy match, etc.\n```\n\nDifferent shapes with missing fields can also be expressed using [generics](/languages/tolk/types/generics) and the [void type](/languages/tolk/types/void-never).\n"
  },
  {
    "path": "languages/tolk/features/jetton-payload.mdx",
    "content": "---\ntitle: \"Forward payload in jettons\"\nsidebarTitle: \"Payload in jettons\"\n---\n\nA jetton transfer may include a `forwardPayload` to provide custom data for the transaction recipient. This is a convention, not a language feature.\n\n## Jetton payload schema\n\nBy definition, the TL-B format is `(Either Cell ^Cell)`: one bit plus the corresponding data depending on the bit:\n\n- bit 0 indicates inline payload: all subsequent bits and references;\n- bit 1 indicates ref payload: the next reference.\n\nWhen inline, the payload is positioned at the end of a message.\n\nSome existing jetton implementations do not follow the schema:\n\n- Some allow empty data, no bits at all, which is invalid because at least one bit must exist. An empty payload should be encoded as bit 0 – empty inline payload.\n- Some do not verify that no extra data remains after bit 1.\n- Error codes vary across implementations.\n\n## Canonical payload typing\n\nTL-B `(Either X Y)` is a union type `X | Y` in Tolk. This can be defined as:\n\n```tolk\nstruct Transfer {\n    // ...\n    forwardPayload: RemainingBitsAndRefs | cell\n}\n```\n\nIt is parsed and serialized according to the schema: either bit 0 + inline data, or bit 1 + ref.\n\nThis approach can be used for assignment and client metadata. Trade-offs include:\n\n- consumes more gas due to runtime branching (`IF` bit 0);\n- does not verify that no extra data remains after bit 1.\n\n## Payload typing cases\n\nThe approach to representing a jetton `forwardPayload` depends on the intended usage and validation requirements.\n\n### Proxy data without validation\n\nTo proxy any data as-is, use `RemainingBitsAndRefs`:\n\n```tolk\nstruct Transfer {\n    // ...\n    forwardPayload: RemainingBitsAndRefs\n}\n```\n\n### Canonical union with validation\n\nTo validate a canonical union `RemainingBitsAndRefs | cell`, ensure that no extra data remains after a ref payload:\n\n```tolk\nstruct Transfer {\n    // ...\n    forwardPayload: RemainingBitsAndRefs | cell\n    mustBeEmpty: RemainingBitsAndRefs\n}\n\nfun Transfer.validatePayload(self) {\n    // if extra data exists, throws 9\n    self.mustBeEmpty.assertEnd()\n    // if no bits at all, failed with 9 beforehand,\n    // because the union could not be loaded\n}\n```\n\n### Validation with slices\n\nIf gas consumption is critical but validation is required, avoid allocating unions on the stack. Instead, validate a slice and keep it for further serialization:\n\n```tolk\nstruct Transfer {\n    // ...\n    forwardPayload: ForwardPayload\n}\n\ntype ForwardPayload = RemainingBitsAndRefs\n\n// validate TL/B `(Either Cell ^Cell)`\nfun ForwardPayload.checkIsCorrectTLBEither(self) {\n    var mutableCopy = self;\n    // throw 9 if no bits at all (\"maybe ref\" loads one bit)\n    if (mutableCopy.loadMaybeRef() != null) {\n        // if ^Cell, throw 9 if other data exists\n        mutableCopy.assertEnd()\n    }\n}\n```\n\n### Custom error codes\n\nTo throw custom error codes instead of an error with [exit code 9](/tvm/exit-codes#9:-cell-underflow), calling `loadMaybeRef()` is discouraged.\n\n```tolk\ntype ForwardPayload = RemainingBitsAndRefs\n\nstruct (0b0) PayloadInline {\n    data: RemainingBitsAndRefs\n}\n\nstruct (0b1) PayloadRef {\n    refData: cell\n    rest: RemainingBitsAndRefs\n}\n\ntype PayloadInlineOrRef = PayloadInline | PayloadRef\n\n// validate TL/B `(Either Cell ^Cell)`\nfun ForwardPayload.checkIsCorrectTLBEither(self) {\n    val p = lazy PayloadInlineOrRef.fromSlice(self);\n    match (p) {\n        PayloadInline => {\n            // okay, valid\n        }\n        PayloadRef => {\n            // valid if nothing besides ref exists\n            assert (p.rest.isEmpty()) throw ERR_EXTRA_BITS\n        }\n        else => {\n            // both not bit '0' and not bit '1' — empty\n            throw ERR_EMPTY_PAYLOAD_FIELD\n        }\n    }\n}\n```\n\n### Dynamic assignment\n\nKeeping a remainder reduces gas usage and enables validation, but it is less convenient when a payload must be assigned dynamically. The remainder is a plain `slice` containing an encoded union. For example, creating a ref payload from a `cell` requires manual construction.\n\n```tolk\nfun createRefPayload(ref: cell) {\n    // not like this, mismatched types\n    val err1 = ref;\n    // not like this, incorrect logic\n    val err2 = ref.beginParse();\n\n    // but like this: '1' + ref\n    val payload = beginCell()\n            .storeBool(true).storeRef(ref)\n            .asSlice();\n}\n```\n\nUsing `RemainingBitsAndRefs | cell` remains convenient for assignment but may incur additional gas costs.\n"
  },
  {
    "path": "languages/tolk/features/lazy-loading.mdx",
    "content": "---\ntitle: \"Lazy loading\"\n---\n\nTolk uses the `lazy` keyword – the compiler tracks which fields are accessed and loads only those fields, skipping the rest.\nIn practice, prefer `lazy T.fromCell()` over `T.fromCell()`.\n\n## `lazy` usage\n\nConsider a `Storage` struct in a wallet:\n\n```tolk\nstruct Storage {\n    isSignatureAllowed: bool\n    seqno: uint32\n    subwalletId: uint32\n    publicKey: uint256\n    extensions: cell?\n}\n\nfun Storage.load() {\n    return Storage.fromCell(contract.getData())\n}\n```\n\n`Storage.load()` unpacks the cell, loads all fields, performs consistency checks, etc.\n\n`lazy Storage.load()` does not load all fields. Unused fields are skipped:\n\n```tolk\nget fun publicKey() {\n    val st = lazy Storage.load();\n    // <-- here \"skip 65 bits, preload uint256\" is inserted\n    return st.publicKey\n}\n```\n\nThe compiler tracks all control-flow paths, inserts load points when required, and groups unused fields to skip. This works for any type and any combination of fields.\n\n## `lazy` usage of referenced cells\n\nConsider the NFT collection:\n\n```tolk\nstruct NftCollectionStorage {\n    adminAddress: address\n    nextItemIndex: uint64\n    content: Cell<CollectionContent>\n    // ...\n}\n\nstruct CollectionContent {\n    metadata: cell\n    minIndex: int32\n    commonKey: uint256\n}\n```\n\nTo read `content` and then get `commonKey` from it:\n\n```tolk\nval storage = lazy NftCollectionStorage.load();\n// <-- here just \"preload ref\" is inserted\nval contentCell = storage.content;\n```\n\n1. Skipping `address` and `uint64` is unnecessary. Accessing a reference does not require skipping preceding fields.\n1. To read `commonKey` from `content`, load the cell with `lazy`.\n\n```tolk\nval storage = lazy NftCollectionStorage.load();\n\n// <-- \"preload ref\" inserted — to get `content`\n// Cell<T>.load() unpacks a cell and returns T\nval content = lazy storage.content.load();\n\n// <-- \"skip 32 bits, preload uint256\" - to get commonKey\nreturn content.commonKey;\n```\n\n`p: Cell<Point>` does not allow direct access to `p.x`. The cell must be loaded first using either `Point.fromCell(p)` or `p.load()`. Both work with `lazy`.\n\n## `lazy` matching\n\nA union type such as an incoming message can be read with `lazy`:\n\n```tolk\nstruct (0x12345678) CounterIncrement { /* ... */ }\nstruct (0x23456789) CounterReset     { /* ... */ }\n\ntype MyMessage = CounterIncrement | CounterReset\n\nfun onInternalMessage(in: InMessage) {\n    val msg = lazy MyMessage.fromSlice(in.body);\n    match (msg) {\n        CounterReset => {\n            assert (something) throw 403;\n            // <-- here \"load msg.initial\" is inserted\n            storage.counter = msg.initial;\n        }\n        // ...\n    }\n}\n```\n\nWith `lazy` applied to unions:\n\n1. No union is allocated on the stack upfront; matching and loading are deferred until needed.\n1. `match` operates by inspecting the slice prefix (opcode).\n1. Within each branch, the compiler inserts loading points and skips unused fields, as it does for structs.\n\n`lazy` matching avoids unnecessary stack operations.\n\n## `lazy` matching and `else`\n\n`match` with `lazy` on a union operates by inspecting the prefix. Any unmatched case falls into the `else` branch.\n\n```tolk\nval msg = lazy MyMessage.fromSlice(in.body);\nmatch (msg) {\n    CounterReset => { /* ... */ }\n    // ... handle all variants of the union\n\n    // else - when nothing matched;\n    // even input less than 32 bits, no \"underflow\" thrown\n    else => {\n        // for example\n        throw 0xFFFF\n    }\n}\n```\n\nWithout an explicit `else`, unpacking throws `error 63` by default, which is controlled by the `throwIfOpcodeDoesNotMatch` option in `fromSlice`. The `else` branch allows inserting any custom logic.\n\n`else` in a type-based `match` is allowed only with `lazy` because matching uses prefixes. Without `lazy`, the union is matched normally and an `else` branch is not allowed.\n\n## Partial updating\n\nThe `lazy` keyword also applies when writing data back.\n\nExample:\n\nLoad a storage, use its fields for assertions, update one field, and save it back:\n\n```tolk\nvar storage = lazy Storage.load();\n\nassert (storage.validUntil > blockchain.now()) throw 123;\nassert (storage.seqno == msg.seqno) throw 456;\n// ...\n\nstorage.seqno += 1;\ncontract.setData(storage.toCell());   // <-- magic\n```\n\n`toCell()` does not save all fields of the storage since only `seqno` is modified. Instead, after loading `seqno`, the compiler saves an immutable tail and reuses it when writing back:\n\n```tolk\nvar storage = lazy Storage.load();\n// actually, what was done:\n// - load isSignatureAllowed, seqno\n// - save immutable tail\n// - load validUntil, etc.\n\n// ... use all fields for reading\n\nstorage.seqno += 1;\nstorage.toCell();\n// actually, what was done:\n// - store isSignatureAllowed, seqno\n// - store immutable tail\n```\n\nThe compiler can also group unmodified fields located in the middle, load them as a slice, and preserve that slice on write-back.\n\n## How does `lazy` skip unused fields?\n\nWhen several consecutive fields are unused, the compiler tries to group them. This works for fixed-size types such as `intN` or `bitsN`:\n\n```tolk\nstruct Demo {\n    isAllowed: bool     // always 1 bit\n    queryId: uint64     // always 64 bits\n    crc: bits32         // always 32 bits\n    next: RemainingBitsAndRefs\n}\n\nfun demo() {\n    val obj = lazy Demo.fromSlice(someSlice);\n    // <-- skip 1+64+32 = 97 bits\n    obj.next;\n}\n```\n\nIn Fift assembler, “skip 97 bits” becomes:\n\n```fift\n97 LDU\nNIP\n```\n\nVariable-width fields, such as `coins`, cannot be grouped and cannot be skipped with one instruction – TVM has no instruction for that. The only option is to load the value and ignore it.\n\nThe same applies to `address`. Even though it occupies 267 bits, the value should be validated even when unused; otherwise, binary data could be decoded incorrectly.\n\nFor these types, `lazy` does only \"load and ignore\".\n\nIn practice, `intN` types are common, so grouping has an effect. The trick \"access a ref without skipping any data\" also works.\n\n## What are the disadvantages of `lazy`?\n\nIn terms of gas consumption, `lazy fromSlice` is equal to or cheaper than regular `fromSlice`. When all fields are accessed, it loads them one by one, the same way as the non-lazy version. There is a difference unrelated to gas consumption:\n\n- If a slice is small or contains extra data, `fromSlice` throws.\n- `lazy` picks only the requested fields and handles partially invalid input. For example:\n\n```tolk\nstruct Point {\n    x: int8\n    y: int8\n}\n\nfun demo(s: slice) {\n    val p = lazy Point.fromSlice(s);\n    return p.x;\n}\n```\n\nSince only `p.x` is accessed, an input of `FF` (8 bits) is acceptable even though `y` is missing. Similarly, `FFFF0000` (16 bits of extra data) is also acceptable, as `lazy` ignores any data that is not requested.\n"
  },
  {
    "path": "languages/tolk/features/message-handling.mdx",
    "content": "---\ntitle: \"Handling messages\"\n---\n\nEach Tolk contract has special entrypoints – reserved functions that handle different message types. Handling an incoming message uses ordinary language constructs.\n\n## `onInternalMessage`\n\nContracts primarily handle [internal messages](/foundations/messages/internal#internal-messages). Users interact with contracts through their wallets, which send internal messages to the contract. The entrypoint is declared as follows:\n\n```tolk\nfun onInternalMessage(in: InMessage) {\n    // internal non-bounced messages arrive here\n}\n```\n\nThe basic guidelines are:\n\n- For each incoming message, declare a `struct` with a unique 32-bit prefix, opcode.\n- Declare a union type that represents all supported messages.\n- Parse this union from `in.body` and `match` over structures.\n\n```tolk\nstruct (0x12345678) CounterIncrement {\n    incBy: uint32\n}\n\nstruct (0x23456789) CounterReset {\n    initialValue: int64\n}\n\ntype AllowedMessage = CounterIncrement | CounterReset\n\nfun onInternalMessage(in: InMessage) {\n    val msg = lazy AllowedMessage.fromSlice(in.body);\n    match (msg) {\n        CounterIncrement => {\n            // use `msg.incBy`\n        }\n        CounterReset => {\n            // use `msg.initialValue`\n        }\n        else => {\n            // invalid input; a typical reaction is:\n            // ignore empty messages, \"wrong opcode\" if not\n            assert (in.body.isEmpty()) throw 0xFFFF\n        }\n    }\n}\n```\n\n### Example breakdown\n\n- [`struct`](/languages/tolk/types/structures) declares business data, including messages and storage.\n- `(0x12345678)` defines a message opcode, 32-bit. Unique prefixes are used to route binary data in `in.body`.\n- `AllowedMessage` is a type alias for a [union type](/languages/tolk/types/unions).\n- `in: InMessage` provides access to message properties such as `in.body` and `in.senderAddress`.\n- `T.fromSlice` [parses binary data into `T`](/languages/tolk/features/auto-serialization). When combined with [`lazy`](/languages/tolk/features/lazy-loading), parsing is performed on demand.\n- [`match`](/languages/tolk/syntax/pattern-matching) routes a union type. Within each branch, the type of `msg` is narrowed, smart cast.\n- `throw 0xFFFF` is a standard reaction to an unrecognized message. Contracts typically ignore empty messages, which represent balance top-ups with an empty body. For this reason, `throw` is guarded by [`if`](/languages/tolk/syntax/conditions-loops) or `assert`.\n\nBounced messages are not handled by `onInternalMessage`.\n\n### Define and modify contract storage\n\n[Contract storage](/languages/tolk/features/contract-storage) is defined as a regular structure. Storage types commonly define `load` and `save` methods to access persistent contract data:\n\n```tolk\nstruct Storage {\n    counterValue: int64\n}\n\nfun Storage.load() {\n    return Storage.fromCell(contract.getData())\n}\n\nfun Storage.save(self) {\n    contract.setData(self.toCell())\n}\n```\n\nThen, in `match` cases, invoke those methods:\n\n```tolk\nmatch (msg) {\n    CounterIncrement => {\n        var storage = lazy Storage.load();\n        storage.counterValue += msg.incBy;\n        storage.save();\n    }\n    // ...\n}\n```\n\nStorage may also be loaded once before the `match` statement and reused across branches.\n\n### Legacy `onInternalMessage`\n\nIn FunC, a handler is declared as:\n\n```func\n() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure {\n    ;; manually parse in_msg_full to retrieve sender_address and others\n}\n```\n\nTolk continues to support this style of declaration. Code produced by a [converter](https://github.com/ton-blockchain/convert-func-to-tolk) results in:\n\n```tolk\nfun onInternalMessage(myBalance: coins, msgValue: coins, msgFull: cell, msgBody: slice) {\n    // manually parse msgFull to retrieve senderAddress and others\n}\n```\n\nThe modern approach uses the `InMessage` type. It simplifies message handling and reduces gas consumption. Migrating from the legacy code is:\n\n- `myBalance` -> `contract.getOriginalBalance()`, contract state, not a message property\n- `msgValue` -> `in.valueCoins`\n- `msgFull` -> use `in.senderAddress` etc., without manual parsing\n- `msgBody` -> `in.body`\n\n## `onBouncedMessage`\n\n`onBouncedMessage` is a special entrypoint for handling [bounced messages](/foundations/messages/internal#bounces).\n\n```tolk\nfun onBouncedMessage(in: InMessageBounced) {\n    // messages sent with BounceMode != NoBounce arrive here\n}\n```\n\n`InMessageBounced` is similar to `InMessage`. The difference is that `in.bouncedBody` has a different layout, depending on how the original message is sent.\n\n### `BounceMode` in `createMessage`\n\nWhen [sending a message](/languages/tolk/features/message-sending) using `createMessage`, the `bounce` behavior must be specified:\n\n```tolk\nval msg1 = createMessage({\n    bounce: BounceMode.NoBounce,\n    body: TransferMessage { ... },\n    // ...\n});\nmsg1.send(mode); // will not be bounced on error\n\nval msg2 = createMessage({\n    bounce: BounceMode.RichBounce,\n    body: TransferMessage { ... },\n    // ...\n});\nmsg2.send(mode); // may be bounced\n```\n\n`BounceMode` is an enum with the following options:\n\n- `BounceMode.NoBounce`.\n- `BounceMode.Only256BitsOfBody` — `in.bouncedBody` contains `0xFFFFFFFF` followed by the first 256 bits; lowest gas cost, often sufficient.\n- `BounceMode.RichBounce` — provides access to the entire `originalBody`; `gasUsed`, `exitCode`, and other failure-related properties are also available; highest gas cost.\n- `BounceMode.RichBounceOnlyRootCell` — similar to `RichBounce`, but `originalBody` contains only the root cell.\n\n### Handle `in.bouncedBody`\n\nThe structure of `in.bouncedBody` depends on the `BounceMode`.\n\nWhen all bounceable messages are sent using `Only256BitsOfBody`:\n\n```tolk\nfun onBouncedMessage(in: InMessageBounced) {\n    // in.bouncedBody is 0xFFFFFFFF + 256 bits\n    in.bouncedBody.skipBouncedPrefix();\n    // handle the rest, keep the 256-bit limit in mind\n}\n```\n\nWhen `RichBounce` is used:\n\n```tolk\nfun onBouncedMessage(in: InMessageBounced) {\n    val rich = lazy RichBounceBody.fromSlice(in.bouncedBody);\n    // handle rich.originalBody\n    // use rich.xxx to get exitCode, gasUsed, and so on\n}\n```\n\nMixing different modes, where some messages use a minimal body and others use a full body, complicates handling and is discouraged. The binary body of an outgoing message, such as `TransferMessage`, is returned either as `in.bouncedBody` with a 256-bit limit or as `rich.originalBody`, which contains the full slice. To handle this consistently:\n\n- define a union type that includes all message types that may be bounced;\n- handle it using `lazy` in `onBouncedMessage`.\n\n```tolk\nstruct (0x98765432) TransferMessage {\n    // ...\n}\n// ... and other messages\n\n// some of them are bounceable (send not with NoBounce)\ntype TheoreticallyBounceable = TransferMessage // | ...\n\n// example for BounceMode.Only256BitsOfBody\nfun onBouncedMessage(in: InMessageBounced) {\n    in.bouncedBody.skipBouncedPrefix();   // skips 0xFFFFFFFF\n\n    val msg = lazy TheoreticallyBounceable.fromSlice(in.bouncedBody);\n    match (msg) {\n        TransferMessage => {\n            // revert changes using `msg.xxx`\n        }\n        // ...\n    }\n}\n```\n\n## `onExternalMessage`\n\nIn addition to internal messages, a contract can handle [external messages](/foundations/messages/external-in) originating off-chain.\nFor example, [wallet contracts](/standard/wallets/how-it-works) process external messages and perform signature validation using a public key.\n\n```tolk\nfun onExternalMessage(inMsg: slice) {\n    // external messages arrive here\n}\n```\n\nWhen a contract accepts an external message, it has limited gas for execution. After validating the request, the contract must call `acceptExternalMessage()` to increase the available gas. The `commitContractDataAndActions()` function can also be used. Both functions are part of the standard library and are documented inline.\n\n## Additional reserved entrypoints\n\nTolk defines several reserved entrypoints:\n\n- `fun onTickTock` is invoked on tick-tock transactions;\n- `fun onSplitPrepare` and `fun onSplitInstall` are reserved for split and install transactions; currently not used by the blockchain;\n- `fun main` is used for simple snippets and demos.\n\nThe following program is valid:\n\n```tolk\nfun main() {\n    return 123\n}\n```\n\nIt compiles and runs, pushing value 123 onto the stack. The corresponding TVM `method_id` is `0`.\n"
  },
  {
    "path": "languages/tolk/features/message-sending.mdx",
    "content": "---\ntitle: \"Sending messages\"\n---\n\nTolk provides a high-level function `createMessage`, which is followed by `send`:\n\n```tolk\nval reply = createMessage({\n    bounce: BounceMode.NoBounce,\n    value: ton(\"0.05\"),\n    dest: senderAddress,\n    body: RequestedInfo { ... }\n});\nreply.send(SEND_MODE_REGULAR);\n```\n\n## Union types in contracts interaction\n\nWhen handling a message, some values can be represented in multiple valid forms. [Union types](/languages/tolk/types/unions) allow expressing these alternatives explicitly, so the same message-handling logic can accept and correctly process any of them.\n\n### Message value\n\nThe message value consists of a Toncoin amount:\n\n```tolk\nvalue: someTonAmount\n```\n\nWhen extra currencies are required, the message value includes both Toncoin and a dictionary:\n\n```tolk\nvalue: (someTonAmount, extraDict)\n```\n\nThis is possible because the `value` field is defined as a union:\n\n```tolk\n// how it is declared in stdlib\nstruct CreateMessageOptions<TBody> {\n    // ...\n    value: coins | (coins, ExtraCurrenciesMap)\n}\n```\n\nThen, the compiler selects the matching representation and serializes it accordingly.\n\n### Message destination\n\nMessage destinations are defined using the same union-based approach.\n\n```tolk\ndest: someAddress,\ndest: (workchain, hash)\n```\n\nThe destination field accepts multiple representations:\n\n```tolk\nstruct CreateMessageOptions<TBody> {\n    // ...\n    dest: address |             // either just send a message to some address\n          builder |             // ... or a manually constructed builder with a valid address\n          (int8, uint256) |     // ... or to workchain + hash (also known as accountID)\n          AutoDeployAddress     // ... or \"send to stateInit\" aka deploy (address auto-calculated)\n}\n```\n\nEach option represents a valid way to specify the message destination. The selected form is resolved at compile time.\n\n## Deployment and `StateInit`\n\nConsider a contract that deploys another contract. For example, a jetton minter deploying a jetton wallet. The wallet code and its initial data are known:\n\n```tolk\nval walletInitialState: ContractState = {\n    code: ...,   // probably, kept in minter's storage\n    data: ...,   // initial wallet's storage\n};\n```\n\nWhen sending a message to the wallet, it may not yet exist on-chain. In this case, the message must include the wallet's code and initial data. The message destination is therefore defined by the wallet's [`StateInit`](/foundations/messages/deploy#deploy-message).\n\n```tolk\n// address auto-calculated, code+data auto-attached\ndest: {\n    stateInit: walletInitialState\n}\n```\n\nFor more advanced scenarios, configure additional fields:\n\n```tolk\ndest: {\n    workchain: ...,     // default: 0 (basechain)\n    stateInit: ...,     // either code+data OR a ready cell\n    toShard:   ...,     // default: null (no sharding)\n}\n```\n\n### Shard-based deployment\n\nThe `createMessage` interface supports deploying contracts into a specific shard. For example, in sharded jettons, a jetton wallet must be deployed into the same shard as the owner's wallet.\n\nThis is expressed as follows:\n\n- A jetton wallet is deployed close to the owner's wallet;\n- This closeness is defined by [`shard_prefix`](/foundations/shards#sharding-process).\n\nThe example below uses `shard_prefix` is 8:\n\n| Title                          | Address hash     | Comment                                  |\n| ------------------------------ | ---------------- | ---------------------------------------- |\n| `closeTo` owner address        | `01010101...xxx` | owner's wallet                           |\n| `shardPrefix`                  | `01010101`       | first 8 bits of `closeTo`                |\n| `stateInitHash`                | `yyyyyyyy...yyy` | derived from code and data               |\n| `result` jetton wallet address | `01010101...yyy` | jetton wallet in the same shard as owner |\n\nDeployment with shard targeting is configured as follows:\n\n```tolk\ndest: {\n    stateInit: walletInitialState,\n    toShard: {\n        closeTo: ownerAddress,\n        fixedPrefixLength: 8\n    }\n}\n```\n\nShard prefix is part of `StateInit` together with code and data and is required for correct contract initialization in the blockchain. The compiler embeds it automatically. But semantically, on its own shard prefix is not meaningful. For this reason, shard prefix and `closeTo` are treated as a single entity.\n\n## Message body\n\nA [message](/foundations/messages/overview) is a cell. Its body can either be embedded into the same cell or placed into a separate cell and referenced.\n\nWhen creating a message, the `body` should be provided. The compiler determines how the body is stored.\n\n```tolk\ncreateMessage({\n    // ...\n    body: RequestedInfo { ... }\n});\n```\n\n### Inline or referenced body\n\n- If `body` is small, it is embedded directly into the message cell.\n- If `body` is large or has unpredictable size, it is stored as a ref.\n\nThe decision is made at compile time. No runtime checks are involved.\nThis is implemented using [generics](/languages/tolk/types/generics):\n\n```tolk\nfun createMessage<TBody>(\n    options: CreateMessageOptions<TBody>\n): OutMessage;\n\nstruct CreateMessageOptions<TBody> {\n    // ...\n    body: TBody;\n}\n```\n\nEach `createMessage()` call has its own `TBody`, allowing the compiler to estimate the body size:\n\n- if the maximum size is less than 500 bits and 2 refs, the body is embedded;\n- if the size is 500 bits or more, or requires more than 2 refs, the body is stored as a ref;\n- if the body contains `builder` or `slice`, its size is considered unpredictable, and it is stored as a ref.\n\nIf the body is large or unpredictable, it can be force-inlined by wrapping it into a special type:\n\n```tolk\n// maximum 620 bits (if all coins are billions of billions)\n// by default, the compiler will make a ref\nstruct ProbablyLarge {\n    a: (coins, coins, coins, coins, coins)\n}\n\nfun demo(contents: ProbablyLarge) {\n    // but you are sure: coins are small;\n    // so, you take the risks and force \"no ref\"\n    createMessage({\n        body: UnsafeBodyNoRef {\n            forceInline: contents,\n        },\n        // ...\n    });\n    // btw, here TBody = UnsafeBodyNoRef<ProbablyLarge>\n}\n```\n\nIf `body` is already a cell, it is stored as a ref:\n\n```tolk\ncreateMessage({\n    body: someCell,  // ok, just a cell, keep it as a ref\n    // ...\n});\n```\n\nTherefore, do not pass `body: obj.toCell()`. Pass `body: obj`, and the compiler will choose the optimal and correct encoding.\n\n### Non-struct body\n\n`body` is not limited to structs. For example:\n\n```tolk\nval excessesMsg = createMessage({\n   // ...\n   body: (0xd53276db as int32, input.queryId)\n});\nexcessesMsg.send(mode);\n```\n\nThe call is inferred as `createMessage<(int32, uint64)>(...)` and encoded accordingly.\n\n### Empty body\n\nIf no `body` is needed, it can be omitted entirely:\n\n```tolk\ncreateMessage({\n    bounce: BounceMode.NoBounce,\n    dest: somewhere,\n    value: remainingBalance\n});\n```\n\nIn this example, the `body` type is `void`.\n\nA struct is declared as `CreateMessageOptions<TBody = void>`. By convention, fields of type `void` may be omitted in object literals.\n\n## Sending modes\n\nA message created with `createMessage()` is typically sent using [`msg.send(mode)`](/foundations/messages/modes#sending-modes).\n\n## `ContractState` and `StateInit`\n\n`StateInit` contains more fields than `code` and `data`. For this reason, the `code` and `data` pair is defined as `ContractState`:\n\n```tolk\n// in stdlib\nstruct ContractState {\n    code: cell\n    data: cell\n}\n```\n\nWhile a field `stateInit: ContractState | cell` is named as `stateInit`, emphasizing that a full `StateInit` can be automatically initialized from `ContractState`.\n\n## `createExternalLogMessage`\n\n`createExternalLogMessage` follows the same general model as `createMessage`. [External outgoing messages](/foundations/messages/external-out) do not support bounce behavior, attached Toncoin, or related options, so the set of available fields is different. External messages are used only for emitting logs intended for indexers.\n\nExample:\n\n```tolk\nval emitMsg = createExternalLogMessage({\n    dest: createAddressNone(),\n    body: DepositEvent { ... }\n});\nemitMsg.send(SEND_MODE_REGULAR);\n```\n\nOnly `dest` and `body` are available for external outgoing messages:\n\n```tolk\nstruct CreateExternalLogMessageOptions<TBody = void> {\n    /// destination is either an external address or a pattern to calculate it\n    dest: any_address |     // either some valid external/none address (not internal)\n          builder |         // ... or a manually constructed builder with a valid external address\n          ExtOutLogBucket;  // ... or encode topic/eventID in destination\n\n    /// body is any serializable object (or just miss this field for empty body)\n    body: TBody;\n}\n```\n\nThe compiler automatically determines whether `body` fits into the same cell or must be stored as a reference. `UnsafeBodyNoRef` is also supported.\n\nExample of emitting an external log:\n\n```tolk\nstruct DepositData {\n    amount: coins;\n    ...\n}\n\nval emitMsg = createExternalLogMessage({\n    dest: ExtOutLogBucket { topic: 123 },   // for indexers\n    body: DepositData { ... }\n});\nemitMsg.send(SEND_MODE_REGULAR);\n```\n\nExample of emitting an external log:\n\n```tolk\nstruct (0x12345678) DepositEvent {\n    amount: coins;\n    ...\n}\n\ncreateExternalLogMessage({\n    dest: createAddressNone(),\n    body: DepositEvent { ... }   // 0x12345678 for indexers\n});\n```\n\n`ExtOutLogBucket` represents a custom external address for emitting logs to the outer world. It includes a numeric topic that defines the message body format.\nIn the example above, a deposit event is emitted using `topic: 123`. Such logs can be indexed by destination address without parsing the message body.\n"
  },
  {
    "path": "languages/tolk/features/standard-library.mdx",
    "content": "---\ntitle: \"Standard library\"\nsidebarTitle: \"Standard library\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nTolk provides a standard library or stdlib that includes commonly used functions.\n\n<Aside type=\"tip\">\n  IDEs provide auto-completion and navigation to definitions and inline documentation using <kbd>Cmd</kbd>+Click or <kbd>Ctrl</kbd>+Click.\n</Aside>\n\n## Compile-time calculations and embedding\n\nConstant values can be embedded into a contract using dedicated functions.\n\n### `address()`\n\nThe `address()` function embeds a constant address:\n\n```tolk\nconst REFUND_ADDR = address(\"EQCRDM9h4k3UJdOePPuyX40mCgA4vxge5Dc5vjBR8djbEKC5\")\n```\n\n### String-based compile-time functions\n\nSeveral functions, such as `stringCrc32()`, operate on string literals. They require constant inputs and are evaluated to an `int` at compile time.\n\n```tolk\n// calculates crc32 of a string\nconst crc32 = stringCrc32(\"some_str\") // = 4013618352 = 0xEF3AF4B0\n\n// calculates crc16 (XMODEM) of a string\nconst crc16 = stringCrc16(\"some_str\") // = 53407 = 0xD09F\n\n// calculates sha256 of a string and returns 256-bit integer\nconst hash = stringSha256(\"some_crypto_key\")\n\n// calculates sha256 of a string and takes the first 32 bits\nconst minihash = stringSha256_32(\"some_crypto_key\")\n\n// interprets an N-chars ascii string as a number in base 256\nconst base256 = stringToBase256(\"AB\") // = 16706 (65*256 + 66)\n```\n\n### `ton()`\n\nCalculates nanotoncoins at compile time.\n\n```tolk\nconst ONE_TON = ton(\"1\");     // `coins`, value: 1000000000\n\nfun calcCost() {\n    val cost = ton(\"0.05\");   // `coins`, value: 50000000\n    return ONE_TON + cost;\n}\n```\n\n## Common functions\n\nAll functions in this section are available everywhere. They are defined in `@stdlib/common.tolk`, which is auto-imported.\n\n### Tuples\n\nTuple-related functions allow interacting with [tuple types](/languages/tolk/types/tuples), which are dynamic containers of up to 255 elements.\n\n#### `createEmptyTuple`\n\nCreates a tuple with zero elements.\n\n#### `tuple.push`, `tuple.get`, etc.\n\nAn IDE suggests available methods after a dot `.`:\n\n```tolk\nfun demo() {\n    var t = createEmptyTuple();\n    t.push(123);\n    return t.get<int>(0);       // 123\n}\n```\n\n#### `T.toTuple` and `T.fromTuple`\n\nPacks an object from the stack into a tuple and converts it back. If a value occupies N stack slots, the resulting tuple has size N.\n\n```tolk\nstruct Point {\n    x: int\n    y: int\n}\n\nfun demo() {\n    var p: Point = { x: 1, y: 2 };\n    var t = p.toTuple();     // [ 1 2 ]\n    p = Point.fromTuple(t);  // restored\n    t.get<int>(0);           // 1\n}\n```\n\n### Mathematical primitives\n\nThese functions accept and return integers unless stated otherwise. All [integers](/languages/tolk/types/numbers) are 257-bit.\n\n#### `min(x, y)`\n\nReturns the minimum of two integers.\n\n#### `max(x, y)`\n\nReturns the maximum of two integers.\n\n#### `minMax(x, y)`\n\nReturns `(int, int)` – a tensor `(smallest, largest)`.\n\n#### `abs(x)`\n\nReturns the absolute value of an integer.\n\n#### `sign(x)`\n\nReturns the sign of an integer value:\n\n- `-1` if x \\< 0;\n- `0` if x == 0;\n- `1` if x > 0.\n\n#### `divMod(x, y)`\n\nReturns `(int, int)` — the quotient and remainder of `x / y`.\n\nExample: `divMod(112, 3)` = `(37, 1)`.\n\n#### `modDiv(x, y)`\n\nReturns `(int, int)` — the remainder and quotient of `x / y`.\n\nExample: `modDiv(112, 3)` = `(1, 37)`.\n\n#### `mulDivFloor(x, y, z)`\n\nComputes multiple-then-divide: `floor(x * y / z)`. The intermediate result is stored in a 513-bit integer to prevent precision loss.\n\n#### `mulDivRound(x, y, z)`\n\nSimilar to `mulDivFloor`, but rounds the result: `round(x * y / z)`.\n\n#### `mulDivCeil(x, y, z)`\n\nSimilar to `mulDivFloor`, but ceils the result: `ceil(x * y / z)`.\n\n#### `mulDivMod(x, y, z)`\n\nReturns `(int, int)` — the quotient and remainder of `(x * y / z)`.\n\nExample: `mulDivMod(112, 3, 10)` = `(33, 6)`.\n\n### Global getters and setters of current contract state\n\nAll functions in this section are methods of the empty struct `contract`.\n\n#### `contract.getAddress`\n\nReturns `address` — the internal address of the current smart contract. It can be further parsed using `address.getWorkchain` and others.\n\n#### `contract.getOriginalBalance`\n\nReturns `coins` — the balance of the smart contract in nanotoncoins at the start of the [compute phase](/tvm/exit-codes#compute-phase).\n\n#### `contract.getOriginalBalanceWithExtraCurrencies`\n\nReturns `[coins, ExtraCurrenciesMap]` — similar to `contract.getOriginalBalance`, but also returns extra currencies.\n\n#### `contract.getData`\n\nReturns `cell` — the persistent contract storage cell. Typically, its result is used as [`Storage.fromCell()`](/languages/tolk/features/contract-storage).\n\n#### `contract.setData(cell)`\n\nSets the persistent contract storage. Typically, the argument is [`storageObject.toCell()`](/languages/tolk/features/contract-storage).\n\n#### `contract.getCode`\n\nReturns `cell` — the smart contract code stored in TVM [register `c7`](/tvm/registers).\n\n#### `contract.setCodePostponed(newCodeCell)`\n\nCreates an output action that updates the smart contract code after successful termination of the current execution.\n\n### Global getters of the blockchain (environment) state\n\nMost functions in this section are methods of the empty struct `blockchain`.\n\n#### `blockchain.now`\n\nReturns `int` — the current Unix timestamp in seconds.\n\n#### `blockchain.logicalTime`\n\nReturns `int` — the logical time of the current transaction.\n\n#### `blockchain.currentBlockLogicalTime`\n\nReturns `int` — the starting logical time of the current block.\n\n#### `blockchain.configParam(i)`\n\nReturns `cell?` — the value of the global [configuration parameter](/foundations/config) with integer index `i`, or `null` if not exists.\n\n#### `commitContractDataAndActions`\n\nCommits the current state of TVM registers `c4` persistent data and `c5` actions, so the current execution is considered successful with these values even if an exception is thrown later during the compute phase.\n\n### Signature checks, hashing, cryptography\n\nFunctions and methods for hashing, signature verification, and randomization.\n\n#### `cell.hash`\n\nReturns `uint256` — the representation hash of a cell. Useful for signing and checking signatures of arbitrary entities represented by a tree of cells.\n\n#### `slice.hash`\n\nReturns `uint256` — the hash of data in a slice. The same as `cell.hash` for a cell containing data and references from this slice.\n\n#### `builder.hash`\n\nReturns `uint256` — the hash of the data in a builder. Equivalent to converting the builder to a cell and hashing it, without creating a cell.\n\n#### `slice.bitsHash`\n\nReturns `uint256` — the SHA-256 hash of the data bits in a slice, excluding references. If the bit length is not divisible by eight, throws a cell underflow exception.\n\n#### `isSignatureValid(hash, signatureSlice, publicKey)`\n\nVerifies an Ed25519 signature. Checks `signatureSlice` against `hash` using `publicKey`, both of type `uint256`. The signature must contain at least 512 data bits; only the first 512 bits are used. Returns `bool`.\n\n#### `isSliceSignatureValid(dataSlice, signatureSlice, publicKey)`\n\nSimilar to `isSignatureValid`, but accepts a `slice` instead of a precomputed hash. If the bit length of `data` is not divisible by eight, throws a cell underflow exception.\n\n#### `random.uint256`\n\nReturns `uint256` — a new pseudo-random value.\n\nCall `random.initialize` to make randomization unpredictable.\n\n#### `random.range(limit)`\n\nReturns `int` — a new pseudo-random integer z in the range `0..limit−1` or `limit..−1` if negative. More precisely, an unsigned random value `x` is generated, then `z := x * limit / 2^256` is computed.\n\nCall `random.initialize` to make randomization unpredictable.\n\n#### `random.getSeed`\n\nReturns `uint256` — the current random seed used to generate pseudo-random numbers.\n\n#### `random.setSeed(newSeed)`\n\nSets the random seed to the provided value.\n\n#### `random.initializeBy(mixSeedWith)`\n\nMixes the random seed with the provided value.\n\n#### `random.initialize`\n\nInitializes the seed with current time to make randomization unpredictable.\n\nCall this function once before using `random.uint256` or `random.range`.\n\n### Size computation primitives\n\nCan be useful for computing storage fees of user-provided data.\n\n#### `cell.calculateSize(maxCells)`\n\nReturns `(x, y, z, -1)` or `(null, null, null, 0)`. Recursively computes the count of distinct cells `x`, data bits `y`, and cell references `z` in a tree of cells. The total count of visited cells `x` cannot exceed non-negative `maxCells`; otherwise a zero flag is returned to indicate failure.\n\n#### `slice.calculateSize(maxCells)`\n\nSimilar to `cell.calculateSize`, but accepting a slice instead of a cell. The returned value `x` includes the cell that contains the slice.\n\n#### `cell.calculateSizeStrict(maxCells)`\n\nA non-quiet version of `cell.calculateSize` that throws a cell overflow exception on failure.\n\n#### `slice.calculateSizeStrict(maxCells)`\n\nA non-quiet version of `slice.calculateSize` that throws a cell overflow exception on failure.\n\n#### `cell.depth`\n\nReturns `int` — the depth of a cell: `0` if no references, otherwise `1` + maximum of depths of all references.\n\n#### `slice.depth`\n\nReturns `int` — the depth of a slice, equivalent to `cell.depth`.\n\n#### `builder.depth`\n\nReturns `int` — the depth of a builder, equivalent to `cell.depth`.\n\n#### `sizeof<T>(anyVariable)`\n\nReturns `int` — the number of stack slots occupied by `anyVariable` occupies; works at compile-time.\n\n### Debug primitives\n\nOnly work for local TVM execution with debug–level verbosity.\n\n#### `debug.print<T>(anyVariable)`\n\nDumps a variable to the debug log.\n\n#### `debug.printString(str)`\n\nDumps a string to the debug log.\n\n#### `debug.dumpStack`\n\nDumps the stack, at most the top 255 values, and shows its depth.\n\n### Slice primitives: parsing cells\n\n`cell.beginParse()` converts a cell into a slice.\n\n`slice.loadAddress` and other `loadXXX` methods are suggested by the IDE after a dot.\n\nPrefer [automatic serialization](/languages/tolk/features/auto-serialization) over manual slice parsing.\n\n### Builder primitives: constructing cells\n\n`beginCell()` creates a builder.\n\n`builder.storeAddress` and other `storeXXX` methods are suggested by the IDE after a dot.\n\n`builder.endCell()` constructs a cell from the written data.\n\nPrefer [automatic serialization](/languages/tolk/features/auto-serialization)\nover manual builder construction.\n\n### Address manipulation primitives\n\nMethods for [`address` and `any_address`](/languages/tolk/types/address) are suggested by the IDE after a dot.\n\n#### `address.fromWorkchainAndHash(wc, hash)`\n\nA static method of `address` — constructs an internal address with a size of 267 bits from arguments.\n\n```tolk\nfun demo() {\n    val a = address.fromWorkchainAndHash(0, somehash);\n    a.getWorkchain() == BASECHAIN;   // true\n}\n```\n\n#### `address.getWorkchain`\n\nReturns `int8` — the workchain from an [internal address](/foundations/addresses/formats).\n\n#### `address.getWorkchainAndHash`\n\nReturns `(int8, uint256)` — the workchain and hash from an internal address.\n\n#### `address.calculateSameAddressInAnotherShard(options)`\n\nGiven an internal address A=\"aaaa...a\", returns \"bbaa...a\". The result consists of D bits from address B and 256-D bits from address A.\n\n#### `createAddressNone`\n\nReturns any\\_address holding a slice `00`, which is two zero bits, at runtime. This value represents a none address.\n\n```tolk\nfun demo() {\n    val none = createAddressNone();  // it's `any_address`\n    none.isInternal();      // false\n    none.isNone();          // true\n}\n```\n\nThis is a rarely used `any_address`, not `address`. Use it only in combination with external addresses. For example, pass a `none` to `createExternalLogMessage`, which accepts `any_address`.\n\nTo represent [internal or none](/languages/tolk/types/address) , use `address?` and `null`.\n\n#### `any_address.isNone`, `any_address.isInternal`, `any_address.isExternal`\n\nChecks which specific blockchain address is contained in `any_address`.\n\n#### `any_address.castToInternal`\n\nCasts `any_address` to `address`, with a runtime check that the value is internal. To skip the check, use an [unsafe cast](/languages/tolk/types/type-checks-and-casts):\n`addr = myAny as address`.\n\n### Reserving Toncoins on the contract balance\n\nThe standard library provides several `RESERVE_MODE_XXX` constants for [reserve modes](/foundations/actions/reserve), as well as the following functions.\n\n#### `reserveToncoinsOnBalance`\n\nCreates an output action that reserves Toncoins on the contract balance.\n\n#### `reserveExtraCurrenciesOnBalance`\n\nSimilar to `reserveToncoinsOnBalance`, but also accepts a dictionary `extraAmount`.\n\n### Creating and sending messages\n\nStdlib provides several `SEND_MODE_XXX` constants for [sending modes](/foundations/messages/modes).\n\n[Message cell composition](/languages/tolk/features/message-sending) is encapsulated by the `createMessage` function.\n\nA low-level function, `sendRawMessage`, is also available, but its use is not recommended.\n\n## Modules requiring explicit imports\n\nIn addition to the always-available functions from `common.tolk`, Tolk provides several modules that must be explicitly imported before use.\n\n```tolk\nimport \"@stdlib/gas-payments\"\n```\n\nGas- and payment-related primitives. All functions are documented with detailed comments and can be explored in the IDE.\n\n- `getGasConsumedAtTheMoment`\n- `acceptExternalMessage`\n- `setGasLimitToMaximum`\n- `setGasLimit`\n- `calculateGasFee`\n- `calculateGasFeeWithoutFlatPrice`\n- `calculateStorageFee`\n- `calculateForwardFee`\n- `calculateForwardFeeWithoutLumpPrice`\n- `contract.getStorageDuePayment`\n- `contract.getStoragePaidPayment`\n\n```tolk\nimport \"@stdlib/exotic-cells\"\n```\n\nFunctions for loading and parsing [exotic cells](/foundations/serialization/cells), including library references.\n\n```tolk\nimport \"@stdlib/lisp-lists\"\n```\n\nLisp-style lists are represented as nested two-element tuples. For example, `[1, [2, [3, null]]]` represents the list `[1, 2, 3]`. They are rarely used in modern code.\n\n```tolk\nimport \"@stdlib/tvm-dicts\"\n```\n\nLow-level API for working with TVM dictionaries. Their use is not recommended; prefer [built-in maps](/languages/tolk/types/maps).\n\n```tolk\nimport \"@stdlib/tvm-lowlevel\"\n```\n\nFunctions for working with TVM registers and the stack.\n\n## Why are some functions `builtin`?\n\nMany functions in `common.tolk` don't provide `asm` instructions:\n\n```tolk\n@pure\nfun slice.loadInt(mutate self, len: int): int\n    builtin\n```\n\nThis is done for [optimization](/languages/tolk/features/compiler-optimizations) purposes. The compiler generates different assembler code depending on the arguments. For example, if `len` is a constant value such as `32`, `loadUint` is translated to `32 LDU`. If `len` is a variable, it is taken from the stack and the `LDUX` instruction is emitted.\n\nAnother example, `builder.storeUint(1, 32).storeUint(2, 64)` is not translated into `32 STU` and `64 STU`. Instead, these calls are merged into a single `STSLICECONST`.\n\n## How does the embedded stdlib work?\n\nThe stdlib is bundled with the compiler as the `tolk-stdlib/` directory and is discovered automatically. An import of the form `@stdlib/xxx` loads `{STDLIB_PATH}/xxx.tolk`.\n\nThe stdlib directory is discovered as follows:\n\n1. The compiler searches predefined and relative paths. For example, when launched from a system-installed package such as `/usr/bin/tolk`, the stdlib is located at `/usr/share/ton/smartcont`. For custom installations, the `TOLK_STDLIB` environment variable can be set.\n1. The WASM wrapper [tolk-js](https://github.com/ton-blockchain/tolk-js) also includes the stdlib, so it is already available when using blueprint.\n1. IDE plugins automatically locate the stdlib to provide auto-completion. Blueprint installs `tolk-js`, creating the `node_modules/@ton/tolk-js/` folder in the project structure. It contains `common.tolk`, `tvm-dicts.tolk`, and other stdlib files.\n"
  },
  {
    "path": "languages/tolk/from-func/converter.mdx",
    "content": "---\ntitle: \"FunC-to-Tolk converter\"\nsidebarTitle: \"Converter\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nThe [converter](https://github.com/ton-blockchain/convert-func-to-tolk) allows any FunC project to be transformed into Tolk with a single command:\n\n```bash\nnpx @ton/convert-func-to-tolk contracts\n```\n\nThis is a syntax-level converter that assists in migrating contracts to Tolk. It rewrites FunC code with one-to-one semantics and emits a Tolk version of the contract that remains close to the FunC original.\n\nExample input: [jetton-minter.fc](https://github.com/ton-blockchain/convert-func-to-tolk/blob/master/tests/inout/jetton-minter.fc).<br />\nExample output: [jetton-minter.tolk](https://github.com/ton-blockchain/convert-func-to-tolk/blob/master/tests/inout/jetton-minter.fc.tolk).\n\nThe converted contract does not use modern Tolk features such as structures, auto-serialization, or clean message composition. After some manual fixes, it compiles, runs, and passes tests.\n\nIf a contract does not compile after conversion, refer to the [GitHub repository](https://github.com/ton-blockchain/convert-func-to-tolk). It contains common issues and provides ways to fix them.\n\n## Refactoring\n\n- Use the modern [`onInternalMessage`](/languages/tolk/features/message-handling#oninternalmessage).\n- Extract a [`Storage` struct](/languages/tolk/features/contract-storage) with `toCell` and `fromCell`.\n- Refactor incoming messages into [structs](/languages/tolk/syntax/structures-fields#serialization-prefixes-and-opcodes) with 32-bit opcodes – incrementally, one message at a time.\n- Define a union of possible messages and match it using [`lazy`](/languages/tolk/features/lazy-loading).\n- Extract outgoing messages into structs and [send](/languages/tolk/features/message-sending) them.\n\n<Aside\n  type=\"tip\"\n  title={\"Maintain tests at every stage\"}\n>\n  Keeping tests passing throughout the refactoring process ensures safe, incremental modernization without breaking functionality.\n</Aside>\n\n## Examples\n\nThe [Tolk contract examples](/languages/tolk/examples) page features some contracts from the [Tolk vs. FunC benchmarks](https://github.com/ton-blockchain/tolk-bench) repository, all converted step by step using the migration tool. Check the Git history for each migration.\n"
  },
  {
    "path": "languages/tolk/from-func/stdlib-comparison.mdx",
    "content": "---\ntitle: \"Standard libraries comparison\"\nsidebarTitle: \"Standard libraries\"\n---\n\nTolk provides a standard library that evolved from [FunC's standard library](/languages/func/stdlib).\nTherefore, many functions from `stdlib.fc` can be mapped to Tolk, and most of these functions were converted into [methods](/languages/tolk/syntax/functions-methods).\n\n## Functions vs methods\n\nTolk supports [declaring methods](/languages/tolk/syntax/functions-methods), including primitives. Consequently, many FunC global-scope functions are now methods, e.g., `cell.hash()`, `tuple.size()`, etc.\n\n```tolk\n@pure\nfun cell.hash(self): uint256\n    asm \"HASHCU\"\n```\n\nIn FunC, `x.f()` works equally to `f(x)`. For instance, `someTuple.tuple_size()` and `tuple_size(someTuple)`. In Tolk, `someTuple.size()` is the only valid notation.\n\n## Renamed and removed functions\n\nFor `load_xxx`, `store_xxx`, and `skip_xxx`, use [automatic serialization](/languages/tolk/features/auto-serialization). Methods `slice.loadXXX`, `builder.storeXXX`, and `slice.skipXXX` are available for manual cell parsing, but their use is not recommended.\n\nFor `idict_xxx`, `udict_xxx`, and `dict_xxx`, use [native maps](/languages/tolk/types/maps). Dictionaries remain available in the file `@stdlib/tvm-dicts`, but their is not recommended.\n\nOther functions:\n\n| FunC name                     | Tolk name                            |\n| ----------------------------- | ------------------------------------ |\n| `empty_tuple`                 | `createEmptyTuple`                   |\n| `t~tpush(v)`                  | `t.push(v)`                          |\n| `first(t)` or `t.first()`     | `t.first()`                          |\n| `at(t,i)` or `t.at(i)`        | `t.get(i)` or dot-access `t.{i}`     |\n| `touch(v)`                    | `v.stackMoveToTop()`                 |\n| `impure_touch`                | _(deleted)_                          |\n| `single`                      | _(deleted)_                          |\n| `unsingle`                    | _(deleted)_                          |\n| `pair`                        | _(deleted)_                          |\n| `unpair`                      | _(deleted)_                          |\n| `triple`                      | _(deleted)_                          |\n| `untriple`                    | _(deleted)_                          |\n| `tuple4`                      | _(deleted)_                          |\n| `untuple4`                    | _(deleted)_                          |\n| `second`                      | _(deleted)_                          |\n| `third`                       | _(deleted)_                          |\n| `fourth`                      | _(deleted)_                          |\n| `pair_first`                  | _(deleted)_                          |\n| `pair_second`                 | _(deleted)_                          |\n| `triple_first`                | _(deleted)_                          |\n| `triple_second`               | _(deleted)_                          |\n| `triple_third`                | _(deleted)_                          |\n| `minmax`                      | `minMax`                             |\n| `now`                         | `blockchain.now`                     |\n| `my_address`                  | `contract.getAddress`                |\n| `get_balance + pair_first`    | `contract.getOriginalBalance`        |\n| `cur_lt`                      | `blockchain.logicalTime`             |\n| `block_lt`                    | `blockchain.currentBlockLogicalTime` |\n| `cell_hash(c)`                | `c.hash()`                           |\n| `slice_hash(s)`               | `s.hash()`                           |\n| `string_hash(s)`              | `s.bitsHash()`                       |\n| `check_signature`             | `isSignatureValid`                   |\n| `check_data_signature`        | `isSliceSignatureValid`              |\n| `compute_data_size(c)`        | `c.calculateSizeStrict()`            |\n| `slice_compute_data_size(s)`  | `s.calculateSizeStrict()`            |\n| `compute_data_size?(c)`       | `c.calculateSize()`                  |\n| `slice_compute_data_size?(s)` | `s.calculateSize()`                  |\n| `~dump`                       | `debug.print`                        |\n| `~strdump`                    | `debug.printString`                  |\n| `dump_stack`                  | `debug.dumpStack`                    |\n| `get_data`                    | `contract.getData`                   |\n| `set_data`                    | `contract.setData`                   |\n| `get_c3`                      | `getTvmRegisterC3`                   |\n| `set_c3`                      | `setTvmRegisterC3`                   |\n| `bless`                       | `transformSliceToContinuation`       |\n| `accept_message`              | `acceptExternalMessage`              |\n| `set_gas_limit`               | `setGasLimit`                        |\n| `buy_gas`                     | _(deleted)_                          |\n| `commit`                      | `commitContractDataAndActions`       |\n| `divmod`                      | `divMod`                             |\n| `moddiv`                      | `modDiv`                             |\n| `muldiv`                      | `mulDivFloor`                        |\n| `muldivr`                     | `mulDivRound`                        |\n| `muldivc`                     | `mulDivCeil`                         |\n| `muldivmod`                   | `mulDivMod`                          |\n| `begin_parse`                 | `beginParse`                         |\n| `end_parse(s)`                | `s.assertEnd()`                      |\n| `first_bits(s)`               | `s.getFirstBits()`                   |\n| `skip_last_bits(s)`           | `s.removeLastBits()`                 |\n| `slice_last(s)`               | `s.getLastBits()`                    |\n| `cell_depth(c)`               | `c.depth()`                          |\n| `slice_refs(s)`               | `s.remainingRefsCount()`             |\n| `slice_bits(s)`               | `s.remainingBitsCount()`             |\n| `slice_bits_refs(s)`          | `s.remainingBitsAndRefsCount()`      |\n| `slice_empty?(s)`             | `s.isEmpty()`                        |\n| `slice_data_empty?(s)`        | `s.isEndOfBits()`                    |\n| `slice_refs_empty?(s)`        | `s.isEndOfRefs()`                    |\n| `slice_depth(s)`              | `s.depth()`                          |\n| `equal_slice_bits(a,b)`       | `a.bitsEqual(b)`                     |\n| `builder_refs(b)`             | `b.refsCount()`                      |\n| `builder_bits(b)`             | `b.bitsCount()`                      |\n| `builder_depth(b)`            | `b.depth()`                          |\n| `begin_cell`                  | `beginCell`                          |\n| `end_cell`                    | `endCell`                            |\n| `parse_addr`                  | _(deleted)_                          |\n| `parse_std_addr`              | use `address` type                   |\n| `parse_var_addr`              | _(deleted)_                          |\n| `config_param`                | `blockchain.configParam`             |\n| `raw_reserve`                 | `reserveToncoinsOnBalance`           |\n| `raw_reserve_extra`           | `reserveExtraCurrenciesOnBalance`    |\n| `send_raw_message`            | use `createMessage`                  |\n| `set_code`                    | `contract.setCodePostponed`          |\n| `random`                      | `random.uint256`                     |\n| `rand`                        | `random.range`                       |\n| `get_seed`                    | `random.getSeed`                     |\n| `set_seed`                    | `random.setSeed`                     |\n| `randomize`                   | `random.initializeBy`                |\n| `randomize_lt`                | `random.initialize`                  |\n| `dump`                        | `debug.print`                        |\n| `strdump`                     | `debug.printString`                  |\n| `dump_stk`                    | `debug.dumpStack`                    |\n| `empty_list`                  | `createEmptyList`                    |\n| `cons`                        | `listPrepend`                        |\n| `uncons`                      | `listSplit`                          |\n| `list_next`                   | `listNext`                           |\n| `car`                         | `listGetHead`                        |\n| `cdr`                         | `listGetTail`                        |\n| `new_dict`                    | `createEmptyMap`                     |\n| `dict_empty?(d)`              | `m.isEmpty`                          |\n| `pfxdict_get?`                | `prefixDictGet`                      |\n| `pfxdict_set?`                | `prefixDictSet`                      |\n| `pfxdict_delete?`             | `prefixDictDelete`                   |\n\nLisp-style lists require an explicit import; IDEs usually add the import automatically.\n\n```tolk\nimport \"@stdlib/lisp-lists\"\n```\n\n## Mutating functions\n\nIn FunC, `x~method` mutates, whereas `x.method` returns a copy. In Tolk, methods are called with dot `.` and may [mutate](/languages/tolk/syntax/mutability) the object.\n\n| FunC                               | Tolk                                      |\n| ---------------------------------- | ----------------------------------------- |\n| `int n = cs~load_uint(32);`        | `var n = cs.loadUint(32);`                |\n| `var (cs2, n) = cs.load_uint(32);` | `var cs2 = cs; var n = cs2.loadUint(32);` |\n\n- If `cs~load_uint(…)` was used, `cs.loadUint(…)` behaves identically.\n- If `cs.load_uint(…)` was used to obtain a copy, a different approach is required.\n\n## Added functions\n\nTolk provides functions out of the box.\n\nThe [standard library](/languages/tolk/features/standard-library) is split into multiple files. Functions from `common.tolk` are always available, and most FunC analogues are included. Functions from other files must be explicitly imported:\n\n```tolk\nimport \"@stdlib/gas-payments\"\n\n// now `calculateGasFee()` and other symbols are visible\n```\n"
  },
  {
    "path": "languages/tolk/from-func/tolk-vs-func.mdx",
    "content": "---\ntitle: \"Tolk vs FunC\"\n---\n\nFunC is the first high-level language for TON smart contracts. Legacy FunC codebases exist, but the compiler is no longer maintained.\nTolk is the primary and only actively supported language in the TON ecosystem.\n\n## Migrating from FunC to Tolk\n\n1. Review the list of [differences](/languages/tolk/from-func/tolk-vs-func#key-differences).\n1. See the [Tolk contract examples](/languages/tolk/examples) page.\n1. Use the [FunC-to-Tolk converter](/languages/tolk/from-func/converter) to migrate existing projects.\n\n## Gas benchmarks\n\nThe [`tolk-bench` repository](https://github.com/ton-blockchain/tolk-bench) compares FunC and Tolk across several TEP contracts. See the [Tolk contract examples](/languages/tolk/examples) page for selected cases.\n\nAcross all measured metrics, Tolk reduces gas consumption by 30–50% compared to FunC. This reduction is primarily due to differences in language design.\n\n## Common characteristics\n\n- Both languages compile to Fift assembler.\n- Both languages run on [TVM](/tvm/overview) after compilation to bitcode.\n- Both languages are supported by [IDE plugins](/contract-dev/ide/overview).\n- Both languages are available in [Blueprint](/contract-dev/blueprint/overview) and other client-side tooling.\n- Both support command-line usage.\n\n## Key differences\n\nThe differences between Tolk and FunC are primarily in language design rather than syntax.\n\n### Basic syntax\n\n- FunC resembles C, the name stands for \"functional C\".\n- [Tolk resembles](/languages/tolk/basic-syntax) TypeScript, Rust, and Kotlin.\n\n```tolk\nfun sum(a: int, b: int): int {\n    return a + b;\n}\n```\n\n### Structures\n\n- FunC uses unnamed tensors such as `(int, slice, int, int)`.\n- Tolk uses named [structures](/languages/tolk/syntax/structures-fields) with the same runtime efficiency.\n\n```tolk\nstruct Demo {\n    previousValue: int256\n    ownerAddress: address\n    effectsCount: uint32\n    totalAmount: coins\n}\n```\n\n### Automatic serialization\n\n- FunC requires manual bit-level serialization using builders and slices.\n- Tolk derives [serialization](/languages/tolk/features/auto-serialization) from `struct` using `toCell` and `fromCell`.\n\n```tolk\nstruct Point {\n    x: int8\n    y: int8\n}\n\nfun demo() {\n    var value: Point = { x: 10, y: 20 };\n\n    // makes a cell containing \"0A14\" (hex)\n    var c = value.toCell();\n    // back to { x: 10, y: 20 }\n    var p = Point.fromCell(c);\n}\n```\n\nAll [integer types](/languages/tolk/types/numbers) such as `int8`, `uint64`, and `coins` are TVM integers.\n\n### Lazy loading\n\n- FunC requires manual control over preloads and skips for optimization.\n- Tolk uses the [`lazy` keyword](/languages/tolk/features/lazy-loading) to load only accessed fields.\n\n```tolk\nget fun publicKey() {\n    val st = lazy Storage.load();\n    // <-- here \"skip 65 bits, preload uint256\" is inserted\n    return st.publicKey\n}\n```\n\n### Boolean type\n\n- FunC represents only integers: `-1` for true, `0` for false; `ifnot`.\n- Tolk provides a [`bool` type](/languages/tolk/types/booleans) and logical operators `&&`, `||`, and `!`.\n\n```tolk\nif (trustInput || validate(input)) {\n    // ...\n}\n```\n\n### Address type\n\n- FunC represents only slices; bits comparison and parsing.\n- Tolk provides a [`address` type](/languages/tolk/types/address) with methods and the `==` operator.\n\n```tolk\nif (in.senderAddress == storage.ownerAddress) {\n    val workchain = storage.ownerAddress.getWorkchain();\n    // ...\n}\n```\n\n### Null safety\n\n- FunC allows any variable to hold `null`, which may lead to runtime errors.\n- Tolk provides [nullable types](/languages/tolk/types/nullable) `T?`, null safety, and smart casts.\n\n```tolk\nfun checkWithOptional(a: int, b: int?): bool {\n    if (b == null) {\n        return checkSingle(a);\n    }\n    return b >= 0 && checkDouble(a, b);\n}\n```\n\n### Type system features\n\n- FunC provides several types that expose TVM primitives.\n- Tolk provides [a type system](/languages/tolk/types/list-of-types), including unions, generics, and enums.\n\n```tolk\nstruct Container<T> {\n    element: T?\n}\n\nstruct Nothing\n\ntype Wrapper<T> = Nothing | Container<T>\n```\n\n### Methods for all types\n\n- FunC provides functions in the global scope only.\n- Tolk provides both [functions and methods](/languages/tolk/syntax/functions-methods), applicable to structures and primitives.\n\n```tolk\n// no `self` — static method\nfun Point.createZero(): Point {\n    return { x: 0, y: 0 }\n}\n\n// has `self` — instance method\nfun Point.sumCoords(self) {\n    return self.x + self.y\n}\n\n// even for primitives: cells, integers, tuples, etc.\nfun tuple.isEmpty(self) {\n    return self.size() == 0\n}\n```\n\n### No `impure` keyword\n\n- In FunC, if `impure` is omitted, a function call may be dropped.\n- In Tolk, user function calls are not removed by the compiler.\n\n```tolk\nfun validate(input: SomeStruct) {\n    // ...\n}\n```\n\n### No `~` tilde methods\n\n- FunC distinguishes between `x~f()` and `x.f()`.\n- Tolk uses a dot `.` syntax for method calls.\n\n```tolk\nval delta = someSlice.loadUint(32);   // mutates someSlice\nval owner = someSlice.loadAddress();\n```\n\n### Native maps over TVM dictionaries\n\n- FunC uses dictionaries, for example `m~idict_set_builder(1,32,begin_cell().store_uint(10,32))`.\n- Tolk provides native [maps](/languages/tolk/types/maps), for example `m.set(1, 10)`.\n\n```tolk\nvar m: map<int8, int32> = createEmptyMap();\nm.set(1, 10);\nm.addIfNotExists(2, -20);\nm.delete(2);   // now: [ 1 => 10 ]\n```\n\n### Message handling\n\n- FunC defines `() recv_internal(4 params)` and parses a message cell.\n- Tolk provides [`onInternalMessage(in)`](/languages/tolk/features/message-handling) and use `in.senderAddress`, etc.\n\n```tolk\nfun onInternalMessage(in: InMessage) {\n    // internal non-bounced messages arrive here\n    in.senderAddress;\n    in.originalForwardFee;\n    // and other fields\n}\n\nfun onBouncedMessage(in: InMessageBounced) {\n    // bounced messages arrive here\n}\n```\n\n### Message routing\n\n- FunC routes incoming messages using `if-else` checks on the `opcode`, for example `if (op == OP_TRANSFER)`.\n- Tolk routes messages using union types and [pattern matching](/languages/tolk/syntax/pattern-matching).\n\n```tolk\ntype MyMessage =\n    | CounterIncBy\n    | CounterReset\n    // ...\n\nfun onInternalMessage(in: InMessage) {\n    val msg = lazy MyMessage.fromSlice(in.body);\n    match (msg) {\n        CounterIncBy => {\n            // ...\n        }\n        CounterReset => {\n            // ...\n        }\n        // ...\n    }\n}\n```\n\n### Empty messages handling\n\n- FunC checks for empty message bodies using `if (slice_empty?(...))` at the beginning of `recv_internal()`.\n- Tolk handles empty or unknown messages using `else` in a [`lazy` matching](/languages/tolk/features/lazy-loading#lazy-matching).\n\n```tolk\nfun onInternalMessage(in: InMessage) {\n    val msg = lazy MyMessage.fromSlice(in.body);\n    match (msg) {\n        CounterReset => { /* ... */ }\n        // ... handle all variants of the union\n\n        else => {\n            // for example: ignore empty messages\n            if (in.body.isEmpty()) {\n                return\n            }\n            throw 0xFFFF\n        }\n    }\n}\n```\n\n### Message composition\n\n- FunC requires manual bit-level message construction, for example `store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)`.\n- Tolk provides [`createMessage`](/languages/tolk/features/message-sending), which automatically chooses between inline body and body reference.\n\n```tolk\nval reply = createMessage({\n    bounce: BounceMode.NoBounce,\n    value: ton(\"0.05\"),\n    dest: senderAddress,\n    body: RequestedInfo { ... }\n});\nreply.send(SEND_MODE_REGULAR);\n```\n\n### Deployment and `StateInit`\n\n- FunC requires manual packing of contract code and data according to TL-B.\n- Tolk uses `createMessage` to attach `StateInit` and compute the destination automatically.\n\n```tolk\nval deployMsg = createMessage({\n    // address auto-calculated, code+data auto-attached\n    dest: {\n        stateInit: {\n            code: contractCodeCell,\n            data: emptyStorage.toCell(),\n        },\n        // optionally control workchains and sharding\n    }\n});\n```\n\n### Identifier syntax\n\n- FunC allows arbitrary symbols in identifiers, for example `var 2+2 = ...`.\n- Tolk allows only [alphanumeric identifiers](/languages/tolk/syntax/variables), for example  `2+2` is `4`.\n\n```tolk\nconst OP_INCREASE = 0x12345678\n```\n\n### Automatic inlining of small functions\n\n- In FunC, prefer larger functions for reduced gas consumption.\n- In Tolk, the compiler auto-inlines functions without additional gas cost.\n\n```tolk\nfun int.zero() {\n    return 0\n}\n\nfun int.inc(mutate self, byValue: int = 1): self {\n    self += byValue;\n    return self;\n}\n\nfun main() {\n    return int.zero().inc().inc()\n}\n```\n\nIs reduced to `return 2` in assembler:\n\n```fift\nmain() PROC:<{\n    2 PUSHINT\n}>\n```\n\nIn FunC, `inline` modifier operates at the Fift level and may introduce extra stack permutations. In Tolk, inlining is performed at the compiler level and is combined with [constant folding](/languages/tolk/features/compiler-optimizations).\n\n### Merging consecutive `builder.storeUint`\n\n- FunC manually combines constant stores into `b.storeUint(0x18,6)`.\n- Tolk merges `b.storeUint(...).storeUint(...)` if constant.\n\n```tolk\nb.storeUint(0, 1)\n .storeUint(1, 1)\n .storeUint(1, 1)\n .storeUint(0, 1)\n .storeUint(0, 2)\n```\n\nTranslated to:\n\n```fift\nb{011000} STSLICECONST\n```\n\n### Standard library redesigned\n\nThere're [differences in a standard library](/languages/tolk/from-func/stdlib-fc). For example, functions from `stdlib.fc` use descriptive naming:\n\n|         FunC         |                Tolk               |\n| :------------------: | :-------------------------------: |\n|      `cur_lt()`      |     `blockchain.logicalTime()`    |\n|       `car(l)`       |          `listGetHead(l)`         |\n| `raw_reserve(coins)` | `reserveToncoinsOnBalance(coins)` |\n|      `~dump(x)`      |          `debug.print(x)`         |\n\nMany global-scope functions became methods for primitives:\n\n|            FunC            |         Tolk        |\n| :------------------------: | :-----------------: |\n|      `s.slice_hash()`      |      `s.hash()`     |\n|  `equal_slices_bits(a, b)` |   `a.bitsEqual(b)`  |\n|       `t.tuple_len()`      |      `t.size()`     |\n| `t~tpush(triple(x, y, z))` | `t.push([x, y, z])` |\n\nString postfixes like `\"...\"c` became built-in functions:\n\n|   FunC   |            Tolk           |\n| :------: | :-----------------------: |\n| `\"...\"c` |    `stringCrc32(\"...\")`   |\n| `\"...\"H` |   `stringSha256(\"...\")`   |\n| `\"...\"h` |  `stringSha256_32(\"...\")` |\n| `\"...\"a` |      `address(\"...\")`     |\n| `\"...\"s` | `stringHexToSlice(\"...\")` |\n| `\"...\"u` |  `stringToBase256(\"...\")` |\n\n### Assembler functions\n\nAlthough Tolk is a high-level language, it exposes [low-level capabilities](/languages/tolk/features/asm-functions). Code may still be written in a FunC-style with manual builders and slices, and TVM instructions are supported.\n\n```tolk\n@pure\nfun incThenNegate(v: int): int\n    asm \"INC\" \"NEGATE\"\n```\n"
  },
  {
    "path": "languages/tolk/idioms-conventions.mdx",
    "content": "---\ntitle: \"Idioms and conventions\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nAfter learning of [basic syntax](/languages/tolk/basic-syntax), study the common patterns, conventions, and best practices to write idiomatic Tolk code.\n\n## Prefer automatic serialization to manual one\n\nManual work with slices and builders is error-prone and tedious. By comparison, [auto-serialization](/languages/tolk/features/auto-serialization) with structures helps express data with types and prevents many related bugs.\n\n```tolk\nstruct Holder {\n    owner: address\n    lastUpdated: uint32\n    extra: Cell<ExtraInfo>\n}\n\nfun demo(data: Holder) {\n    // make a cell with 299 bits and 1 ref\n    val c = data.toCell();\n\n    // unpack it back\n    val holder = Holder.fromCell(c);\n}\n```\n\n## Prefer typed cells with `Cell<T>`\n\nAll data in TON is stored in cells. To express data relation clearly and to aid in [serialization](/languages/tolk/features/auto-serialization#controlling-cell-references-typed-cells), use cells with well-typed contents: `Cell<T>`.\n\n```tolk\nstruct Holder {\n    // ...\n    extra: Cell<ExtraInfo>\n}\n\nstruct ExtraInfo {\n    someField: int8\n    // ...\n}\n\nfun getDeepData(value: Holder) {\n    // `value.extra` is a reference\n    // use `load()` to access its contents\n    val data = value.extra.load();\n    return data.someField;\n}\n```\n\n## Use lazy data loading\n\nWhen reading data from cells, add the [`lazy` keyword](/languages/tolk/features/lazy-loading):\n\n- `lazy SomeStruct.fromCell(c)` over `SomeStruct.fromCell(c)`\n- `lazy typedCell.load()` over `typedCell.load()`\n\nWith `lazy`, the compiler loads only the requested fields, skipping the rest. This reduces gas consumption and bytecode size:\n\n```tolk\nget fun publicKey() {\n    val st = lazy Storage.load();\n    // <-- here, \"skip 65 bits, preload uint256\" is inserted\n    return st.publicKey\n}\n```\n\n## Use type aliases to express custom serialization logic\n\nSerialization may require custom rules which are not covered by existing types. Tolk allows defining custom [serialization rules for type aliases](/languages/tolk/types/overall-serialization#type-aliases):\n\n```tolk\n// The custom type alias over a regular, untyped slice\ntype MyString = slice\n\n// The function that is called when composing a new cell with a builder\nfun MyString.packToBuilder(self, mutate b: builder) {\n    // ...custom logic for MyString serialization\n}\n\n// The function that is called when loading data from the cell with a slice\nfun MyString.unpackFromSlice(mutate s: slice) {\n    // ...custom logic for MyString deserialization\n}\n\n// With those two functions implemented, MyString becomes\n// a type with clear serialization rules and can be used anywhere\nstruct Everywhere {\n    tokenName: MyString\n    fullDomain: Cell<MyString>\n}\n```\n\nConsider a structure that holds a signature hash of the data in its tail:\n\n```tolk\nstruct SignedRequest {\n    signature: uint256\n    // hash of all data below is signed\n    field1: int32\n    field2: address?\n    // ...\n}\n```\n\nThe task is to parse the structure and check the signature of the fields below `signature` against it. A manual approach would be to read `uint256`, calculate the hash of the remaining slice, then read other fields and compare the signatures.\n\nHowever, a better solution is to continue using auto-serialization by introducing a synthetic field populated only when loading a slice and never when composing a cell with a builder:\n\n```tolk\ntype HashOfRemainder = uint256\n\nstruct SignedRequest {\n    signature: uint256\n    restHash: HashOfRemainder // populated on load\n    field1: int32\n    field2: address?\n    // ...\n}\n\nfun HashOfRemainder.unpackFromSlice(mutate s: slice) {\n    // In this case, `s` is a slice remainder after loading `signature`,\n    // while the `restHash` field has to contain the hash of that remainder:\n    return s.hash()\n}\n\n// Now, assert that signatures match\nfun demo(input: slice) {\n    val req = SignedRequest.fromSlice(input);\n    assert (req.signature == req.restHash) throw XXX;\n}\n```\n\n## Use contract storage as a structure\n\n[Contract storage](/languages/tolk/features/contract-storage) is a regular `struct`, serialized into persistent on-chain data.\n\nAdd `load` and `store` methods for convenience:\n\n```tolk\nstruct Storage {\n    counterValue: int64\n}\n\nfun Storage.load() {\n    return Storage.fromCell(contract.getData())\n}\n\nfun Storage.save(self) {\n    contract.setData(self.toCell())\n}\n```\n\n## Express messages as structs with 32-bit prefixes\n\nBy convention, every message in TON has an _opcode_: a unique 32-bit number. In Tolk, every [`struct`](/languages/tolk/syntax/structures-fields) can have a serialization prefix of arbitrary length. Use 32-bit prefixes to express message opcodes.\n\n```tolk\nstruct (0x12345678) CounterIncrement {\n    // ...message body fields...\n}\n```\n\nWhen implementing [Jettons](/standard/tokens/jettons/overview), [NFTs](/standard/tokens/nft/overview), or other standard contracts, use predefined opcodes according to the specification. Otherwise, opcodes are ad hoc.\n\n## Use unions to handle incoming messages\n\nThe suggested pattern:\n\n1. Each [incoming message](/languages/tolk/features/message-handling) is made a struct with an opcode.\n1. Structs are combined into a union type.\n1. Union is used to lazily load data from the message body slice.\n1. Finally, result is [pattern matched](/languages/tolk/syntax/pattern-matching) over union variants.\n\n```tolk\nstruct (0x12345678) CounterIncrement {\n    incBy: uint32\n}\n\nstruct (0x23456789) CounterReset {\n    initialValue: int64\n}\n\ntype AllowedMessage = CounterIncrement | CounterReset\n\nfun onInternalMessage(in: InMessage) {\n    val msg = lazy AllowedMessage.fromSlice(in.body);\n    match (msg) {\n        CounterIncrement => {\n            // use `msg.incBy`\n        }\n        CounterReset => {\n            // use `msg.initialValue`\n        }\n        else => {\n            // invalid input; a typical reaction is:\n            // ignore empty messages, \"wrong opcode\" if not\n            assert (in.body.isEmpty()) throw 0xFFFF\n        }\n    }\n}\n```\n\nThe `lazy` keyword works with unions and performs a lazy match by the slice prefix: a message opcode. This approach is more efficient than manual opcode parsing and branching via a series of `if (op == TRANSFER_OP)` statements.\n\n## Use structs to send messages\n\nTo send a message from contract A to contract B:\n\n1. Declare a struct with an opcode and fields expected by the receiver.\n1. Use the `createMessage()` function to compose a message, and the `send()` method to send it.\n\n```tolk\nstruct (0x98765432) RequestedInfo {\n    // ...\n}\n\nfun respond(/* ... */) {\n    val reply = createMessage({\n        bounce: BounceMode.NoBounce,\n        value: ton(\"0.05\"),\n        dest: addressOfB,\n        body: RequestedInfo {\n            // ... initialize fields\n        }\n    });\n    reply.send(SEND_MODE_REGULAR);\n}\n```\n\n<Aside type=\"tip\">\n  When both contracts share the same codebase, a struct serves as an outgoing message for A and an incoming message for B.\n</Aside>\n\n## Attach initial code and data to a message to deploy another contract\n\nContract deployment is performed by attaching the code and data of the future contract to a message sent to its soon-to-be-initialized address. That address is deterministically calculated from the attached code and data.\n\nA common case is when the jetton minter contract deploys a jetton wallet contract per user, knowing the future wallet's initial state: code and data.\n\n```tolk\nval msgThatDeploys = createMessage({\n    // address auto-calculated, code+data auto-attached\n    dest: {\n        // initial state\n        stateInit: {\n            code: jettonWalletCode,\n            data: emptyWalletStorage.toCell(),\n        }\n    }\n});\n```\n\nSince one cannot synchronously check whether a contract is already deployed, the standard approach is always to attach the initial state needed for deployment whenever the contract's logic requires it.\n\nTo calculate or validate resulting addresses in addition to sending messages to them, always extract the `StateInit` generation to a separate function:\n\n```tolk\nfun calcDeployedJettonWallet(/* ... */): AutoDeployAddress {\n    val emptyWalletStorage: WalletStorage = {\n        // ... initialize fields from parameters\n    };\n\n    return {\n        stateInit: {\n            code: jettonWalletCode,\n            data: emptyWalletStorage.toCell()\n        }\n    }\n}\n\nfun demoDeploy() {\n    val deployMsg = createMessage({\n        // address auto-calculated, code+data auto-attached\n        dest: calcDeployedJettonWallet(...),\n        // ...\n    });\n    deployMsg.send(mode);\n}\n```\n\n<Aside type=\"tip\">\n  See the [Tolk contract examples](/languages/tolk/examples#jetton) page for selected contracts from the [`tolk-bench`](https://github.com/ton-blockchain/tolk-bench).\n</Aside>\n\n## Target certain shards when deploying sibling contracts\n\nSpecify the prefix length and the contract address to aim for the [same shard](/languages/tolk/features/message-sending#shard-based-deployment). For example, sharded jetton wallet must be deployed to the same shard as the owner's wallet.\n\n```tolk\nval deployMsg = createMessage({\n    dest: {\n        stateInit: { code, data },\n        toShard: {\n            closeTo: ownerAddress,\n            fixedPrefixLength: 8\n        }\n    }\n});\n```\n\n## Emit events and logs to off-chain world during development\n\n[External messages](/languages/tolk/features/message-sending#universal-createexternallogmessage) with a special address `none` are used to emit events and logs to the outer world. Indexers catch such messages and provide a picture of on-chain activity.\n\nExternal messages cost less gas than internal ones and help track events during contract development. They provide a simple way to emit structured logs that indexers and debugging tools can consume.\n\nTo send an external log message:\n\n1. Create a `struct` to represent the message body.\n1. Use `createExternalLogMessage()` to compose a message and the `send()` method to send it.\n\n```tolk\nstruct DepositEvent {\n    // ...fields...\n}\n\nfun demo() {\n    val emitMsg = createExternalLogMessage({\n        dest: createAddressNone(),\n        body: DepositEvent {\n            // ...field values...\n        }\n    });\n    emitMsg.send(SEND_MODE_REGULAR);\n}\n```\n\n## Return several state values as a structure from a get method\n\nWhen a [contract getter](/languages/tolk/features/contract-getters) needs to return several values, introduce a structure. Avoid returning unnamed tensors like `(int, int, int)`. Field names provide clear metadata for client wrappers and human readers.\n\n```tolk\nstruct JettonWalletDataReply {\n    jettonBalance: coins\n    ownerAddress: address\n    minterAddress: address\n    jettonWalletCode: cell\n}\n\nget fun get_wallet_data(): JettonWalletDataReply {\n    return {\n        jettonBalance: ...,\n        ownerAddress: ...,\n        minterAddress: ...,\n        jettonWalletCode: ..,\n    }\n}\n```\n\n## Validate user input with assertions\n\nAfter parsing an incoming message, validate required fields with [`assert`](/languages/tolk/syntax/exceptions#assert-statement):\n\n```tolk\nassert (msg.seqno == storage.seqno) throw E_INVALID_SEQNO;\nassert (msg.validUntil > blockchain.now()) throw E_EXPIRED;\n```\n\nIf a condition is violated, execution terminates with the specified error code. Otherwise, a contract remains ready to serve the next request. This is the standard mechanism for reacting to invalid input.\n\n## Organize a project into several files\n\nConsistent file structure across projects simplifies navigation:\n\n- Supply `errors.tolk` with constants or enums.\n- Supply `storage.tolk` with storage and helper methods.\n- Supply `messages.tolk` with incoming and outgoing messages.\n- Have `some-contract.tolk` as an entrypoint. Keep entrypoint files minimal, use [imports](/languages/tolk/syntax/imports) to bring all supplementary code.\n\nWhen developing several related contracts simultaneously, keep them in the same codebase. For instance, struct `SomeMessage`, outgoing for contract A, can be incoming for contract B. In other cases,  contract A must know B's storage to assign the initial state for deployment.\n\n## Prefer methods to functions\n\nAll symbols across different files share the same namespace and must have unique names project-wide. There are no modules or exports.\n\nUse [methods](/languages/tolk/syntax/functions-methods) to avoid name collisions:\n\n```tolk\nfun Struct1.validate(self) { /* ... */ }\nfun Struct2.validate(self) { /* ... */ }\n```\n\nMethods are also more convenient: `obj.someMethod()` reads better than `someFunction(obj)`.\n\n```tolk\nstruct AuctionConfig {\n    // ...fields...\n}\n\n// Prefer this:\nfun AuctionConfig.isInvalid(self) {\n    // ...\n}\n\n// Over this:\n// fun isAuctionConfigInvalid(config: AuctionConfig) {}\n```\n\nStatic methods follow the same pattern: `Auction.createFrom(...)` reads better than `createAuctionFrom(...)`.\n\nA method without a `self` parameter is static:\n\n```tolk\nfun Auction.createFrom(config: cell, minBid: coins) {\n    // ...\n}\n```\n\nStatic methods also group utility functions. For example, standard functions like `blockchain.now()` are static methods on an empty struct. This technique emulates namespaces:\n\n```tolk\nstruct blockchain\n\nfun blockchain.now(): int /* ... */;\nfun blockchain.logicalTime(): int /* ... */;\n```\n\n## Use optional addresses to have address defaults\n\nA nullable [address](/languages/tolk/types/address) `address?` is a pattern for an optional address, sometimes called _\"maybe address\"_:\n\n- `null` represents the address `none`.\n- `address` represents an internal address.\n\n## Calculate CRC32 or SHA256 at compile-time\n\nSeveral [built-in functions](/languages/tolk/features/standard-library) operate on [strings](/languages/tolk/types/strings) and work at compile-time:\n\n```tolk\n// Calculates CRC32 of a string\nconst crc32 = stringCrc32(\"some_str\")\n\n// Calculates SHA256 of a string as a 256-bit integer\nconst hash = stringSha256(\"some_crypto_key\")\n```\n\n## Encode slices as strings\n\nTVM has no [strings](/languages/tolk/types/strings), only slices. A binary slice must be encoded in a specific way to be parsed and interpreted correctly as a string:\n\n1. Fixed-size strings via `bitsN` are possible if the size is predefined.\n1. Snake strings place a portion of data in the current cell and the rest in a ref cell, recursively. Use custom serializers to enable construction and parsing of such variable-length strings.\n\n## Avoid micro-optimization\n\nThe [compiler applies many optimizations](/languages/tolk/features/compiler-optimizations): it automatically inlines functions, reduces stack allocations, and handles the underlying work. Attempts to outsmart the compiler yield negligible effects, either positive or negative.\n\nPrefer readability over manual optimizations:\n\n- Use one-line methods freely as they are auto-inlined.\n- Use flat structures: they are as efficient as raw stack values.\n- Extract standalone values into constants and variables.\n- Avoid assembler functions unless necessary.\n"
  },
  {
    "path": "languages/tolk/overview.mdx",
    "content": "---\ntitle: \"Tolk language\"\nsidebarTitle: \"Overview\"\n---\n\nTolk is a statically typed language for writing smart contracts on TON. It provides declarative data structures, automatic cell serialization, and message handling primitives.\n\nThe language compiles to [TVM](/tvm/overview) and provides direct control over execution.\n\n```tolk\ntype AllowedMessage = CounterIncrement | CounterReset\n\nfun onInternalMessage(in: InMessage) {\n    val msg = lazy AllowedMessage.fromSlice(in.body);\n    match (msg) {\n        CounterIncrement => { ... }\n        CounterReset => { ... }\n    }\n}\n\nget fun currentCounter() {\n    val storage = lazy Storage.load();\n    return storage.counter;\n}\n```\n\nTolk is compatible with existing [TON standards](/from-ethereum#standards).\n\n## Key features\n\nTolk provides high-level readability while preserving low-level control:\n\n- a type system for describing [cell](/foundations/serialization/cells) layouts;\n- [`lazy` loading](/languages/tolk/features/lazy-loading) that skips unused fields;\n- unified message composition and deployment;\n- a compiler targeting the Fift assembler;\n- tooling with IDE integration.\n\n## From FunC to Tolk\n\nTolk evolved from FunC and is now the recommended language for TON smart contracts. To migrate from FunC:\n\n- see [Tolk contract examples](/languages/tolk/examples) for embedded jetton and NFT examples;\n- check [gas benchmarks](https://github.com/ton-blockchain/tolk-bench);\n- read [Tolk vs FunC](/languages/tolk/from-func/tolk-vs-func) for an overview;\n- use the [FunC-to-Tolk converter](/languages/tolk/from-func/converter) to migrate existing projects.\n\n## Quick start\n\n1. Run the command:\n\n   ```bash\n   npm create ton@latest\n   ```\n\n1. Enter a project name and choose \"A simple counter contract (Tolk)\".\n\n1. Follow [Your first smart contract](/contract-dev/first-smart-contract) page to write the contract in Tolk.\n\n## IDE support\n\n1. [JetBrains IDEs plugin](/contract-dev/ide/jetbrains#tolk) provides syntax highlighting and code navigation.\n1. [VSCode extension](/contract-dev/ide/vscode#tolk) adds syntax highlighting, code navigation, and other language features for VS Code and VS Code-based editors such as VSCodium, Cursor, and Windsurf.\n1. [Language server](https://github.com/ton-blockchain/ton-language-server#other-editors) supports (Neo)Vim, Helix, and other editors with LSP support.\n\n## Start with\n\n- [Basic syntax](/languages/tolk/basic-syntax)\n- [Idioms and conventions](/languages/tolk/idioms-conventions)\n- [Contract examples](/languages/tolk/examples)\n- [Type system](/languages/tolk/types/list-of-types)\n- [Message handling](/languages/tolk/features/message-handling)\n"
  },
  {
    "path": "languages/tolk/syntax/conditions-loops.mdx",
    "content": "---\ntitle: \"Conditions and loops\"\n---\n\nTolk provides constructs for controlling contract flow.\n\n- Use `if`, `assert`, and loops for conditional logic.\n- Use `match` expression for [pattern matching](/languages/tolk/syntax/pattern-matching).\n\n## `if` statement\n\n`if` statement works as in most languages. `else if` and `else` blocks are optional.\n\n```tolk\nif (condition) {\n    // ...\n} else {\n    // ...\n}\n```\n\nA condition must be a boolean or an integer. If not equals 0, then `true`:\n\n```tolk\nif (someInt) {     // means \"someInt != 0\"\n    // ...\n}\n```\n\nThe body of `if` and `else` must be enclosed in `{ ... }`:\n\n```tolk\n// invalid\nif (condition)\n    someFn();\n\n// valid\nif (condition) {\n    someFn();\n}\n```\n\n## `assert` statement\n\n`assert` throws an [exceptions](/languages/tolk/syntax/exceptions) if a condition is false.\n\n```tolk\nassert (condition) throw ERR_CODE;\n```\n\nIt is equivalent to the following form:\n\n```tolk\nif (!condition) {\n    throw ERR_CODE;\n}\n```\n\n## `match` expression\n\n`match` is used to perform different actions for different values of a variable. A common use case is routing values of a [union type](/languages/tolk/types/unions):\n\n```tolk\nfun demo(v: A | B | C) {\n    match (v) {\n        A => {\n            // use `v.aField` etc.\n        }\n        B => { /* ... */ }\n        C => { /* ... */ }\n    }\n}\n```\n\nThe `match` is equivalent to a series of `if-else` checks:\n\n```tolk\nfun demo(v: A | B | C) {\n    if (v is A) {\n        // use `v.aField` etc.\n    }\n    else if (v is B) { /* ... */ }\n    else { /* ... */ }\n}\n```\n\nThe `match` can also be used for expressions, switch-like behavior:\n\n```tolk\nfun invertNumber(curValue: int) {\n    return match (curValue) {\n        1 => 0,\n        0 => 1,\n        else => throw ERR_UNEXPECTED,\n    };\n}\n```\n\n## Ternary operator\n\nThe ternary form `condition ? when_true : when_false` is available:\n\n```tolk\nfun myAbs(v: int) {\n    return v < 0 ? -v : v\n}\n```\n\nIf the types of `when_true` and `when_false` differ, the result becomes a union type. In most cases this is unintended, so the compiler reports an error.\n\n```tolk\nfun demo(a: int32, b: int64) {\n    // instead of inferring result1 as `int32 | int64`,\n    // an error \"probably it's not what you expected\"\n    val result1 = a > b ? a : b;\n\n    // correct: specify the type manually\n    val result2: int = a > b ? a : b;\n\n    // also correct, types are compatible\n    val result3 = a > b ? a as int64 : b;\n}\n```\n\n## `while` loops\n\n`while` and `do-while` loops repeatedly execute their bodies while the condition remains `true`. `while` checks the condition first and may not execute the body at all, whereas `do-while` runs the body first.\n\n```tolk\nfun demoWhile(i: int) {\n    while (i > 0) {\n        debug.print(i);\n        i -= 1;\n    }\n}\n\nfun demoDoWhile() {\n    var rand: int;\n    do {\n        rand = random.uint256();\n    } while (rand % 2 == 0);\n    return rand;  // an odd number\n}\n```\n\n`while` is used to iterate over maps:\n\n```tolk\nfun iterateOverMap(m: map<int32, Point>) {\n    var r = m.findFirst();\n    while (r.isFound) {\n        // ...\n        r = m.iterateNext(r);\n    }\n}\n```\n\n## `repeat` loop\n\nThe `repeat (N)` statement executes its block `N` times:\n\n```tolk\nrepeat (5) {\n    // executed 5 times\n}\n```\n\n`N` may be either a constant or a variable.\n\n## `break` and `continue`\n\nThe keywords `break` and `continue` are not supported.\n"
  },
  {
    "path": "languages/tolk/syntax/exceptions.mdx",
    "content": "---\ntitle: \"Exceptions in Tolk\"\nsidebarTitle: \"Exceptions\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nTolk supports exceptions and handling them with `try catch`. If an exception is not caught, the program terminates with `errCode`.\n\nIn [TVM](/tvm/overview), exceptions are numbers. There is no `Error` class or exception hierarchy, only [exit codes](/tvm/exit-codes).\n\n## Error codes\n\nA simple pattern is to define a constant for each exception that a contract may produce:\n\n```tolk\nconst ERR_LOW_BALANCE = 200\nconst ERR_SIGNATURE_MISMATCH = 201\n```\n\nYet, this pattern should not be used in production environments, as it does not scale. Instead, use an `enum` — they are easier to maintain and reference, as enumerations come with exhaustive checks from the compiler:\n\n```tolk\nenum ErrCode {\n    LowBalance = 200,\n    SignatureMismatch,    // implicitly 201\n}\n```\n\nUse these constants in `throw` and related statements described on this page.\n\n<Aside\n  type=\"tip\"\n  title={\"Use error codes between 64 and 2048\"}\n>\n  Lower values are [reserved](/tvm/exit-codes) by TVM. Larger ones are more gas-expensive.\n</Aside>\n\n## `throw` statement\n\nTo throw an exception unconditionally:\n\n```tolk\nthrow ERR_CODE;\n```\n\nNon-constant expressions such as `throw someVariable` are supported but not recommended. It works, but the compiler cannot determine possible error codes and therefore cannot provide a correct ABI for external callers.\n\nAn exception can carry an argument:\n\n```tolk\nthrow (ERR_CODE, errArg);\n```\n\nThe argument is available in `catch` and must be a TVM primitive, not a tuple nor a tensor.\n\n## `assert` statement\n\nAn `assert` is a shorthand for \"throw if a condition is not satisfied\". It is commonly used when parsing user input:\n\n```tolk\nassert (msg.seqno == storage.seqno) throw E_INVALID_SEQNO;\nassert (msg.validUntil > blockchain.now()) throw E_EXPIRED;\n```\n\n- The long form `assert (condition) throw ERR_CODE` is preferred.\n- The short form `assert (condition, ERR_CODE)` exists but is not recommended.\n\nThe `condition` must be either a boolean or an integer, where non-zero integers are treated as `true` and all other integer values as `false`.\n\nAn `assert` statement is equivalent to:\n\n```tolk\nif (!condition) {\n    throw ERR_CODE;\n}\n```\n\n## TVM implicit throws\n\nDuring contract execution, TVM may throw runtime exceptions. For example:\n\n- `slice.loadInt(8)` will fail when the slice is empty.\n- `builder.storeRef(cell)` will fail when the builder has 4 references already.\n- `tuple.push(value)` will fail when the tuple has 255 elements already.\n- etc.\n\nAdditionally, an [out-of-gas exception](/tvm/exit-codes#14%3A-out-of-gas-error) may occur at **any** point, and it cannot be caught using a [`catch`](#try-catch-statement) block. It can only be prevented by writing [exhaustive testing suites](/contract-dev/testing/overview).\n\n## `try catch` statement\n\nThe `catch` block is used to handle most runtime errors within the `try` block, except for out-of-gas exceptions:\n\n```tolk\ntry {\n    // ...\n} catch (errCode) {\n    // errCode is `int`\n}\n```\n\n- Use the short form `catch { ... }` when `errCode` is not needed.\n- Use the long form `catch (errCode, arg)` when the exception may carry an argument produced by `throw (errCode, arg)`. If the exception was thrown as `throw errCode`, the argument is `null`.\n\n```tolk\ntry {\n    throw (ERR_LOW_BALANCE, 555);\n} catch (errCode, arg) {\n    val data = arg as int;    // 555\n}\n```\n\n<Aside\n  type=\"caution\"\n>\n  Any error inside a `try` block reverts all changes made within. TVM restores local variables and control registers to the state they had before entering `try`.\n\n  However, gas counters and TVM codepage settings are **not** rolled back. Gas is always spent.\n</Aside>\n"
  },
  {
    "path": "languages/tolk/syntax/functions-methods.mdx",
    "content": "---\ntitle: \"Functions and methods\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n## Function declaration\n\nA function is declared using the `fun` keyword, followed by the function name and parameters:\n\n```tolk\nfun f(<params>)\n```\n\n### Parameter type\n\nEach function parameter must have an explicit type.\n\n```tolk\n// invalid:\nfun sum(a, b) {}\n\n// valid:\nfun sum(a: int, b: bool) {}\n```\n\n### Return type\n\nA function may declare its return type explicitly:\n\n```tolk\nfun demo(): int {\n    // ...\n}\n```\n\nIf the return type is omitted, the compiler infers it from `return` statements:\n\n```tolk\nfun demo() {   // auto-infer `int`\n    // ...\n    return 10;\n}\n```\n\nIf different `return` statements produce different types, the compiler reports an error. Union types are not inferred, as this usually indicates a bug.\n\n### Default parameter value\n\nDefault values are placed after the type and must be constant expressions:\n\n```tolk\nfun plus(value: int, delta: int = 1) {\n    return value + delta\n}\n\nfun demo() {\n    plus(10);     // 11\n    plus(10, 5);  // 15\n}\n```\n\n## Method declaration\n\nMethods are declared as extension functions with a receiver specified before the name:\n\n```tolk\nfun <receiver>.f(<params>)\n```\n\n### Instance and static methods\n\nIf the first parameter is `self`, it is an instance method: `fun <receiver>.f(self, ...)`. Otherwise, it is a static method: `fun <receiver>.f(...)`.\n\n```tolk\nstruct Point {\n    x: int\n    y: int\n}\n\n// has `self` — instance method\nfun Point.sumCoords(self) {\n    return self.x + self.y\n}\n\n// no `self` — static method\nfun Point.createZero(): Point {\n    return { x: 0, y: 0 }\n}\n\n```\n\nInstance methods are invoked using `obj.method()`. Static methods are invoked on the receiver type.\n\n```tolk\nfun demo() {\n    val p = Point.createZero();\n    return p.sumCoords();    // 0\n}\n```\n\n### Receiver and `self`\n\nThe type of `self` is determined by the receiver. All parameters after `self` must have explicit types. If the return type is omitted, it is inferred.\n\n```tolk\nfun Point.equalTo(self, r: Point) {   // auto-infer `bool`\n    return self.x == r.x && self.y == r.y\n}\n```\n\n### Methods for non-struct types\n\nMethods are not limited to structures. They may be declared for any receiver type, unions, aliases, and primitives:\n\n```tolk\nfun int.one() {\n    return 1\n}\n\nfun int.negate(self) {\n    return -self\n}\n\nfun demo() {\n    return int.one().negate()   // -1\n}\n```\n\nAll standard methods are declared this way: `fun cell.hash(self)`.\n\n## Immutability of `self`\n\nIn instance methods, `self` is immutable by default.\n\nTo allow modifications, declare [`mutate self`](/languages/tolk/syntax/mutability) explicitly.\n\n```tolk\n// mind `mutate` — to allow modifications\nfun Point.reset(mutate self) {\n    self.x = 0;\n    self.y = 0;\n}\n```\n\n### Returning `self` and method chaining\n\nReturning `self` makes a method chainable. To enable chaining, declare the `return` type as `self`.\n\nFor example, all methods of `builder` return `self`, which allows consecutive calls like `b.storeXXX().storeXXX()`.\n\n```tolk\nfun builder.myStoreInt32(mutate self, v: int): self {\n    self.storeInt(v, 32);\n    return self;\n}\n\nfun demo() {\n    return beginCell()\n        .storeAddress(SOME_ADDR)\n        .myStoreInt32(123)\n        .endCell();\n}\n```\n\n## Generic functions\n\nA function declared with type parameters `T` is called a generic function.\n\n```tolk\nfun duplicate<T>(value: T): (T, T) {\n    var copy: T = value;\n    return (value, copy);\n}\n```\n\n### Type parameter inference\n\nWhen calling a generic function, the compiler automatically infers type arguments:\n\n```tolk\nfun demo() {\n    duplicate(1);         // duplicate<int>\n    duplicate(somePoint); // duplicate<Point>\n    duplicate((1, 2));    // duplicate<(int, int)>\n}\n```\n\n### Explicit type arguments\n\nType arguments may be specified explicitly using `f<...>(args)`:\n\n```tolk\nfun demo() {\n    duplicate<int32>(1);\n    duplicate<Point?>(null);    // two nullable points\n}\n```\n\n### Multiple type parameters\n\nA generic function may declare multiple type parameters:\n\n```tolk\n// returns `(tensor.0 || defA, tensor.1 || defB)`\nfun replaceNulls<T1, T2>(tensor: (T1?, T2?), defA: T1, defB: T2): (T1, T2) {\n    var (a, b) = tensor;\n    return (a == null ? defA : a, b == null ? defB : b);\n}\n```\n\n### Default type parameters\n\nGeneric functions may define default type parameters:\n\n```tolk\nfun f<T1, T2 = int>(value: T1): T2 {\n    // ...\n}\n```\n\nDefault type parameters cannot reference other type parameters.\n\n### Generic functions as values\n\nSince Tolk supports first-class functions, generic functions can be passed as arguments and stored in variables.\n\n```tolk\nfun customInvoke<TArg, R>(f: TArg -> R, arg: TArg) {\n    return f(arg);\n}\n```\n\n### Type inference limitations\n\nAlthough type parameters are usually inferred from function arguments, there are cases where a type parameter `<T>` cannot be inferred because it does not depend on them. Tuples are a common example:\n\n```tolk\n// a method `tuple.get` is declared this way in stdlib:\nfun tuple.get<T>(self, index: int): T;\n\nfun demo(t: tuple) {\n    var mid = t.get(1);    // error, can not deduce T\n\n    // correct is:\n    var mid = t.get<int>(1);\n    // or\n    var mid: int = t.get(1);\n}\n```\n\n### Assigning generic functions to variables\n\nA generic function may be assigned to a variable. Since this is not a function call, `<T>` must be specified explicitly:\n\n```tolk\nfun genericFn<T>(v: T) {\n    // ...\n}\n\nfun demo() {\n    var callable = genericFn<builder>;\n    callable(beginCell());\n}\n```\n\n## Generic methods\n\nDeclaring a method for a generic type does not differ from declaring any other method.\nWhen parsing the receiver, the compiler treats unknown symbols as type parameters.\n\n```tolk\nstruct Pair<T1, T2> {\n    first: T1\n    second: T2\n}\n\n// both <T1,T2>, <A,B>, etc. work: any unknown symbols\nfun Pair<A, B>.create(f: A, s: B): Pair<A, B> {\n    return {\n        first: f,\n        second: s,\n    }\n}\n\n```\n\n### Instance generic methods\n\nGeneric methods can be instance methods by declaring `self`:\n\n```tolk\n// instance method with `self`\nfun Pair<A, B>.compareFirst(self, rhs: A) {\n    return self.first <=> rhs\n}\n```\n\n### Generic methods as values\n\nGeneric methods can be also used as first-class functions:\n\n```tolk\nvar callable = Pair<int, slice>.compareFirst;\ncallable(somePair, 123);    // pass somePair as self\n```\n\n### Methods for generic structure\n\nMethods for generic structures can themselves be generic:\n\n```tolk\nfun Pair<A, B>.createFrom<U, V>(f: U, s: V): Pair<A, B> {\n    return {\n        first: f as A,\n        second: s as B,\n    }\n}\n\nfun demo() {\n    return Pair<int?, int?>.createFrom(1, 2);\n}\n```\n\n## Specialization and overloading\n\nOverloading and partial specialization allow declaring multiple methods with the same name for different receiver types without conflicts.\n\n### Methods for any receiver\n\nA method may be declared for an arbitrary receiver by using an unknown symbol, typically `T`, as the receiver types. Such a method is applicable to any type.\n\n```tolk\n// any receiver\nfun T.copy(self): T {\n    return self\n}\n\n// any nullable receiver\nfun T?.isNull(self): bool {\n    return self == null\n}\n```\n\n### Overloading by receiver type\n\nSpecific receiver types do not conflict:\n\n```tolk\nfun T.someMethod(self) { ... }\nfun int.someMethod(self) { ... }\n\nfun demo() {\n    42.someMethod();              // (2)\n    address(\"...\").someMethod();  // (1) with T=address\n}\n```\n\n### Partial specialization for generic receivers\n\nA method declared for a generic receiver may have specialized implementations for predefined types or patterns. Consider an iterator over a tuple of slices, where each slice encodes a value of type `T`:\n\n```tolk\nstruct TupleIterator<T> {\n    data: tuple      // [slice, slice, ...]\n    nextIndex: int\n}\n\nfun TupleIterator<T>.next(self): T {\n    val v = self.data.get<slice>(self.nextIndex);\n    self.nextIndex += 1;\n    return T.fromSlice(v);\n}\n```\n\nFor `TupleIterator<int32>` or `TupleIterator<Point>`, `next()` decodes the next slice and returns a value of type `T`. However, additional requirements are:\n\n- `TupleIterator<slice>` should return `data[i]` without calling `fromSlice()`;\n- `TupleIterator<Cell<T>>` should unpack a cell and return `T`, not `Cell<T>`.\n\nTolk allows overloading methods for more specific receiver types:\n\n```tolk\nfun TupleIterator<T>.next(self): T { ... }\nfun TupleIterator<Cell<T>>.next(self): T { ... }\nfun TupleIterator<slice>.next(self): slice { ... }\n```\n\nAnother example declares an extension method for `map<K, V>`, with specialized implementations for specific receiver patterns:\n\n- when `V = K`,\n- and when `V` is another map, the method behavior differs.\n\n```tolk\nfun map<K, V>.method(self) { ... }\nfun map<K, K>.method(self) { ... }\nfun map<K, map<K2, V2>>.method(self) { ... }\n\n// (1) called for map<int8, int32> / map<bits4, Cell<bits4>>\n// (2) called for map<bool, bool> / map<int8, AliasForInt8>\n// (3) called for map<address, map<int32, ()>>\n```\n\n<Aside type=\"note\">\n  If a user declares `struct T`, methods like `fun T.copy()` are interpreted as specializations rather than as generic methods.\n  To avoid ambiguity, do not use single-letter type names for concrete types; prefer descriptive names.\n</Aside>\n\n## Auto-inline small functions\n\nThe [compiler automatically inlines small functions](/languages/tolk/features/compiler-optimizations) in-place when possible. For example:\n\n```tolk\nfun int.zero() {\n    return 0\n}\n\nfun int.inc(mutate self, byValue: int = 1): self {\n    self += byValue;\n    return self;\n}\n\nfun main() {\n    return int.zero().inc().inc()\n}\n```\n\nIt is reduced to the following assembler code:\n\n```fift\nmain() PROC:<{\n    2 PUSHINT\n}>\n```\n\n## Attributes\n\nA function or method may be preceded by one or several attributes:\n\n```tolk\n@noinline\n@custom(\"any contents here\")\nfun slowSum(a: int, b: int) {\n    return a + b\n}\n```\n\nThe following attributes are allowed:\n\n- `@inline` forces a function to be inlined in-place. Typically unnecessary, as the compiler performs inlining automatically.\n- `@inline_ref` enables a special form of inlining where the function body is embedded as a child cell reference in the resulting bytecode.\n- `@noinline` turns off inlining for a function, for example, for a slow path.\n- `@method_id(<number>)` is a low-level annotation to manually override the TVM `method_id`.\n- `@pure` indicates that a function does not modify global state, including TVM state. If its result is unused, the call may be removed and typically used in assembler functions.\n- `@deprecated` marks a function as deprecated; it exists only for backward compatibility.\n- `@custom(<anything>)` is a custom expression that is not analyzed by the compiler.\n\n## Assembler functions\n\nTolk supports declaring low-level [assembler functions](/languages/tolk/features/asm-functions) with embedded Fift code:\n\n```tolk\n@pure\nfun minMax(x: int, y: int): (int, int)\n    asm \"MINMAX\"\n```\n\n## Anonymous functions (lambdas)\n\nTolk supports first-class functions: [they can be passed as callbacks](/languages/tolk/types/callables).\nBoth named functions and function expressions may be referenced:\n\n```tolk\nfun customRead(reader: (slice) -> int) {\n    // ...\n}\n\nfun demo() {\n    customRead(fun(s) {\n        return s.loadUint(32)\n    })\n}\n```\n"
  },
  {
    "path": "languages/tolk/syntax/imports.mdx",
    "content": "---\ntitle: \"Imports and name resolution\"\nsidebarTitle: \"Imports\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nIn practice, contract code is split across multiple files. Projects with multiple contracts share a single codebase, including messages, storage layouts, and related logic. Symbols defined in one file can be used in another by importing that file. After an import, all its public symbols are available to the importing file.\n\n## Importing files\n\nError codes are commonly placed in a separate file, for example `errors.tolk`:\n\n```tolk\nconst ERR_ZERO_BALANCE = 123\n// ...\n```\n\nTo use these constants in `parse.tolk`, the file must be imported explicitly:\n\n```tolk\nimport \"errors\"\n\nfun validate(balance: coins) {\n    assert (balance > 0) throw ERR_ZERO_BALANCE;\n}\n```\n\n<Aside type=\"tip\">\n  When selecting items from auto-completion, [IDE](/contract-dev/ide/overview) inserts imports automatically. This works in both JetBrains-based and VSCode-based IDEs.\n</Aside>\n\n## Name uniqueness\n\nAll top-level symbols must have unique names.\n\n- There is no `export const ...` or `export fun ...` declarations needed.\n- All constants, functions, and other top-level declarations are visible by default.\n- No module‑private symbols exist.\n\nAs a result, all top-level symbols across imported files must have unique names. Declaring `fun log()` in multiple files causes a duplicate declaration error when both files are imported.\n\nTechniques to avoid name collisions:\n\n1. Use long, descriptive names for top-level symbols, especially in multi‑contract projects.\n   - Good: `ReturnExcessesBack`, `WalletStorage`.\n   - Bad: `Excesses`, `Storage`.\n1. Group integer constants to enums.\n1. [Prefer methods to global-scope functions](/languages/tolk/idioms-conventions#prefer-methods-to-functions).\n\n## Repeated symbols across contracts\n\nWhen developing multiple contracts, each contract has its own file, compilation target. Contract files do not import one another; therefore, the following declarations do not conflict across different contracts:\n\n- `onInternalMessage` and `onExternalMessage`;\n- `get fun`;\n- other contract entrypoints.\n\n```tolk\n// file: a-contract.tolk\nimport \"storage\"\nimport \"errors\"\n\nfun onInternalMessage(in: InMessage) {\n    // ...\n}\n\nget fun name() {\n    return \"a\"\n}\n```\n\n```tolk\n// file: b-contract.tolk\nimport \"storage\"\nimport \"errors\"\n\nfun onInternalMessage(in: InMessage) {\n    // ...\n}\n\nget fun name() {\n    return \"b\"\n}\n```\n\nGet methods conceptually belong to the scope of a specific contract.\n\nIn a multi-contract project, each contract file typically contains only:\n\n- its entrypoints,\n- optionally, a union of allowed messages,\n- and contract-specific logic.\n\nThe remaining codebase is shared.\n\nFor instance, a struct `SomeMessage` outgoing for one contract and incoming for another. When one contract deploys another, both must share the storage struct.\n\nAs a guideline, group messages, errors, utils, etc. in shared files, and use only minimal declarations inside each `contract.tolk`.\n"
  },
  {
    "path": "languages/tolk/syntax/mutability.mdx",
    "content": "---\ntitle: \"Mutability\"\n---\n\nTolk follows [value semantics](https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_value): function arguments are copied by value. There are no pointers or object references.\n\nThe `mutate` keyword, used both at declaration and invocation, allows a function to modify the argument.\n\n## Value semantics\n\nFunction arguments are copied by value: calls do not modify the original data.\n\n```tolk\nfun someFn(x: int) {\n    x += 1;\n}\n\nfun demo() {\n    var origX = 0;\n    someFn(origX);  // origX remains 0\n}\n```\n\nThis also applies to slices, cells, and other types:\n\n```tolk\nfun readFlags(cs: slice) {\n    return cs.loadInt(32);\n}\n\nfun onInternalMessage(in: InMessage) {\n    var flags = readFlags(in.body);  // body is NOT modified\n    // `in.body.loadInt(32)` reads the same flags\n}\n```\n\n## `mutate` parameter\n\nThe `mutate` keyword makes a parameter mutable. To prevent unintended modifications, `mutate` must also be specified at the call site.\n\n```tolk\nfun increment(mutate x: int) {\n    x += 1;\n}\n\nfun demo() {\n    // correct:\n    var origX = 0;\n    increment(mutate origX);  // origX becomes 1\n\n    // these are compiler errors\n    increment(origX);         // error, unexpected mutation\n    increment(10);            // error, not lvalue\n}\n```\n\nThis also applies to slices and other types:\n\n```tolk\nfun readFlags(mutate cs: slice) {\n    return cs.loadInt(32);\n}\n\nfun onInternalMessage(in: InMessage) {\n    var flags = readFlags(mutate in.body);\n    // `in.body.loadInt(32)` reads the next integer\n}\n```\n\nA function can define multiple `mutate` parameters:\n\n```tolk\nfun incrementXY(mutate x: int, mutate y: int, delta: int) {\n    x += delta;\n    y += delta;\n}\n\nfun demo() {\n    var (a, b) = (5, 8);\n    incrementXY(mutate a, mutate b, 10);   // a = 15, b = 18\n}\n```\n\nThis behavior is similar to passing by reference, but since `ref` is already used in TON for cells and slices, the keyword `mutate` is chosen.\n\n## `self` in methods\n\nInstance methods are declared as `fun <receiver>.f(self)`. By default, `self` is immutable:\n\n```tolk\nfun slice.readFlags(self) {\n    return self.loadInt(32);  // error, a mutating method\n}\n\nfun slice.preloadFlags(self) {\n    return self.preloadInt(32);  // ok, a read-only method\n}\n```\n\n## `mutate self`\n\n`mutate self` allows modifying the receiver:\n\n```tolk\nfun slice.readFlags(mutate self) {\n    return self.loadInt(32);\n}\n```\n\nThus, when calling `someSlice.readFlags()`, the object is mutated.\n\nMethods for [structures](/languages/tolk/types/structures) are declared in the same way:\n\n```tolk\nstruct Point {\n    x: int\n    y: int\n}\n\nfun Point.reset(mutate self) {\n    self.x = self.y = 0\n}\n```\n\nA mutating method can modify another variable:\n\n```tolk\nfun Point.resetAndRemember(mutate self, mutate sum: int) {\n    sum = self.x + self.y;\n    self.reset();\n}\n\nfun demo() {\n    var (p, sumBefore) = (Point { x: 10, y: 20 }, 0);\n    p.resetAndRemember(mutate sumBefore);\n    return (p, sumBefore);      // { 0, 0 } and 30\n}\n```\n\n## How does `mutate` work?\n\nTolk code is executed by [TVM](/tvm/overview) – a stack-based virtual machine. Mutations work by implicitly returning new values through the stack.\n\n```tolk\n// transformed to: \"returns (int, void)\"\nfun increment(mutate x: int): void {\n    x += 1;\n    // a hidden \"return x\" is inserted\n}\n\nfun demo() {\n    var x = 5;\n    // transformed to: (newX, _) = increment(x); x = newX\n    increment(mutate x);\n}\n```\n\nMutating methods work the same:\n\n```tolk\n// transformed to: (newS, flags) = loadInt(s, 32); s = newS\nflags = s.loadInt(32);\n```\n\n## `T.fromSlice(s)` does not modify `s`\n\n[Auto-serialization](/languages/tolk/features/auto-serialization) with `fromSlice` follows the same mutability rules. Passing an argument without `mutate` never modifies the original variable.\n\nIn a call `f(anyVariable)`, the variable remains unchanged. If a function needs to modify its argument, the call must explicitly use `mutate`: `f(mutate anyVariable)`.\n\nThe same rule applies to `AnyStruct.fromSlice(s)`. The slice is not mutated, and its internal pointer is not shifted. So, calling `s.assertEnd()` does not check \"nothing is left after loading `AnyStruct`\".\n\n```tolk\nstruct Point {\n    x: int8\n    y: int8\n}\n\nfun demo(s: slice) {\n    // want to check that \"0102\" is ok, \"0102FF\" is wrong\n    // but this is NOT correct\n    var p = Point.fromSlice(s);\n    s.assertEnd(); // because s is not mutated\n}\n```\n\nTo check that a slice does not contain excess data, no special actions are required, because `fromCell` and `fromSlice` automatically ensure the slice ends after reading. For input `0102FF`, an exception 9 is thrown. This behavior can be turned off with an option:\n\n```tolk\nPoint.fromSlice(s, {\n    assertEndAfterReading: false    // true by default\n})\n```\n"
  },
  {
    "path": "languages/tolk/syntax/operators.mdx",
    "content": "---\ntitle: \"Operators\"\n---\n\nTolk provides standard operators for integers and booleans.\n\n## Operator priority\n\nFrom highest to lowest.\n\n### Parenthesis `(` `)`\n\nGroups expressions: `(1 + 2) * 3`; or creates [tensors](/languages/tolk/types/tensors): `pair = (1, 2)`.\n\n### Square brackets `[` `]`\n\nCreates typed [tuples](/languages/tolk/types/tuples): `[1, 2]`.\n\n### Operator `lazy`\n\nWith [lazy loading](/languages/tolk/features/lazy-loading) the compiler loads only the accessed fields and skips the rest.\n\n### Non-null assertion operator `!`\n\nSkips the [nullability](/languages/tolk/types/nullable) check: `someVar!`.\n\n### Unary operators `!` `~` `-` `+`\n\n[Logical negation](/languages/tolk/types/booleans) `!x`, bitwise not `~x`, unary `-x` and `+x`.\n\n### Operators `as` `is` `!is`\n\n[Unsafe `as` cast](/languages/tolk/types/type-checks-and-casts) and checks for [union types](/languages/tolk/types/unions): `someVar is int`.\n\n### Multiplicative `*` `/` `%` `^/` `~/`\n\nInteger multiplication, division, modulo, ceiling-division, and rounding-division. All [integers](/languages/tolk/types/numbers) have 257-bit precision.\n\n### Additive `+` `-`\n\nStandard integer addition and subtraction.\n\n### Shifts `<<` `>>` `^>>` `~>>`\n\nBitwise shifts, extended by ceiling-right and rounding-right.\n\n### Comparison `==` `<` `>` `<=` `>=` `!=` `<=>`\n\nComparison operators. `<=>` is known as the spaceship or sign operator. Operators `==` and `!=` also work for several non-numeric types. For example, [addresses](/languages/tolk/types/address).\n\n### Bitwise `&` `|` `^`\n\nStandard bitwise operators, applicable to both integers and booleans.\n\n### Logical `&&` `||`\n\n[Short-circuit](/languages/tolk/types/booleans#logical-vs-bitwise-operators): the right operand is evaluated only when necessary.\n\n### Assignment `=` `+=` `-=` and other\n\nAssignment and augmented assignments.\n\n### Ternary `... ? ... : ...`\n\nTernary expressions are available in [conditions](/languages/tolk/syntax/conditions-loops).\n\n## Missing operators\n\nTolk does not support `i++` and `i--`. Use `i += 1` and `i -= 1` instead.\n\n## Warnings on unexpected precedence\n\nA common pitfall:\n\n```tolk\nif (flags & 0xFF != 0) {\n    // ...\n}\n```\n\nThis does not check the lowest byte. It is parsed as `flags & (0xFF != 0)`, because `!= ` has higher precedence, as in C++.\n\nTo prevent such cases, the compiler reports an error:\n\n```ansi\nerror: & has lower precedence than !=, probably this code won't work as you expected.\n       Use parenthesis: either (... & ...) to evaluate it first, or (... != ...) to suppress this error.\n\n   2 |     if (flags & 0xFF != 0) {\n     |         ^^^^^^^^^^^^^^^^^\n```\n"
  },
  {
    "path": "languages/tolk/syntax/pattern-matching.mdx",
    "content": "---\ntitle: \"Pattern matching\"\n---\n\nTolk supports a `match` expression for pattern matching. It works both on types and on expressions.\n\n## `match` for union types\n\nPattern matching on union types is used in [message handling](/languages/tolk/features/message-handling).\n\n```tolk\ntype IncomingMessage =\n    | CounterIncBy\n    | CounterReset\n    // ...\n\n// ... after parsing a message\nmatch (msg) {\n    CounterIncBy => {\n        newCounter = curCounter + msg.byValue\n    }\n    CounterReset => {\n        newCounter = 0\n    }\n    // ...\n}\n```\n\nThis is a general mechanism compatible with any union type:\n\n```tolk\nfun processValue(value: int | slice) {\n    match (value) {\n        int => {\n            value * 2\n        }\n        slice => {\n            value.loadUint(8)\n        }\n    }\n}\n```\n\nA `match` on a union must be exhaustive: all alternatives must be covered.\n\n```tolk\nfun errDemo(v: int | slice | Point) {\n    match (v) {\n        slice => { v.loadAddress() }\n        int => { v * 2 }\n        // error: missing `Point`\n    }\n}\n```\n\n`else` is not allowed for unions, but is permitted for a [`lazy` match](/languages/tolk/features/lazy-loading#lazy-matching).\n\n## Syntax details\n\n- After `=>`, one of the following is allowed:\n  - a block: `A => { ... }`;\n  - an expression: `A => 123`;\n  - a return statement: `A => return SOME_EXPR`;\n  - a throw statement: `A => throw ERR_CODE`.\n\n- A comma is:\n  - optional after a block: `A => { ... } B => { ... }`;\n  - required in all other cases: `A => 1, B => 2`.\n\n- A `match` can be used as an expression: `return match (v) { ... }`.\n\n- Variable declarations are allowed inside: `match (val v = ...)`.\n\n## `match` as expression\n\n`match` can be used in expression position. In this form, it can be:\n\n- assigned to a variable: `var smth = match (v) { ... }`;\n- returned from a function: `return match (v) { ... }`.\n\n```tolk\ntype Pair2 = (int, int)\ntype Pair3 = (int, int, int)\n\nfun getLast(tensor: Pair2 | Pair3) {\n    return match (tensor) {\n        Pair2 => tensor.1,\n        Pair3 => tensor.2,\n    }\n}\n```\n\n## Variables declaration\n\nA variable may be declared directly in the `match` expression.\n\n```tolk\nfun getPair2Or3(): Pair2 | Pair3 {\n    // ...\n}\n\nfun demo() {\n    match (val v = getPair2Or3()) {\n        Pair2 => return v.0 + v.1,\n        Pair3 => throw v.0 + v.1 + v.2,\n    }\n}\n```\n\n## `match` for expressions\n\n`match` can be used with constant expressions, similar to `switch`:\n\n```tolk\nval nextValue = match (curValue) {\n    1 => 0,\n    0 => 1,\n    else => -1\n};\n```\n\nRules:\n\n- Only constant expressions are allowed before `=>`.\n- `else` is required when `match` is used as an expression.\n- `else` is optional when `match` is used as a statement.\n\n```tolk\n// statement form\nmatch (curValue) {\n    1 => { nextValue = 0 }\n    0 => { nextValue = 1 }\n    -1 => throw NEGATIVE_NOT_ALLOWED\n}\n\n// expression form, `else` required\nval nextValue = match (curValue) {\n    // ...\n    else => 1 + 2\n}\n```\n\nAll comparable types are supported, including addresses and enums.\n\n## `match` for enums\n\nPattern matching on [enums](/languages/tolk/types/enums) requires exhaustive coverage of all cases:\n\n```tolk\nmatch (someColor) {\n    Color.Red => {}\n    Color.Green => {}\n    // error: Color.Blue is missing\n}\n```\n\nAlternatively, use `else` to handle the remaining values:\n\n```tolk\nmatch (someColor) {\n    Color.Red => {}\n    else => {}\n}\n```\n"
  },
  {
    "path": "languages/tolk/syntax/structures-fields.mdx",
    "content": "---\ntitle: \"Structures and fields\"\n---\n\nTolk supports [structures](/languages/tolk/types/structures) — similar to TypeScript classes.\n\n## Structure syntax\n\n```tolk\nstruct Demo {\n    allowExotic: bool = false\n    customData: tuple\n}\n```\n\n- Every field has a required type and an optional default value.\n- Fields are separated by newlines, which are preferred, or by commas or semicolons.\n- Fields can be `private` and `readonly`.\n\n## Object creation\n\nUse `{ ... }` when the type is clear, or `StructName { ... }` explicitly.\n\n```tolk\nfun demo() {\n    // the type is clear from the assignment\n    var o1: Demo = { customData: someTuple };\n    o1.someMethod();\n\n    // alternatively, `Demo { ... }`\n    Demo{customData: someTuple}.someMethod();\n}\n```\n\n## Shorthand object syntax\n\nThe shorthand `{ a, b }` expands to `{ a: a, b: b }`. This syntax is similar to object shorthand in TypeScript.\n\n```tolk\nfun createDemo(allowExotic: bool, customData: tuple) {\n    return Demo { allowExotic, customData }\n}\n```\n\n## Methods for structures\n\n[Methods](/languages/tolk/syntax/functions-methods) are declared separately as extension functions:\n\n```tolk\nfun Demo.hasData(self): bool {\n    return self.customData.size() != 0\n}\n```\n\n## Empty structures\n\nA structure without fields is used as a grouping construct for static methods. For example, standard functions such as `blockchain.now()` are declared this way:\n\n```tolk\nstruct blockchain\n\nfun blockchain.now(): int\n    asm \"NOW\"\n\nfun blockchain.logicalTime(): int\n    asm \"LTIME\"\n```\n\nThese methods are static because they do not accept `self`.\n\n## Default values for fields\n\nFields with default values may be missed out of a literal:\n\n```tolk\nstruct DefDemo {\n    f1: int = 0\n    f2: int? = null\n    f3: (int, coins) = (0, ton(\"0.05\"))\n}\n\nfun demo() {\n    var d: DefDemo = {};         // ok\n    var d: DefDemo = { f2: 5 };  // ok\n}\n```\n\n## Private and readonly fields\n\n- `private` – accessible only within methods.\n- `readonly` – immutable after object creation.\n\n```tolk\nstruct PositionInTuple {\n    private readonly t: tuple\n    currentIndex: int\n}\n\nfun PositionInTuple.create(t: tuple): PositionInTuple {\n    return { t, currentIndex: 0 }\n}\n\nfun PositionInTuple.next(mutate self) {\n    // self.t cannot be modified: it is readonly\n    self.currentIndex += 1;\n}\n\nfun demo() {\n    var p = PositionInTuple.create(someTuple);\n    // p.t is unavailable here: it is private\n}\n```\n\nAn object with a private field can only be constructed by a static method or an assembler function.\n\n## Generic structs\n\n[Generics](/languages/tolk/types/generics) exist only at the type level and incur no runtime cost.\n\n```tolk\nstruct Nullable<T> {\n    value: T?\n}\n```\n\n## Methods for generic structs\n\nWhen parsing the receiver in `fun <receiver>.f()`, the compiler treats unknown symbols as type parameters:\n\n```tolk\nfun Nullable<T>.isNull(self) {\n    return self.value == null\n}\n```\n\nIt's a generalization. For example, `fun T.copy()` is valid for any receiver.\n\nMethod overloading or partial specialization is also allowed:\n\n```tolk\nfun Nullable<map<K, V>>.isNull(self) {\n    return self.value.isEmpty()\n}\n```\n\n## Serialization prefixes and opcodes\n\nThe syntax `struct (PREFIX) Name { ... }` specifies a [serialization prefix for the structure](/languages/tolk/types/overall-serialization#structures). For messages, 32-bit prefixes are typically called opcodes.\n\n```tolk\nstruct (0x7362d09c) TransferNotification {\n    queryId: uint64\n    // ...\n}\n```\n\nAn outgoing message starts with the hex number:\n\n```tolk\n// message will be '0x7362d09c0000000000000000' + ...\ncreateMessage({\n    // ...\n    body: TransferNotification {\n        queryId: 0,\n        // ...\n    }\n});\n```\n\nPrefixes are not restricted to 32 bits:\n\n- `0x000F` — 16-bit hexadecimal prefix, value 15.\n- `0b010` — 3-bit binary prefix, value 2.\n\nNon‑32‑bit prefixes are useful for controlling union types when expressing TL‑B's multiple constructors.\n"
  },
  {
    "path": "languages/tolk/syntax/variables.mdx",
    "content": "---\ntitle: \"Variables\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n- Use `val` for immutable variables and `var` for mutable variables.\n- Use `const` or `global` outside functions.\n\n## Declaration\n\n- `val` declares a variable that is assigned exactly once:\n\n  ```tolk\n  fun demo() {\n      val coeff = 5;\n      // cannot change its value, `coeff += 1` is an error\n  }\n  ```\n\n- `var` declares a variable that can be reassigned:\n\n  ```tolk\n  fun demo() {\n      var x = 5;\n      x += 1;      // now 6\n  }\n  ```\n\n### Explicit types\n\nA variable may declare its type explicitly. If the type is not specified, it is inferred from the initial assignment:\n\n```tolk\nfun demo() {\n    var x = 5;         // inferred `int`\n    x = null;          // error, cannot assign\n\n    var y: int? = 5;   // specified nullable\n    y = null;          // ok\n}\n```\n\nExplicit types also can be used with structures:\n\n```tolk\nfun demo() {\n    var p1: Point = { x: 10, y: 20 };\n\n    // without an explicit type, use `Point { ... }`\n    var p2 = Point { x: 10, y: 20 };\n}\n```\n\n### Unassigned variables\n\nA variable may be declared without an initial value, but it must be assigned before its first use:\n\n```tolk\nfun demo(mode: int) {\n    var result: int;  // not assigned at declaration\n\n    if (mode == MODE_SLOW) {\n        result = doSlowCalc();\n    } else if (mode == MODE_FAST) {\n        result = doFastCalc();\n    } else {\n        throw ERR_INVALID_MODE;\n    }\n    return result;   // ok, it's definitely assigned\n}\n```\n\n### Multiple variables\n\nDeclaring multiple variables at once is tensor destructuring:\n\n```tolk\nfun demo() {\n    var (a, b) = (1, \"\");\n\n    // with explicit types\n    var (c: int, d: slice) = (1, \"\");\n}\n```\n\n### Nested scope\n\nA block `{ ... }` introduces a nested scope:\n\n```tolk\nfun demo() {\n    val x = 10;\n    if (smth) {\n        val x = 50;  // this is a different `x`\n    }\n    // x is 10\n}\n```\n\n## Function parameters\n\nFunction parameters behave the same as local variables. They can be reassigned, but the reassignment does not affect the caller's state:\n\n```tolk\nfun analyze(userId: int?) {\n    if (userId == null) {\n        userId = DEFAULT_ID;\n    }\n    // ...\n}\n\nfun demo() {\n    var id = null as int?;\n    analyze(id);\n    // id remains `null`\n}\n```\n\nTo make updates to `userId` visible in `demo`, declare the parameter with [`mutate`](/languages/tolk/syntax/mutability#mutate-for-a-parameter): `mutate userId`.\n\n## Constants\n\nGlobal-scope constants are declared with `const` outside functions:\n\n```tolk\nconst SLEEP_TIME_SEC = 5\n```\n\nThe right-hand side must be a constant expression: numbers, const literals, compile-time functions, etc.\n\n```tolk\n// ok\nconst FLAG_JANUARY = 1 << 10\nconst OP_TRANSFER = stringCrc32(\"transfer\")\n\n// error: not a constant expression\nconst CUR_TIME = blockchain.now()\n```\n\nThe type is inferred unless explicitly specified:\n\n```tolk\nconst MODE_NORMAL: uint32 = 0\n```\n\nConstants are not limited to integers:\n\n```tolk\n// type `address`\nconst ADMIN_ADDR = address(\"UQ...\")\n\n// type `coins`\nconst MINIMAL_COST = ton(\"0.05\")\n\n// even objects with constant fields\nconst ZERO_POINT: Point = { x: 0, y: 0 }\n```\n\nTo calculate CRC32 and similar values at compile time, use [`stringCrc32(\"...\")`](/languages/tolk/types/strings#calculate-hex-%2F-crc32-%2F-etc-at-compile-time) and similar.\n\nTo group integer constants, use [enums](/languages/tolk/types/enums).\n\n## Global variables\n\nUse the `global` keyword to declare variables outside functions:\n\n```tolk\nglobal runtimeCalls: tuple\n```\n\nA `global` must have an explicit type and cannot be initialized at the point of declaration. Initialization is done manually at some point in a program. A contract has several entry points, such as `get fun`, `onInternalMessage`, and others.\n\nA `global` must be initialized along the execution path where it is required.\n\n```tolk\nglobal runtimeCalls: tuple\n\nfun execute() {\n    runtimeCalls.push(\"start execute\");\n    // ...\n}\n\nget fun devTrace() {\n    runtimeCalls = createEmptyTuple();   // initialize\n    val result = execute();\n    return (result, runtimeCalls);\n}\n```\n\nIn Tolk, avoid globals when possible. Use [auto-serialization](/languages/tolk/features/auto-serialization) and [`lazy` loading](/languages/tolk/features/lazy-loading).\n\n<Aside\n  type=\"caution\"\n>\n  Use globals with care. Until initialized, a global holds TVM `NULL`, and any invalid access leads to a runtime failure.\n</Aside>\n"
  },
  {
    "path": "languages/tolk/types/address.mdx",
    "content": "---\ntitle: \"Address\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nEvery smart contract has an [address](/foundations/addresses/overview) used for all on-chain interactions.\n\nTolk provides the following types for working with addresses:\n\n- `address` — a standard address; also called \"internal address\".\n- `address?` — nullable address, i.e., either a standard address or `null`; also called \"internal or none\".\n- `any_address` — any kind of address, including external addresses.\n\n## Components\n\nA standard, internal `address` consists of:\n\n- a `int8` workchain — currently, there are only two: masterchain (-1) and basechain (0);\n- a `uint256` hash — a 256-bit account ID.\n\n`address` has methods to retrieve these components:\n\n```tolk\nfun checkAddress(addr: address, expectHash: uint256) {\n    val (wc, hash) = addr.getWorkchainAndHash();\n    assert (wc == 0) throw 123;\n    assert (hash == expectHash) throw 456;\n}\n```\n\nWhen [serialized](/languages/tolk/types/overall-serialization), values of `address` type occupy 267 bits:\n\n- 3 bits for the standard address prefix — `0b100`\n- 8-bit workchain\n- 256-bit hash\n\nDuring deserialization from a cell, the values of type `address` are automatically validated at runtime: if parsing succeeds, the resulting address is guaranteed to be valid.\n\n## Comparison\n\nCompare addresses using `==` or `!=`. Internally, an [address is represented as a raw `slice` without references](/languages/tolk/types/overall-tvm-stack), so `==` and `!=` test for bits equality.\n\n```tolk\nstruct Storage {\n    owner: address\n    // ...\n}\n\nfun onInternalMessage(in: InMessage) {\n    var st = Storage.load();\n    // process a message only from owner\n    if (in.senderAddress == st.owner) {\n        // ...\n    }\n}\n```\n\n## Embedding\n\nEmbed a constant value of type `address` using the `address()` function:\n\n```tolk\nconst REFUND_ADDR = address(\"EQCRDM9h4k3UJdOePPuyX40mCgA4vxge5Dc5vjBR8djbEKC5\")\n```\n\n## Nullable address\n\nA nullable address often represents a potentially absent value:\n\n- There might be an `adminAddress` in the contract's storage, but it may be unset.\n- There might be an `sendExcessesTo` field in a message: if exists, send surplus there; if not, keep it.\n\nThus, type `address?` represents a \"none address\": either an internal address or none. Check for `null` before usage:\n\n```tolk\n// May have no admin\nfun send(adminAddress: address?) {\n    if (adminAddress == null) {\n        return;\n    }\n    // send a message to adminAddress, it's not null\n}\n```\n\nWhen a value of type `address?` is serialized and is not `null`, it occupies 267 as the standard `address`. If it is `null`, then it occupies only 2 zero bits, a so-called `addr_none`.\n\nThe \"none\" address can be created using `createAddressNone()`.\n\n## Any address\n\nAll external messages from outside world to blockchain contracts, such as wallet contracts, come from external addresses.\n\nTo represent internal and external addresses, as well as nullable addresses, use `any_address`:\n\n```tolk\nstruct CrossBridgeMessage {\n    destination: any_address\n}\n```\n\n## Casts\n\nTo manually operate on the bits of an `address`, cast it to a `slice`:\n\n```tolk\nval s = someAddr as slice;\ns.loadUint(3);     // 0b100 — internal address tag\ns.loadInt(8);      // workchain\n```\n\nSince an address is represented as a `slice` at the TVM level, such cast is permitted and is safe. Conversely, the cast in another direction is **unsafe**, because no validation is performed at runtime and any further use might fail:\n\n```tolk\nvar b = beginCell()\n       .storeUint(0b01)   // addr_extern\n       ...;\nvar s = b.endCell().beginParse();\nreturn s as any_address;\n```\n"
  },
  {
    "path": "languages/tolk/types/aliases.mdx",
    "content": "---\ntitle: \"Type aliases\"\n---\n\nTolk supports type aliases, similar to TypeScript and Rust. An alias creates a new name for an existing type and remains fully interchangeable with it.\n\n```tolk\ntype UserId = int32\ntype MaybeOwnerHash = bytes32?\n\nfun calcHash(id: UserId): MaybeOwnerHash {\n    // ...\n}\n```\n\n## Alias interchangeability\n\nAliases are interchangeable with underlying types. `UserId` and `int32` from the above example are fully equivalent:\n\n- `id + 1` is valid and produces `int`;\n- `someF(id)` is valid if `someF` accepts `int32` or `int`;\n- methods for `int32` can be called on `UserId` values and vice versa; and also for `int`, since `int32` is assignable to `int`;\n- a union `UserId | int32` is redundant and is equivalent to `int32`.\n\n```tolk\nfun demo() {\n    var id: UserId = 1;       // ok\n    var num: int = id;        // ok\n    var h = calcHash(id);\n    if (h != null) {\n        h as slice;           // bytes32 as slice\n    }\n}\n```\n\nTo obtain a “strict alias”, which defines a distinct type, use a struct with one field:\n\n```tolk\nstruct UniqueId {\n    value: int32\n}\n```\n\nSuch a struct has no overhead over `int32`, but it becomes a distinct type with its own methods and semantics.\n\n## Distinct alias types\n\nTwo aliases with the same underlying type are considered distinct. If two aliases share the same underlying type:\n\n```tolk\ntype AssetsDict = dict\ntype BalanceDict = dict\n```\n\nThen, they are not assignable to each other. This allows them to define methods with identical names:\n\n```tolk\nfun AssetsDict.validate(self) { /* ... */ }\nfun BalanceDict.validate(self) { /* ... */ }\n\nfun demo(a: AssetsDict, b: BalanceDict) {\n    a.validate();      // ok, method 1\n    b.validate();      // ok, method 2\n    a = b;             // error, can not assign\n}\n```\n\nThis behavior is similar to `intN` types: `int32` is assignable to `int`, and `int64` is assignable to `int`, but `int32` and `int64` are not assignable to each other. Assignment can be done with an explicit [cast](/languages/tolk/types/type-checks-and-casts). For example, `b as AssetsDict`.\n\n## Generic type aliases\n\nType aliases can be [generic](/languages/tolk/types/generics).\n\n```tolk\ntype Wrapper<T> = Nothing | Container<T>\n```\n\n## Stack layout and serialization\n\nA type alias is identical to its underlying type in [stack layout](/languages/tolk/types/overall-tvm-stack) and [serialization](/languages/tolk/types/overall-serialization).\n\nSerialization behavior can be overloaded by defining custom serializers. This is useful when binary encoding cannot be expressed using existing types.\n\n```tolk\ntype MyString = slice\n\nfun MyString.packToBuilder(self, mutate b: builder) {\n    // custom logic\n}\n\nfun MyString.unpackFromSlice(mutate s: slice) {\n    // custom logic\n}\n```\n"
  },
  {
    "path": "languages/tolk/types/booleans.mdx",
    "content": "---\ntitle: \"Booleans\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nTolk has a `bool` type with two values: `true` or `false`.\n\nTVM does not have booleans as a separate type. Instead, `true` is represented as the bit 1 and `false` as the bit 0. In the context of TVM's signed 257-bit integers, this means that `true` corresponds to a decimal -1, while `false` corresponds to 0.\n\n```tolk\nfun isGreater10(v: int): bool {\n    return v > 10\n}\n```\n\nSeveral operators, such as `==` or `&&` produce values of type `bool`. Many standard library functions also return `bool` values:\n\n```tolk\nvar valid = isSignatureValid(...);    // bool\nvar end = someSlice.isEmpty();        // bool\n```\n\n## Logical operators accept both `int` and `bool`\n\n- Operator `!x` supports both `bool` and `int`.\n- The condition of `if` and similar statements accepts both `bool` and `int`, where it treats the latter as `true` if the value is not equal to 0, and as `false` otherwise.\n- Logical operators `&&` and `||` accept both `bool` and `int`. For example, `a && b` evaluates to `true` when both operands are `true` or both operands are non-zero integers.\n\nArithmetic operators are restricted to integers.\n\n```tolk\nvalid && end;  // ok\nvalid & end;   // ok, bitwise & | ^ also work if both are bools\nif (!end)      // ok\n\nvalid + end;   // error\n8 & valid;     // error, int & bool not allowed\n```\n\n## Logical and bitwise operators\n\nTolk has both bitwise `& ^ |` and logical `&& ||` operators that can be used for booleans and integers.\n\nThe main difference is that logical operators short-circuit: the right operand is evaluated only if required.\n\n|      Expression      |                    Behavior                    |\n| :------------------: | :--------------------------------------------: |\n|   `condition & f()`  |             `f()` is called always             |\n|  `condition && f()`  |  `f()` is called only if `condition` is `true` |\n|  `condition \\| f()`  |             `f()` is called always             |\n| `condition \\|\\| f()` | `f()` is called only if `condition` is `false` |\n\nThe compiler performs better instruction optimizations on booleans, saving more gas per comparison.\n\nBitwise operators may sometimes be used instead of logical operators to avoid generating conditional branches at runtime. For example, `(a > 0) && (a < 10)`, when replaced with bitwise `&`, consumes less gas.\n\n## Casting to an integer\n\nUse the `as` operator to cast the `bool` to `int`. No runtime transformations take place: at the TVM level, the `bool` type is represented as an integer with a decimal value of either -1 or 0.\n\n```tolk\n// -1 or 0 in decimal; serialized as a single bit 1 or 0\nvar i = boolValue as int1;\n```\n\n## Serialization\n\nA boolean is [serialized](/languages/tolk/types/overall-serialization) as a single bit: 1 for `true` and 0 for `false`.\n"
  },
  {
    "path": "languages/tolk/types/callables.mdx",
    "content": "---\ntitle: \"Callables\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nTolk supports first-class functions. Function values have callable types of the form `(...ArgsT) -> ReturnT`.\n\n## First-class functions\n\nPass a function as a callback:\n\n```tolk\nfun invokeMath(fn: (int, int) -> int) {\n    return fn(10, 20);\n}\n\nfun myPlus(a: int, b: int) {\n    return a + b;\n}\n\nfun demo() {\n    invokeMath(myPlus);   // 30\n}\n```\n\nA function `myPlus` has the type `(int, int) -> int`. A function `demo`, for example, has the type `() -> void`.\n\nFunctions can be assigned to variables:\n\n```tolk\nfun demo() {\n    val callback = myPlus;\n    callback(5, 5);   // 10\n\n    // or, with explicit type:\n    val fn: (int, int) -> int = myPlus;\n}\n```\n\n<Aside\n  type=\"caution\"\n>\n  Functions with `mutate` parameters cannot be assigned to variables or passed around. Mutation is not part of the type system.\n</Aside>\n\n## Lambda functions\n\nTolk supports [lambda functions](/languages/tolk/syntax/functions-methods):\n\n```tolk\nfun demo() {\n    invokeMath(fun(a, b) {\n        return a * b\n    });    // 200\n}\n```\n\nLambda parameter types may be omitted when they can be inferred. In the example above, both `a` and `b` are inferred as `int` from the `invokeMath` declaration. When parameter types cannot be inferred, they must be specified:\n\n```tolk\n// error: param's type cannot be inferred here:\nval doubleFn = fun(param) { return param * 2 };\n\n// correct is:\nval doubleFn = fun(param: int) { return param * 2 };\n```\n\nAs first-class functions, lambdas can also be returned:\n\n```tolk\nfun createFinalizer() {\n    return fun(b: builder) {\n        b.storeUint(0xFFFFFFFF, 32);\n        return b.toSlice();\n    }\n}\n\nfun demo() {\n    val f = createFinalizer();    // (builder) -> slice\n    f(beginCell());               // slice with 32 bits\n}\n```\n\nLambdas are primarily used in general-purpose tooling. They can be combined with generic types and used as nested expressions without restrictions.\n\n```tolk\nstruct HasCallback<TResult> {\n    arg: int\n    fn: (int -> TResult)?\n}\n\nfun HasCallback<TResult>.invoke(self): TResult {\n    assert (self.fn != null) throw ERR_CALLBACK_UNSET;\n    return self.fn(self.arg)\n}\n```\n\nLambdas are not closures. Capturing variables from an outer scope is not supported:\n\n```tolk\nfun outer(x: int) {\n    return fun(y: int) {\n        return x + y;    // error: undefined symbol `x`\n    }\n}\n```\n\n## Low-level TVM continuations\n\nContinuations are executable cells representing TVM bitcode. A callable is a typed `continuation`.\n\nTolk provides the low-level type `continuation`. For example, the TVM register [`c3`](/tvm/registers) contains the smart contract code. Some functions are available in the standard library:\n\n```tolk\nimport \"@stdlib/tvm-lowlevel\"\n```\n\n## Stack layout and serialization\n\nA callable is backed by the [TVM `CONT`](/languages/tolk/types/overall-tvm-stack). Callable values cannot be [serialized](/languages/tolk/types/overall-serialization).\n"
  },
  {
    "path": "languages/tolk/types/cells.mdx",
    "content": "---\ntitle: \"Cells, slices, builders\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nIn TON, all data is stored in and represented as _cells_.\n\nTolk provides low-level functions for constructing and parsing cells manually, as well as [automatic serialization](/languages/tolk/features/auto-serialization) of structures to and from cells.\n\n## Cells\n\n[Cells](/foundations/serialization/cells) are a data structure that can hold up to 1023 bits of data and up to 4 references to other cells. They are read-only and immutable once created.\n\n### Untyped cells\n\nThe basic type `cell` describes an untyped cell:\n\n```tolk\nstruct SomeMessage {\n    // ...\n    customPayload: cell\n}\n```\n\n### Typed cells\n\n`Cell<T>` represents a cell with known internal structure. Since a single cell stores at most 1023 bits, larger data is split across multiple cells that sequentially reference each other. Circular references are not allowed.\n\n```tolk\nstruct Demo {\n    ref1: cell //          untyped reference\n    ref2: Cell<Inner> //   typed ref\n    ref3: Cell<int256>? // maybe ref\n}\n```\n\nThe `toCell()` method on struct instances produces values of type `Cell<STRUCT_NAME>`. However, any typed cell can be assigned to an untyped `cell` directly.\n\n## Slices\n\nA cell opened for reading is called a _slice_. They allow loading data from cells.\n\nTo read data from a cell manually, call `beginParse()` to get a slice:\n\n```tolk\nvar s = cell.beginParse();\n```\n\nThen load data incrementally: integers, coins, sub-slices, references, etc.\n\n```tolk\nval mode = s.loadUint(8);\nval dest = s.loadAddress();\nval firstRef = s.loadRef();   // cell\n\nif (s.remainingBitsCount()) {\n   // ...\n}\n```\n\n### Prefer distinct slice types\n\nBuilders and slices are low-level primitives for constructing and parsing cells. The values of `builder` and `slice` types contain raw binary data.\n\nAs such, reading an arbitrary `slice` or `builder` from another `slice` is impossible:\n\n```tolk\nstruct CantBeRead {\n    before: int8\n    s: slice\n    after: int8\n}\n```\n\nAn attempt to call `CantBeRead.fromCell(c)` fires an error: \"Can not be deserialized, because `CantBeRead.s` is `slice`\".\n\nExpress the shape of data using the type system and fixed-size slices to make serialization distinct. For example, use `s: bits100` to hold a slice containing at most 100 bits.\n\n### Fixed-size slices\n\nThe `slice` type cannot be serialized, but the `bitsN` types, such as `bits32` or `bytes8`, can. At runtime, `bitsN` is a regular slice, just how `int32` are regular TVM integers.\n\n```tolk\nstruct OkayToRead {\n    before: int8\n    s: bits100\n    after: int8\n}\n\nfun read(c: cell) {\n    // a cell `c` is expected to be 116 bits\n    val r = OkayToRead.fromCell(c);\n    // on the stack: INT, SLICE, INT\n}\n```\n\nTo cast `slice` to `bitsN`, use the unsafe `as` operator. This is intentional: slices may have refs, so explicit casting forces consideration of whether the transformation is valid.\n\nAt runtime, this is a no-op:\n\n```tolk\nfun calcHash(raw: bits512) {\n    // ...\n}\n\nfun demo() {\n    calcHash(someSlice);                   // error\n    calcHash(someSlice as bits512);        // ok\n\n    someBytes.loadAddress();               // error\n    (someBytes as slice).loadAddress();    // ok\n}\n```\n\n### Embed constant slices into a contract\n\n<Aside type=\"note\">\n  [TVM](/tvm/overview) does not have a dedicated string type: they are emulated using slices.\n</Aside>\n\nA [string](/languages/tolk/types/strings) literal is represented as a slice:\n\n```tolk\n// a slice with 4 bytes: 97,98,99,100 (0x61626364)\nconst SLICE1 = \"abcd\"\n```\n\nUse `stringHexToSlice(\"<HEX_BYTES>\")` to embed hexadecimal binary data:\n\n```tolk\n// a slice with 2 bytes: 16,32 (0x1020)\nconst SLICE2 = stringHexToSlice(\"1020\")\n```\n\n## Builders\n\nA cell under construction is called a _builder_. They allow composing new cells.\n\nTo construct a cell manually, create a builder, write data to it, then finalize:\n\n```tolk\nvar b = beginCell();\nb.storeUint(123, 8);\nb.storeAddress(dest);\nval c = b.endCell();\n```\n\nMethods named `storeXYZ` return `self`, which is a builder, so calls can be chained:\n\n```tolk\nval c = beginCell()\n    .storeUint(123, 8)\n    .storeAddress(dest)\n    .endCell();\n```\n\n### Read from a builder\n\nThe only way to access bits already written to a builder is to convert it into a slice:\n\n```tolk\nvar s = b.asSlice();\n// or (exactly the same)\nvar s = b.endCell().beginParse();\n```\n\nConstructing a cell is generally expensive in terms of gas, but `b.endCell().beginParse()` is optimized and does not create intermediate cells.\n\n## Automatic construction and parsing\n\nStructures are [auto-serializable](/languages/tolk/features/auto-serialization) to and from cells when their fields are well-typed. Prefer using structures over manual work with builders and slices.\n\n### Marshall to and from cells\n\n```tolk\nstruct Something {\n    // ...\n}\n\nfun parseAndModify(c: cell): cell {\n    var smth = Something.fromCell(c)\n    // ...\n    return smth.toCell()\n}\n```\n\nFor `Cell<T>`, call `load()` to get a value of type `T`:\n\n```tolk\nfun parsePoint(c: Cell<Point>) {\n    // same as `Point.fromCell(c)`\n    var p = c.load();\n}\n```\n\nInternally, `fromCell()` calls `beginParse()` and reads data from a slice.\n\n### Marshall to and from builders and slices\n\nA struct can be parsed not only from a cell but also from a slice:\n\n```tolk\nval smth = Something.fromSlice(s);\n```\n\nIn addition to `loadUint()` and similar methods, there is `loadAny<T>()`:\n\n```tolk\nval smth = s.loadAny<Something>();\n// or\nval smth: Something = s.loadAny(); // with T deduced as Something\n```\n\n<Aside type=\"note\">\n  Notice that `T.fromSlice(s)` does not mutate a slice `s`, while `s.loadAny<T>()` does. This is due to how Tolk handles [mutability](/languages/tolk/syntax/mutability): all `s.loadXYZ()` methods mutate a slice, but functions in the form `doSomething(s)` do not.\n</Aside>\n\nSimilarly, `storeAny<T>()` for a builder accepts any serializable value:\n\n```tolk\nbeginCell()\n    .storeAddress(dest)\n    .storeAny(smth)         // T=Something deduced\n    .storeUint(123, 8);\n```\n\nBoth `loadAny<T>()` and `storeAny<T>()` work with arbitrary types, not only with structures:\n\n```tolk\ns.loadAny<int32>();           // same as loadInt(32)\ns.loadAny<(coins, bool?)>();  // read a pair (a tensor)\n\nb.storeAny(someAddress);      // same as storeAddress\nb.storeAny(0xFF as uint8);    // same as storeUint(0xFF, 8)\n```\n\n## Remaining slice when reading\n\nA common pattern is to read a portion of data and then retrieve the remainder. With manual parsing, this happens naturally:\n\n```tolk\nval ownerId = s.loadUint(32);\nval dest = s.loadAddress();\n// `s` contains all bits/refs still unread\nval payload = s;\n```\n\nTo express the same with structures, use the special type `RemainingBitsAndRefs`:\n\n```tolk\nstruct WithPayload {\n    ownerId: uint32\n    dest: address\n    payload: RemainingBitsAndRefs\n}\n```\n\nThen, `obj = WithPayload.fromSlice(s)` is a structure instance where `obj.payload` contains all bits and refs left as a `slice`.\n\nA field with this type must appear last in a struct: no more data exists after reading it.\n\n## Stack layout and serialization\n\nStructure fields of `cell` and `Cell<T>` types which are [serialized](/languages/tolk/types/overall-serialization) as references to corresponding [TVM](/languages/tolk/types/overall-tvm-stack) cells, with nullable types `?` serialized as 0 when the value is `null` and 1, followed by the cell reference otherwise.\n\nThe primitive types `builder` and `slice` cannot be serialized. Use `bitsN` and `RemainingBitsAndRefs` types instead.\n"
  },
  {
    "path": "languages/tolk/types/enums.mdx",
    "content": "---\ntitle: \"Enums\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nTolk supports enums, similar to TypeScript and C++ enums.\n\nIn the [TVM](/tvm/overview), all enums are represented as integers. At the compiler level, an enum is a distinct type.\n\n```tolk\n// will be 0 1 2\nenum Color {\n    Red\n    Green\n    Blue\n}\n```\n\n## Enum members\n\nValues can be specified manually. Otherwise, they are auto-calculated as `+1`.\n\n```tolk\nenum Mode {\n    Foo = 256,\n    Bar,        // implicitly 257\n}\n```\n\n## Enum types\n\nEnums are distinct types, not integers. `Color.Red` has type `Color`, not `int`, although it holds the value `0` at runtime.\n\n```tolk\nfun isRed(c: Color) {\n    return c == Color.Red\n}\n\nfun demo() {\n    isRed(Color.Blue);    // ok\n    isRed(1);             // error, pass `int` to `Color`\n}\n```\n\nSince enums are types, they can be:\n\n- used as variables and parameters,\n- extended with methods,\n- used in struct fields, unions, generics, and other type contexts.\n\n```tolk\nstruct Gradient {\n    from: Color\n    to: Color? = null\n}\n\nfun Color.isRed(self) {\n    return self == Color.Red\n}\n\nvar g: Gradient = { from: Color.Blue };\ng.from.isRed();       // false\nColor.Red.isRed();    // true\n\nmatch (g.to) {\n    null => ...\n    Color => ...\n}\n```\n\n## Exhaustive pattern matching\n\n[`match`](/languages/tolk/syntax/pattern-matching) on enums requires coverage of all cases:\n\n```tolk\nmatch (someColor) {\n    Color.Red => {}\n    Color.Green => {}\n    // error: Color.Blue is missing\n}\n```\n\nAlternatively, use `else` to handle remaining values:\n\n```tolk\nmatch (someColor) {\n    Color.Red => {}\n    else => {}\n}\n```\n\nOperator `==` compares values directly:\n\n```tolk\nif (someColor == Color.Red) {}\nelse {}\n```\n\n## Integer representation\n\nAt the TVM level, every enum is represented as `int`. Casting between the enum and `int` is allowed:\n\n- `Color.Blue as int` evaluates to `2`;\n- `2 as Color` evaluates to `Color.Blue`.\n\n<Aside\n  type=\"caution\"\n>\n  Operator `as` can produce invalid values, for example `100 as Color`. In this case, operator `==` returns `false`, and an exhaustive `match` throws exception [5](/tvm/exit-codes#5%3A-integer-out-of-expected-range).\n</Aside>\n\nDuring deserialization with `fromCell()`, the compiler validates that encoded integers correspond to valid enum values.\n\n## Usage in `throw` and `assert`\n\nEnums are allowed in `throw` and `assert`:\n\n```tolk\nenum Err {\n    InvalidId = 0x100\n    TooHighId\n}\n\nfun validate(id: int) {\n    assert (id < 1000) throw Err.TooHighId;  // excno = 257\n}\n```\n\n## Stack layout and serialization\n\nEvery enum is [backed by TVM](/languages/tolk/types/overall-tvm-stack) `INT` and [serialized](/languages/tolk/types/overall-serialization) as `(u)intN`, where `N` is:\n\n- specified manually, for example: `enum Role: int8 { ... }`;\n- or calculated automatically to fit all values.\n"
  },
  {
    "path": "languages/tolk/types/generics.mdx",
    "content": "---\ntitle: \"Generic structs and aliases\"\nsidebarTitle: \"Generics\"\n---\n\nGeneric structs and type aliases exist only at the type level and incur no runtime cost.\n\n```tolk\nstruct Container<T> {\n    element: T?\n}\n\nstruct Nothing\n\ntype Wrapper<T> = Nothing | Container<T>\n```\n\nExample:\n\n```tolk\nfun checkElement<T>(c: Container<T>) {\n    return c.element != null;\n}\n\nfun demo() {\n    var c: Container<int32> = { element: null };\n\n    var n: Wrapper<int> = Nothing {};\n    var i: Wrapper<int32> = Container { element: 0 };\n}\n```\n\n## Type arguments\n\nType arguments must be specified. When referencing a generic `Container`, `T` must be provided explicitly:\n\n```tolk\nfun getItem(c: Container)        // error\nfun getItem(c: Container<int>)   // ok\nfun getItem<T>(c: Container<T>)  // ok\n```\n\nFor generic functions, type arguments can be inferred from the call site:\n\n```tolk\nfun doSmth<T>(value: Container<T>) {\n    // ...\n}\n\nfun demo() {\n    doSmth({ element: 123 });         // T = int\n    doSmth({ element: cellOrNull });  // T = cell?\n}\n```\n\n## Default type arguments\n\nA type parameter can have a default type: `<T = xxx>`. Such type parameters may be omitted at use sites.\n\n```tolk\nstruct StrangeUnion<T1, T2 = null> {\n    item: T1 | T2\n}\n\nfun demo() {\n    var m1: StrangeUnion<int> = { item: 10 };\n    var m2: StrangeUnion<int, bool> = { item: 20 };\n    // m1.item is `int?`\n    // m2.item is `int | bool`\n}\n```\n\nType arguments cannot reference one another; expressions such as `T2 = T1` are invalid.\n\n## Type aliases\n\nGeneric parameters are supported not only by structs, but also by type aliases. The following example defines a generic type alias `Response<TResult, TError>`:\n\n```tolk\nstruct Ok<TResult> { result: TResult }\nstruct Err<TError> { err: TError }\n\ntype Response<R, E> = Ok<R> | Err<E>\n\nfun loadNextRef(mutate s: slice): Response<cell, int32> {\n    return s.remainingRefsCount()\n        ? Ok { result: s.loadRef() }\n        : Err { err: ERR_NO_MORE_REFS }\n}\n\nfun demo() {\n    match (val r = loadNextRef(mutate parsedSlice)) {\n        Ok => { r.result }    // cell\n        Err => { r.err }      // int32\n    }\n}\n```\n\n## Methods\n\nMethods for generics are declared exactly as for regular structures. In this form, the compiler treats `T`, which is unknown symbol, as a type parameter:\n\n```tolk\nfun Container<T>.getElement(self) {\n    return self.element\n}\n```\n\nWithout `self` parameter, a [method](/languages/tolk/syntax/functions-methods) will be static.\n"
  },
  {
    "path": "languages/tolk/types/list-of-types.mdx",
    "content": "---\ntitle: \"Type system overview\"\nsidebarTitle: \"List of types\"\n---\n\nTolk has the following types:\n\n- [numbers](/languages/tolk/types/numbers) — `int`, `int32`, `uint64`, `coins`, and others.\n- [boolean](/languages/tolk/types/booleans) — `true` and `false`.\n- [address](/languages/tolk/types/address) — `internal`, `external`, and `none`.\n- [cells](/languages/tolk/types/cells) — containers with up to 1023 bits of data and up to 4 references to other cells, plus the cell manipulation primitives of TVM: [builders and slices](/tvm/builders-and-slices).\n- [structures](/languages/tolk/types/structures) — multiple fields grouped into one entity.\n- [generics](/languages/tolk/types/generics) — any struct can be generic `<T>`.\n- [enums](/languages/tolk/types/enums) — distinct types containing integer variants.\n- [nullable types](/languages/tolk/types/nullable) — `null` safety and safe casts.\n- [union types](/languages/tolk/types/unions) — variables holding one of several possible values.\n- [tensors](/languages/tolk/types/tensors) — multiple values placed sequentially on the stack.\n- [tuples](/languages/tolk/types/tuples) — multiple values stored in a single TVM tuple.\n- [maps](/languages/tolk/types/maps) — key-value dictionaries.\n- [callables](/languages/tolk/types/callables) — first-class functions.\n- [`void` and `never`](/languages/tolk/types/void-never) — both represent the absence of a value.\n\nTo make an interchangeable alias for an existing type, including structural types, there are [type aliases](/languages/tolk/types/aliases).\n\nSmart contracts run on a stack-based virtual machine, [TVM](/tvm/overview), which imposes specific rules on how values are represented at runtime. For example, there is no distinct type for [strings](/languages/tolk/types/strings) — they are not native to TVM and thus are emulated using slices.\n\nAll on-chain data and communication rely entirely on [cells](/languages/tolk/types/cells), so the type system focuses on binary serialization and clear data relationships:\n\n- [Type checks and casts](/languages/tolk/types/type-checks-and-casts) covers casting with the unsafe `as` operator.\n- [TVM stack representation](/languages/tolk/types/overall-tvm-stack) summarizes how types map to the TVM stack.\n- [Serialization](/languages/tolk/types/overall-serialization) describes how types serialize and relate to [TL-B](/languages/tl-b/overview).\n"
  },
  {
    "path": "languages/tolk/types/maps.mdx",
    "content": "---\ntitle: \"Maps\"\n---\n\nTolk supports `map<K, V>`, a high-level type that represents TVM dictionaries. `K` denotes the key type, and `V` denotes the value type.\n\n- Keys and values must be serializable.\n- Provides built-in iteration in forward and reverse order, as well as from a specified key.\n- No runtime overhead compared to using low-level dictionaries directly.\n\n## Create an empty map\n\n```tolk\nvar m: map<int8, int32> = createEmptyMap();\n// or\nvar m = createEmptyMap<int8, int32>();\n```\n\nA map is a dedicated type and can be used in parameters, fields, and return types:\n\n```tolk\nstruct Demo {\n    m: map<int64, Point>\n}\n\nfun create(): Demo {\n    return {\n        m: createEmptyMap()\n    }\n}\n```\n\n## Add values to a map\n\nUse `m.set(k, v)` and the following methods:\n\n```tolk\nvar m: map<int8, int32> = createEmptyMap();\nm.set(1, 10);\nm.addIfNotExists(2, -20);\nm.replaceIfExists(2, 20);\nm.delete(2);   // now: [ 1 => 10 ]\n\nm.exists(1);   // true\nm.exists(2);   // false\n```\n\n## Get a value by key\n\n`m.get(key)` returns `isFound + loadValue()`:\n\n```tolk\nvar r = m.get(1);\nif (r.isFound) {\n    val v = r.loadValue();   // 10\n}\n```\n\nCheck `r.isFound`, not `r == null`. `map.get(key)` does not return `V?`, but a dedicated result type.\n\nAlternatively, use `m.mustGet(key)`, which returns `V` and throws if the key is missing:\n\n```tolk\nm.mustGet(1);       // 10\nm.mustGet(100500);  // runtime error\n```\n\n## Iterate forward and backward\n\nThere is no dedicated `foreach` syntax. Iteration follows this pattern:\n\n- Define a starting key using `m.findFirst()` or `m.findLast()`.\n- While `r.isFound`:\n  - use `r.getKey()` and `r.loadValue()`;\n  - advance the cursor using `m.iterateNext(r)` or `m.iteratePrev(r)`.\n\nIterate over all keys in forward order:\n\n```tolk\n// suppose there is a map [ 1 => 10, 2 => 20, 3 => 30 ]\n// this function will print \"1 10 2 20 3 30\"\nfun iterateAndPrint<K, V>(m: map<K, V>) {\n    var r = m.findFirst();\n    while (r.isFound) {\n        debug.print(r.getKey());\n        debug.print(r.loadValue());\n        r = m.iterateNext(r);\n    }\n}\n```\n\nIterate backward over keys ≤ 2:\n\n```tolk\n// suppose `m` is `[ int => address ]` and already populated\n// for every key<=2, print addr.workchain\nfun printWorkchainsBackwards(m: map<int32, address>) {\n    var r = m.findKeyLessOrEqual(2);\n    while (r.isFound) {\n        val a = r.loadValue();   // it's `address`\n        debug.print(a.getWorkchain());\n        r = m.iteratePrev(r);\n    }\n}\n```\n\n## Check if a map is empty\n\n```tolk\nm.isEmpty()    // not `m == null`\n```\n\nAt the TVM level, an empty map is stored as TVM `NULL`. However, since `map` is a dedicated type, it must be checked using `isEmpty()`.\n\nNullable maps `var m: map<...>?` are valid. In this case, `m` may be `null`, or it may hold either an empty or a non-empty map.\n\n## Allowed types for keys and values\n\nThe following key and value types are valid:\n\n```tolk\nmap<int32, Point?>\nmap<address, address>\nmap<Point, map<int3, bool>>\nmap<uint256, Cell<SnakeData>>\nmap<bits18, slice>\n```\n\nSome types are not allowed. General rules:\n\n- Keys must be fixed-width and contain no references.\n  - Valid: `int32`, `address`, `bits256`, `Point`.\n  - Invalid: `int`, `coins`, `cell`.\n- Values must be serializable.\n  - Valid: `coins`, `AnyStruct`, `Cell<AnyStruct>`.\n  - Invalid: `int`, `builder`.\n\nIn practice, keys are commonly `intN`, `uintN`, or `address`. Values can be any serializable type.\n\n## Available methods for maps\n\n- `createEmptyMap<K, V>(): map<K, V>`\n\nReturns an empty typed map. Equivalent to `PUSHNULL`, since TVM `NULL` represents an empty map.\n\n- `createMapFromLowLevelDict<K, V>(d: dict): map<K, V>`\n\nConverts a low-level TVM dictionary to a typed map. Accepts an optional cell and returns the same optional cell. Mismatched key or value types result in failures when calling `map.get` or related methods.\n\n- `m.toLowLevelDict(): dict`\n\nConverts a high-level map to a low-level TVM dictionary. Returns the same optional cell.\n\n- `m.isEmpty(): bool`\n\nChecks whether a map is empty. Use `m.isEmpty()` instead of `m == null`.\n\n- `m.exists(key: K): bool`\n\nChecks whether a key exists in a map.\n\n- `m.get(key: K): MapLookupResult<V>`\n\nGets an element by key. Returns `isFound = false` if key does not exist.\n\n- `m.mustGet(key: K, throwIfNotFound: int = 9): V`\n\nGets an element by key and throws if it does not exist.\n\n- `m.set(key: K, value: V): self`\n\nSets an element by key. Since it returns `self`, calls may be chained.\n\n- `m.setAndGetPrevious(key: K, value: V): MapLookupResult<V>`\n\nSets an element and returns the previous element. If no previous element, `isFound = false`.\n\n- `m.replaceIfExists(key: K, value: V): bool`\n\nSets an element only if the key exists. Returns whether an element was replaced.\n\n- `m.replaceAndGetPrevious(key: K, value: V): MapLookupResult<V>`\n\nSets an element only if the key exists and returns the previous element.\n\n- `m.addIfNotExists(key: K, value: V): bool`\n\nSets an element only if the key does not exist. Returns `true` if added.\n\n- `m.addOrGetExisting(key: K, value: V): MapLookupResult<V>`\n\nSets an element only if the key does not exist. If exists, returns the existing value.\n\n- `m.delete(key: K): bool`\n\nDeletes an element by key. Returns `true` if deleted.\n\n- `m.deleteAndGetDeleted(key: K): MapLookupResult<V>`\n\nDeletes an element by key and returns the deleted element. If not found, `isFound = false`.\n\n- `m.findFirst(): MapEntry<K, V>`\n- `m.findLast(): MapEntry<K, V>`\n\nFinds the first (minimal) or last (maximal) element. For integer keys, returns minimal (maximal) integer. For addresses or complex keys represented as slices, returns lexicographically smallest (largest) key. Returns `isFound = false` when the map is empty.\n\n- `m.findKeyGreater(pivotKey: K): MapEntry<K, V>`\n- `m.findKeyGreaterOrEqual(pivotKey: K): MapEntry<K, V>`\n- `m.findKeyLess(pivotKey: K): MapEntry<K, V>`\n- `m.findKeyLessOrEqual(pivotKey: K): MapEntry<K, V>`\n\nFinds an element with key compared to `pivotKey`.\n\n- `m.iterateNext(current: MapEntry<K, V>): MapEntry<K, V>`\n- `m.iteratePrev(current: MapEntry<K, V>): MapEntry<K, V>`\n\nIterates over a map in ascending or descending order.\n\n## Augmented hashmaps and prefix dictionaries\n\nThese structures are rarely used and are not part of the Tolk type system.\n\n- Augmented hashmaps and [Merkle proofs](/foundations/proofs/overview): implement interaction manually.\n- Prefix dictionaries: `import @stdlib/tvm-dicts` and use [assembly functions](/languages/tolk/features/asm-functions).\n\n## Keys are auto-serialized\n\nAt the TVM level, keys can be numbers or slices. Complex keys, such as `Point`, are automatically serialized and deserialized by the compiler.\n\n```tolk\nstruct Point {\n    x: int8\n    y: int8\n}\n\nfun demo(m: map<Point, V>) {\n    // a key is automatically packed to a 16-bit slice\n    m.set({x: 10, y: 20}, 123);\n    // and unpacked back to `Point`\n    return m.findFirst().key;\n}\n```\n\nIf a key is a struct containing a single `intN` field, it is treated as a number.\n\n```tolk\nstruct UserId {\n    v: int32\n}\n\nstruct Demo {\n    // equal to K=int32 without extra serialization\n    m: map<UserId, V>\n}\n```\n\n## Emulate `Set<T>` with maps\n\nA set can be represented using a map with a unit value type:\n\n```tolk\ntype Set<T> = map<T, ()>\n```\n\nUsing `map<T, ()>` to emulate a set works, but it exposes the full `map` API, while a set has an API consisting of 4 functions. To avoid this, create a simple wrapper:\n\n```tolk\nstruct Set<T> {\n    private m: map<T, ()>\n}\n\nfun Set<T>.add(self, value: T) { /* ... */ }\n// etc.\n```\n\n## `isFound` instead of optional values\n\nMaps support nullable value types, for example:\n\n```tolk\nmap<int32, address?>\nmap<K, Point?>\n```\n\nWith such maps, two different situations are possible:\n\n- the key exists, and the value is `null`;\n- the key does not exist.\n\nIf a map lookup returned an optional value `V?`, these cases could not be distinguished, because both would result in `null`.\n\nThis becomes visible at the TVM level. At the TVM level, a dictionary reads return binary data as slices. The stack contains either:\n\n- `(slice -1)` when the key is found;\n- `(null 0)` when the key is not found.\n\nReturning `V?` would require decoding the value and additional checks to determine whether the key existed:\n\n```ansi\nIF stack[0] == -1:\n    decode stack[1] to V\n    transform V to V?\nELSE:\n    drop stack[1]\n    transform null to V?\n```\n\nThen, at usage, it's compared to `null`:\n\n```tolk\nval v = m.get(k);   // internally, IF ELSE: for decoding\nif (v != null) {    // one more IF: for checking\n    ...\n}\n```\n\nSo, a single map lookup results in multiple runtime checks. To avoid this, map lookup methods return a dedicated result type instead of `V?`:\n\n```tolk\nfun map<K, V>.get(self, key: K): MapLookupResult<V>;\n\nstruct MapLookupResult<TValue> {\n    private readonly rawSlice: slice?\n    isFound: bool\n}\n\nfun MapLookupResult<TValue>.loadValue(self): TValue {\n    return TValue.fromSlice(self.rawSlice!)\n}\n```\n\nKey existence is checked explicitly using `isFound`, and the value is decoded only when needed.\n\nUsage:\n\n```tolk\nval r = m.get(k);\nif (r.isFound) {\n    r.loadValue();\n}\n```\n\nThe same result type is reused by other methods, for example:\n\n```tolk\nval prev = m.setAndGetPrevious(1, 100500);\n// NOT `if (prev != null)`, but\nif (prev.isFound) {\n   prev.loadValue()   // 10\n}\n```\n\n`MapLookupResult` directly corresponds to the `(slice -1)` or `(null 0)` values returned by TVM dictionary operations and avoids additional runtime checks required when returning `V?`.\n\n## Stack layout and serialization\n\n- An empty map is represented as [TVM `NULL`](/languages/tolk/types/overall-tvm-stack) and is [serialized as `0`](/languages/tolk/types/overall-serialization).\n- A non-empty map is represented as a TVM `CELL` and is serialized as `1` followed by a reference.\n"
  },
  {
    "path": "languages/tolk/types/nullable.mdx",
    "content": "---\ntitle: \"Nullable types and null safety\"\nsidebarTitle: \"Nullable types\"\n---\n\nTolk supports nullable types `T?`: they can hold a `null` value and are a shorthand for `T | null`. Any type can be made nullable: primitive types, structures, and other composites.\n\nThe special `null` value cannot be assigned to a non-nullable type.\n\n## Null safety\n\nThe compiler enforces null safety: nullable values cannot be accessed without an explicit check.\n\n```tolk\nvar value = x > 0 ? 1 : null;  // int?\nvalue + 5;                     // error\n\n// A check is required\nif (value != null) {    // value is `int`\n    value + 5;          // ok\n    b.storeInt(value);  // ok\n}\n```\n\nWhen a variable has no explicit type, its type is inferred from the initial assignment. Nullable variables must be declared explicitly:\n\n```tolk\n// Tolk can infer `int`, not `int?`\nvar i = 0;\ni = null;       // error, can't assign `null` to `int`\ni = maybeInt;   // error, can't assign `int?` to `int`\n\n// Type ascription is mandatory for nullables\nvar i: int? = 0;\ni = null;       // ok\n```\n\nWhen the initial value is `null`, the type must be specified:\n\n```tolk\nvar i: int? = null;\n// or\nvar i = null as int?;\n```\n\n## Smart casts\n\nThe nullable type is narrowed after the `null` check. This feature, known as _smart casts_, is available in many general-purpose languages.\n\n```tolk\n// Example 1\nif (lastCell != null) {\n    // here, lastCell is `cell`, not `cell?`\n}\n\n// Example 2\nif (lastCell == null || prevCell == null) {\n    // both are `null`\n    return;\n}\n// here, both lastCell and prevCell are `cell`\n\n// Example 3\nvar x: int? = ...; // `null` or some int value\nif (x == null) {\n    x = random();\n}\n// here, x is `int`\n\n// Example 4\nwhile (lastCell != null) {\n    lastCell = lastCell.beginParse().loadMaybeRef();\n}\n// here, lastCell is `null`\n```\n\nSmart casts apply to local variables, structure fields, and tensor or tuple indices.\n\n```tolk\nstruct HasOpt {\n    optionalId: int?\n}\n\nfun demo(obj: HasOpt) {\n    if (obj.optionalId != null) {\n        // obj.optionalId is `int` here\n    }\n}\n```\n\nSmart casts also apply to initial values. Even if a variable is declared as `int?` but initialized with a number, it remains a safe non-null integer until it is reassigned:\n\n```tolk\nvar idx: int? = -1;\n// idx is `int`\n```\n\n## Non-null assertion operator `!`\n\nThe `!` operator bypasses the compiler's nullability check. It is similar to `!` in TypeScript and `!!` in Kotlin.\n\n```tolk\nfun doSmth(c: cell) {}\n\nfun analyzeStorage(nCells: int, lastCell: cell?) {\n    if (nCells > 0) {       // then lastCell is 100% not null\n        doSmth(lastCell!);  // use ! for this fact\n    }\n}\n```\n\nIn some cases, the developer has knowledge that the compiler lacks:\n\n```tolk\n// this key exists according to config,\n// so one can force `cell` instead of `cell?`\nval mainValidators = blockchain.configParam(16)!;\n```\n\n### Global variables\n\nUnlike local variables, global variables cannot be smart-cast. The `!` operator is the only way to narrow their type:\n\n```tolk\nglobal gLastCell: cell?\n\nfun demo() {\n    // this global is presumed to be set elsewhere,\n    // lets force `cell` instead of `cell?`\n    doSmth(gLastCell!);\n}\n```\n\nThe `!` operator is useful when conditions outside the code itself guarantee non-nullability.\n\n## Stack layout and serialization\n\nPrimitives like `int` or `cell`, when nullable, are [serialized](/languages/tolk/types/overall-serialization) as a TVM value or `null`.\n\nNullable structures and other composites are [represented](/languages/tolk/types/overall-tvm-stack) as tagged unions:\n\n- if their type is `null`, they are serialized as `0`;\n- otherwise, they are serialized as `1` followed by the non-null value.\n\nThe `address?` type is an exception, and it is [serialized in a different way](/languages/tolk/types/address#nullable-address).\n"
  },
  {
    "path": "languages/tolk/types/numbers.mdx",
    "content": "---\ntitle: \"Numbers\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nAt runtime, there are only 257-bit signed integers. They are represented by the Tolk's general `int` type.\n\nHowever, at the start and end of each execution, the contract's state is deserialized and serialized, respectively. To optimize space and reduce storage costs, it is possible to encode integer values using fewer bits.\n\nTolk provides additional integer types to accommodate (de)serialization:\n\n| Name             | Inclusive range                       | Space taken                              | Examples                       |\n| ---------------- | ------------------------------------- | ---------------------------------------- | ------------------------------ |\n| Signed `intN`    | -2<sup>N-1</sup> to 2<sup>N-1</sup>-1 | `N` bits, where `N` is between 1 and 257 | `int32`, `int257`, `int7`      |\n| Unsigned `uintN` | 0 to 2<sup>N</sup>-1                  | `N` bits, where `N` is between 1 and 256 | `uint16`, `uint256`, `uint119` |\n\nThere are also types of variable bit-width:\n\n| Name                 | Inclusive range                       | Space taken            | Notes                                                                         |\n| -------------------- | ------------------------------------- | ---------------------- | ----------------------------------------------------------------------------- |\n| Unsigned `coins`     | 0 to 2<sup>120</sup>-1                | Between 4 and 124 bits | They represent nanoToncoin, where 10<sup>9</sup> nanoToncoin equals 1 Toncoin |\n| Unsigned `varuint16` | Same as `coins`                       | Same as `coins`        | Rarely used                                                                   |\n| Unsigned `varuint32` | 0 to 2<sup>248</sup>-1                | Between 5 and 253 bits | Rarely used                                                                   |\n| Signed `varint16`    | -2<sup>119</sup> to 2<sup>119</sup>-1 | Same as `coins`        | Rarely used                                                                   |\n| Signed `varint32`    | -2<sup>247</sup> to 2<sup>247</sup>-1 | Between 5 and 253 bits | Rarely used                                                                   |\n\n<Aside\n  type=\"caution\"\n>\n  All these types are **257-bit integers at runtime**. [Overflows can occur at runtime](/tvm/exit-codes#4%3A-integer-overflow), but they are more likely during serialization.\n\n  For example, subtracting $300$ from a variable of type `uint8` does not cause a runtime overflow. Yet, attempting to store the result back to the same variable triggers [exit code 5: integer out of expected range](/tvm/exit-codes#5%3A-integer-out-of-expected-range).\n</Aside>\n\n## Literals\n\nAll the following constants are of `int` type:\n\n```tolk\n// Binary literal\nconst TEN = 0b1010;\n\n// Hex literal\nconst MAX_UINT8 = 0xFF;\n\n// Allowed values range from -2^256 to 2^256-1\nconst MAX_INT = 115792089237316195423570985008687907853269984665640564039457584007913129639935;\n```\n\n## First-class types\n\nAll integer types can be nullable, combined within a union, and otherwise used in structural or multi-valued types:\n\n```tolk\nstruct Demo {\n    f1: int32?           // nullable\n    f2: int32 | uint64   // union\n    pair: (int8, coins)\n}\n\nfun demo(d: Demo) {\n    if (d.f1 != null) {\n        d.f1    // smart cast to `int32`\n    }\n    d.pair.1    // `coins`\n}\n```\n\n## No floating-point numbers\n\nThe virtual machine supports only signed 257-bit integers. Floating-point numbers do not exist.\n\nRepresent monetary, Toncoin values with `coins`:\n\n```tolk\n// 1.23 Toncoin or 1,230,000,000 nanoToncoin\nconst MIN_BALANCE = ton(\"1.23\")\n```\n\n## Serialization\n\n[Serialization](/languages/tolk/types/overall-serialization) works as follows:\n\n- `int` — not serializable; use `intN` and other types.\n- `intN` — a fixed `N`-bit signed integer.\n- `uintN` — a fixed `N`-bit unsigned integer.\n- `coins` — an alias to `varuint16`.\n- `varint16` — 4 bits of length followed by an 8 \\* length-bit number.\n- `varuint16` — unsigned version of `varint16`.\n- `varint32` — 5 bits of length followed by an 8 \\* length-bit number.\n- `varuint32` — unsigned version of `varint32`.\n\n### `intN` describes serialization, `int` does not\n\nTo automatically parse binary data, the compiler must load and store integers correctly. When designing a contract schema, fields are described in terms such as \"`queryID` is unsigned 64-bit\" and \"`counterValue` is 32-bit\". This is translates directly in Tolk:\n\n```tolk\nstruct IncMessage {\n    queryID: uint64\n    counterValue: int32\n}\n```\n\nAs a result, `IncMessage` can be serialized to a cell and decoded back.\n\nThe general-purpose type `int` represents an integer with no serialization information. Consider this struct:\n\n```tolk\nstruct Point {\n    x: int\n    y: int\n}\n```\n\nIt is valid and it is possible to create a variable `p` of type `Point`. However, a call `p.toCell()` would produce the following error:\n\n```ansi\nerror: auto-serialization via toCell() is not available for type `Point`\n       because field `Point.x` of type `int` can't be serialized\n       because type `int` is not serializable, it doesn't define binary width\n       hint: replace `int` with `int32` / `uint64` / `coins` / etc.\n```\n\nTo make the struct serializable, replace `int` with a specific integer type:\n\n```tolk\nstruct Point {\n    x: int8\n    y: int8\n}\n```\n\n### Overflow occurs only at serialization\n\nConsider the following code:\n\n```tolk\nvar v: uint8 = 255;\nv += 1;     // 256\n```\n\nThe variable `v` there would neither overflow nor be clamped at runtime. Instead, it would be equal to 256 during subsequent execution steps.\n\nThere are no runtime bounds checks, and overflows of all integer types occur only during serialization, except for the general `int` type, which can [overflow when doing arithmetic](/tvm/exit-codes#4%3A-integer-overflow).\n\n```tolk\nstruct Resp {\n    outValue: uint8\n}\n\nfun demo(resp: Resp) {\n    // 256, no errors yet\n    resp.outValue = v;\n\n    // A runtime overflow error that is caused by serialization\n    // of the struct containing an uint8 to a cell.\n    resp.toCell();\n}\n```\n\n### Generic `int` implicitly casts to and from any `intN`\n\nAll arithmetic operations on `intN` degrade to `int` and all [numeric literals](#literals) are of type `int`.\n\nTo prevent further errors, Tolk disallows direct assignments between `intN` and `intM` types, when `N` and `M` are not equal.\n\n```tolk\nfun takeAnyInt(a: int) { /* ... */ }\nfun getAnyInt(): int { return 42 }\n\nfun f(op: int32, qid: uint64) {\n    op = qid;               // error\n    op = qid as int32;      // ok\n\n    op + query_id;          // ok, int\n    if (op == qid) {}       // ok, not assignment\n\n    takeAnyInt(op);         // ok\n    op = getAnyInt();       // ok\n\n    var amount: int32 = 1000;\n    var percent: uint8 = 50;\n    // ok, int\n    var new = amount * percent / 100;\n    // ok, int auto-casts to int32\n    amount = new;\n}\n```\n\n### Type `coins` and function `ton(\"0.05\")`\n\nSimilar to `int32`, Tolk has a dedicated `coins` type representing nanoToncoin values.\n\nThe `coins` type has special serialization rules. It's serialized as variadic integer: small values consume fewer, large values consume more.\n\nArithmetic with `coins` degrades to `int`, similar to `intN`, except for addition or subtraction operations, where the `coins` type is preserved.\n\nValues of type `int` can be cast back to `coins`, following the same rules as `intN`.\n\nThere is a `ton` built-in function, which calculates nanoToncoin values at compile-time. It accepts only constants and literals, e.g., `ton(some_variable)` is invalid.\n\n```tolk\nconst ONE_TON = ton(\"1\");     // `coins`, value: 1000000000\n\nfun calcCost() {\n    val cost = ton(\"0.05\");   // `coins`, value: 50000000\n    return ONE_TON + cost;\n}\n```\n"
  },
  {
    "path": "languages/tolk/types/overall-serialization.mdx",
    "content": "---\ntitle: \"Serialization\"\nsidebarTitle: \"Serialization\"\n---\n\nThis page assumes prior knowledge of the [TL-B](/languages/tl-b/overview) and [TVM](/tvm/overview). It serves as a concise low-level reference.\n\nA consolidated summary of how Tolk types are serialized into TL-B–compatible binary data.\n\n## `int`\n\n- Not serializable. Use `intN` or other numeric types.\n\n## `intN`\n\n- Fixed N-bit signed integer\n- TL-B: `intN`\n- Stored using `{N} STI`\n- Loaded using `{N} LDI`\n\n## `uintN`\n\n- Fixed N-bit unsigned integer\n- TL-B: `uintN`\n- Stored using `{N} STU`\n- Loaded using `{N} LDU`\n\n## `coins`\n\n- Alias to `varuint16`\n- TL-B: `VarUInteger 16`\n- Stored using `STGRAMS`\n- Loaded using `LDGRAMS`\n\n## `varintN` (N = 16 or 32)\n\n- Variable-length signed integer: 4 or 5 bits for `length + 8 * len` bit number\n- TL-B: `VarInteger {N}`\n- Stored using `STVARINT{N}`\n- Loaded using `LDVARINT{N}`\n\n## `varuintN` (N = 16 or 32)\n\n- Variable-length unsigned integer: 4 or 5 bits for `length + 8 * len` bit number\n- TL-B: `VarUInteger {N}`\n- Stored using `STVARUINT{N}`\n- Loaded using `LDVARUINT{N}`\n\n## `bool`\n\n- One bit: `0` or `1`\n- TL-B: `Bool`\n- Stored using `1 STI`\n- Loaded using `1 LDI` resulting in `0` or `-1`\n\n## `address`\n\n- Standard internal address (267 bits): `0b100 + workchain + hash`\n- TL-B: `addr_std`\n- Stored using `STSTDADDR`\n- Loaded using `LDSTDADDR`\n\n## `address?` (nullable)\n\n- Internal address or none (2 or 267 bits): `00` for null, otherwise an address\n- TL-B: `addr_none` or `addr_std`\n- Stored using `STOPTSTDADDR`\n- Loaded using `LDOPTSTDADDR`\n\n## `any_address`\n\n- Any valid TL-B address, from 2 to 523 bits\n- TL-B: `MsgAddress`\n- Stored using `STSLICE`\n- Loaded using `LDMSGADDR`\n\n## `cell`, `Cell<T>`\n\n- A reference\n- TL-B: `^Cell` / `^T`\n- Stored using `STREF`\n- Loaded using `LDREF`\n\n## `cell?`, `Cell<T>?` (nullable)\n\n- Maybe reference (`0` or `1+ref`)\n- TL-B: `Maybe ^Cell` / `Maybe ^T`\n- Stored using `STOPTREF`\n- Loaded using `LDOPTREF`\n\n## `bitsN`\n\n- N bits\n- TL-B: `bitsN`\n- Stored using `STSLICE`, preceded by a runtime check that the slice contains exactly N bits and zero references; the check can be turned off using `skipBitsNValidation = false`.\n- Loaded using `LDSLICE` / `LDSLICEX` for N > 256\n\n## `RemainingBitsAndRefs`\n\n- Represents the remainder of a slice when reading, and a raw slice when writing.\n- TL-B: `Cell`\n- Stored using `STSLICE`\n- Loaded by copying the current slice and resetting the reader to an empty slice.\n\n## `builder`, `slice`\n\n- Can be used for writing, but not for reading.\n- Not recommended, as they do not reveal internal structure and have unpredictable size.\n- Auto-generated TypeScript wrappers cannot parse them.\n\n## `struct`\n\nIf a struct has a prefix, it is written first. The fields are then serialized sequentially.\n\n```tolk\nstruct (0x12345678) A {\n    a: int8\n    b: cell?\n}\n\nfun demo() {\n    val a: A = {\n        a: 123,\n        b: createEmptyCell(),\n    };\n    // 41 bits and 1 ref: opcode + int8 + '1' + empty ref\n    a.toCell()\n}\n```\n\n### 32-bit prefixes (opcodes)\n\nBy convention, all incoming and outgoing messages use 32-bit prefixes:\n\n```tolk\nstruct (0x7362d09c) TransferNotification {\n    queryId: uint64\n    // ...\n}\n```\n\n### Not only 32-bit prefixes\n\nDeclaring messages with opcodes does not differ from declaring ordinary structs. A prefix can have any bit width:\n\n- `0x000F` — 16-bit prefix\n- `0x0F` — 8-bit prefix\n- `0b010` — 3-bit prefix\n- `0b00001111` — 8-bit prefix\n\nConsider the TL-B scheme:\n\n```tl-b\nasset_simple$001 workchain:int8 ptr:bits32 = Asset;\nasset_booking$1000 order_id:uint64 = Asset;\n// ...\n```\n\nIn Tolk, use structures and union types:\n\n```tolk\nstruct (0b001) AssetSimple {\n    workchain: int8\n    ptr: bits32\n}\n\nstruct (0b1000) AssetBooking {\n    orderId: uint64\n}\n\ntype Asset = AssetSimple | AssetBooking // | ...\n```\n\nDuring deserialization, `Asset` is matched using the explicitly declared prefixes.\n\nIf a `struct` has a prefix, it is applied consistently in all contexts, both standalone and as part of a union:\n\n```tolk\nAssetBooking.fromSlice(s)   // expecting '1000...' (binary)\nAssetBooking{...}.toCell()  // '1000...'\n```\n\n## Type aliases\n\nA type alias is identical to its underlying type, unless a custom serializer is defined.\n\nTo implement a \"variadic string\" encoded as `len + data`:\n\n```\nlen: (## 8)        // 8 bits of len\ndata: (bits len)   // 0..255 bits of data\n```\n\nTo express this, define a type and provide a custom serializer:\n\n```tolk\ntype ShortString = slice\n\nfun ShortString.packToBuilder(self, mutate b: builder) {\n    val nBits = self.remainingBitsCount();\n    b.storeUint(nBits, 8);\n    b.storeSlice(self);\n}\n\nfun ShortString.unpackFromSlice(mutate s: slice) {\n    val nBits = s.loadUint(8);\n    return s.loadBits(nBits);\n}\n```\n\n`ShortString` can then be used as a regular type everywhere:\n\n```tolk\ntokenName: ShortString\nfullDomain: Cell<ShortString>\n```\n\nThe method names `packToBuilder` and `unpackFromSlice` are reserved for this purpose. Their signatures must match exactly as shown.\n\n## `enum`\n\nThe serialization type can be specified manually:\n\n```tolk\n// `Role` will be (un)packed as `int8`\nenum Role: int8 {\n    Admin,\n    User,\n    Guest,\n}\n\nstruct ChangeRoleMsg {\n    ownerAddress: address\n    newRole: Role    // int8: -128 <= V <= 127\n}\n```\n\nOtherwise, it is calculated automatically. For `Role` above, `uint2` is sufficient to fit values `0, 1, 2`:\n\n```tolk\n// `Role` will (un)packed as `uint2`\nenum Role {\n\t  Admin,\n\t  User,\n\t  Guest,\n}\n```\n\nInput values are validated during deserialization. For `enum Role: int8`, any input value outside the range of defined enum variants, e.g., \\< 0 or > 2, triggers [exception 5](/tvm/exit-codes).\n\nValues not explicitly listed in the enum definition are also rejected:\n\n```tolk\nenum OwnerHashes: uint256 {\n    id1 = 0x1234,\n    id2 = 0x2345,\n    ...\n}\n\n// on serialization, just \"store uint256\"\n// on deserialization, \"load uint256\" + throw 5 if v not in [0x1234, 0x2345, ...]\n```\n\n## Nullable types `T?` (except `address?`)\n\n- Often called `Maybe`; `0` or `1+T`\n- TL-B: `(Maybe T)`\n- Stored using `1 STI` + `IF` ...\n- Loaded using `1 LDI` + `IF` ...\n\nException: `address?` is serialized as internal or none (2 or 267 bits):\n\n- `00` – null;\n- otherwise – a standard internal address.\n\n## Union types `T1 | T2 | ...`\n\n- `T | null` is serialized as TL-B `Maybe T`.\n- If all `T_i` have prefixes `struct (0x1234) A`, those prefixes are used.\n- Otherwise, the compiler generates a prefix tree automatically.\n\n### Manual serialization prefixes\n\nIf all `T_i` have manual prefixes, they are used:\n\n```tolk\nstruct (0b001)  AssetSimple   { /* body1 */ }\nstruct (0b1000) AssetBooking  { /* body2 */ }\nstruct (0b01)   AssetNothing  {}\n\nstruct Demo {\n    // '001'+body1 OR '1000'+body2\n    e: AssetSimple | AssetBooking\n    // '001'+body1 OR '1000'+body2 OR '01'\n    f: AssetSimple | AssetBooking | AssetNothing\n}\n```\n\nIf a prefix exists for `A` but not for `B`, the union `A | B` cannot be serialized.\n\n### Auto-generated prefix tree\n\nIf `T_i` do not have manual prefixes, the compiler generates a prefix tree.\n\n- A two-component union `T1 | T2` is serialized as TL-B `Either` using prefixes 0 and 1. Example: `int32 | int64` → `0 + int32` or `1 + int64`.\n\n- For unions with more components, longer prefixes are generated. Example: `int32 | int64 | int128 | int256` → `00 / 01 / 10 / 11`\n\nGeneral rules:\n\n- If `null` is present, it is assigned prefix 0, and all other variants use `1 + tree`:\n  - `A|B|C|D|null` → `0 | 100+A | 101+B | 110+C | 111+D`.\n- If `null` is not present, variants are assigned sequentially:\n  - `A|B|C` → `00+A | 01+B | 10+C`.\n\n```tolk\nstruct WithUnion {\n    f: int8 | int16 | int32\n}\n```\n\nField f is serialized as:\n\n- `00 + int8`\n- `01 + int16`\n- `10 + int32`\n\nOn deserialization, the same prefixes are expected; an unmatched prefix (e.g., 11) triggers an exception.\n\nThe same applies to structs without manual prefixes:\n\n```tolk\nstruct A { ... }    // 0x... prefixes not specified\nstruct B { ... }\nstruct C { ... }\n\nstruct WithUnion {\n    // auto-generated prefix tree: 00/01/10\n    f: A | B | C\n    // with null, like Maybe<A|B>: 0/10/11\n    g: A | B | null\n    // even this works; when '11', a ref exists\n    h: A | int32 | C | cell\n}\n```\n\n## Tensors `(T1, T2, ...)`\n\nTensor components are serialized sequentially, in the same manner as `struct` fields.\n\n## `tuple` and typed tuples\n\nTuples are not serializable. However, tuples can be returned from [get methods](/tvm/get-method#get-methods), since contract getters operate on the TVM stack rather than using serialization.\n\n## `map<K, V>`\n\n- Maybe reference: `0` for empty or `1+ref` for dictionary contents\n- TL-B: [`HashmapE n X`](/languages/tl-b/complex-and-non-trivial-examples#hashmap)\n- Stored using `STDICT`\n- Loaded using `LDDICT`\n\n## Callables `(...ArgsT) -> ResultT`\n\n- Callables cannot be serialized.\n- Lambdas can be used within contract logic but cannot be serialized for off‑chain responses.\n"
  },
  {
    "path": "languages/tolk/types/overall-tvm-stack.mdx",
    "content": "---\ntitle: \"TVM stack representation\"\nsidebarTitle: \"TVM stack\"\n---\n\nThis page assumes prior knowledge of the [Tolk type system](/languages/tolk/types/list-of-types) and [TVM](/tvm/overview). It serves as a concise low-level reference.\n\nA consolidated summary of how Tolk types are represented on the TVM stack.\n\n## `int`, `intN`, `coins`\n\n- All numeric types are backed by TVM `INT`.\n- Type `intN` uses full 257-bit precision, so any integer value fits into it. Overflow occurs only during serialization.\n\n## `bool`\n\n- The `bool` type is backed by TVM `INT` with value `-1` or `0` at runtime.\n- The unsafe cast `someBool as int` is valid and produces `-1` or `0`.\n\n## `address`, `any_address`\n\n- Both `address` and `any_address` are backed by TVM `SLICE` values containing raw binary data.\n- A nullable `address?` is represented as either TVM `NULL` or `SLICE`.\n- The unsafe cast `someAddr as slice` is valid and reversible.\n\n## `cell`\n\n- The `cell` type is backed by TVM `CELL`.\n- The unsafe cast `someCell as Cell<T>` is valid.\n\n## `Cell<T>`\n\n- The `Cell<T>` type is also backed by TVM `CELL`. The type parameter `T` is compile‑time metadata.\n\n## `slice`\n\n- Type `slice` is backed by TVM `SLICE`.\n\n## `bitsN`\n\n- The `bitsN` type is backed by TVM `SLICE`.\n- The unsafe cast `someSlice as bitsN` is valid and reversible.\n\n## `RemainingBitsAndRefs`\n\n- The `RemainingBitsAndRefs` type is backed TVM `SLICE`. It is an alias of `slice` that is handled specially during deserialization.\n\n## `builder`\n\n- The `builder` type is backed by TVM `BUILDER`. Bits written to a builder cannot be read directly. Access to the data is possible only by converting the `builder` to a `slice`.\n\n## `struct`\n\nFields of a structure are placed sequentially on the stack. For example, `Point` occupies two stack slots, and `Line` occupies four:\n\n```tolk\nstruct Point {\n    x: int\n    y: int\n}\n\nstruct Line {\n    start: Point\n    end: Point\n}\n```\n\nWhen constructing a `Line` value, four integers are placed onto the stack:\n\n```tolk\nfun generateLine() {\n    val l: Line = {\n        start: { x: 10, y: 20 },\n        end: { x: 30, y: 40 },\n    };\n    // on a stack: 10 20 30 40\n    return l;\n}\n```\n\nSingle-field structures have no overhead compared to the plain values.\n\n## `enum`\n\n- Every enum is backed by TVM `INT`. Tolk supports integer enums only; for example, not addresses.\n\n## Nullable types `T?`\n\nPrimitive nullable types such as `int?`, `address?`, and `cell?` occupy a single stack slot. That slot holds either TVM `NULL` or the corresponding value.\n\n```tolk\nfun demo(maybeAddr: address?) {\n    // maybeAddr is one stack slot: `NULL` or `SLICE`\n}\n```\n\nA nullable structure with a single non-nullable primitive field can also be represented:\n\n```tolk\nstruct MyId {\n    value: int32\n}\n\nfun demo(maybeId: MyId?) {\n    // maybeId is one stack slot: `NULL` or `INT`\n}\n```\n\nNullable values of multi-slot types, such as `Point` or a tensor `(bool, cell)`, occupy N + 1 stack slots. The last is used for \"typeid\".\n\n```tolk\nstruct Point {\n    x: int\n    y: int\n}\n\nfun demo(maybeP: Point?) {\n    // maybeP is 3 stack slots:\n    // when null: \"NULL, NULL, INT (0)\"\n    // when not:  \"INT (x), INT (y), INT (4567)\"\n}\n```\n\nFor every nullable type, the compiler assigns a unique `typeid`; for example, 4567 for `Point`. The `typeid` is stored in an extra stack slot. The `typeid` value for `null` is `0`. Expressions such as `p == null` or `p is Point` check the `typeid` slot.\n\nThe following structure, when nullable, requires an extra stack slot:\n\n```tolk\nstruct Tricky {\n    opt: int?\n}\n\nfun demo(v: Tricky?) {\n    // v occupies 2 stack slots,\n    // because either `v == null` or `v.opt == null`:\n    // when v == null: \"NULL, INT (0)\"\n    // when v != null: \"INT/NULL, INT (2345)\"\n}\n```\n\n## Union types `T1 | T2 | ...`\n\nUnion types are represented as tagged unions on the stack:\n\n- each alternative type is assigned a unique `typeid`; e.g., 1234 for `int`;\n- the union occupies N+1 stack slots, where N is the maximum size of `T_i`;\n- the(N+1)-th slot contains the `typeid` of the current value.\n\nThus, `match` is implemented as a comparison of the (N+1)-th slot, and passing or assigning a value involves stack rearrangement.\n\n```tolk\nfun complex(v: int | slice | (int, int)) {\n    // `v` is 3 stack slots:\n    // - int:        (NULL, 100, 1234)\n    // - slice:      (NULL, CS{...}, 2345)\n    // - (int, int): (200, 300, 3456)\n}\n\nfun demo(someOf: int | slice) {\n    // `someOf` is 2 stack slots: value and type-id\n    // - int:   (100, 1234)\n    // - slice: (CS{...}, 2345)\n    match (someOf) {\n        int => {     // IF TOP == 1234\n            // slot1 is TVM `INT`, can be used in arithmetics\n        }\n        slice => {   // ELSE\n            // slot1 is TVM `SLICE`, can be used to loadInt()\n        }\n    }\n\n    complex(v);   // passes (NULL, v.slot1, v.typeid)\n    complex(5);   // passes (NULL, 5, 1234)\n}\n```\n\n`T | null` is called nullable and optimized for atomic types: `int?` uses a single slot. Non-atomics are handled generally, with `typeid=0`.\n\n## Tensors `(T1, T2, ...)`\n\nTensor components are placed sequentially on the stack, identical to `struct` fields. For example, `(coins, Point, int?)` occupies 4 stack slots: `INT (coins), INT (p.x), INT (p.y), INT/NULL`.\n\n```tolk\ntype MyTensor = (coins, Point, int?)\n\nfun demo(t: MyTensor) {\n    // t is 4 stack slots\n    val p = t.1;\n    // p is 2 stack slots\n}\n```\n\n## `tuple`\n\n- Type `tuple` is backed by TVM `TUPLE` and occupies a single stack slot, regardless of the number of elements; up to 255.\n\n## Typed tuple `[T1, T2, ...]`\n\nA typed tuple is backed by TVM `TUPLE`. Its structure is known at compile time; at runtime it is an ordinary TVM `tuple`.\n\n```tolk\nfun demo(t: [int, [int, int]]) {\n    // t is one stack slot (TVM `TUPLE`)\n    // t.0 is TVM `INT`\n    // t.1 is TVM `TUPLE`\n    return t.1.0;    // asm \"1 INDEX\" + \"0 INDEX\"\n}\n```\n\n## `map<K, V>`\n\n- `map<K, V>` occupies a single stack slot: either TVM `NULL` or `CELL`.\n- Non-empty maps, `CELL`, have [a non-trivial bit-level layout](/languages/tl-b/complex-and-non-trivial-examples#hashmap).\n\n## Callables `(...ArgsT) -> ResultT`\n\n- A callable and `continuation` is backed by TVM `CONT`.\n\n## `void`, `never`\n\n- Both represent the absence of a value and occupy zero stack slots. For example, a function with return type `void` does not place any value onto the stack.\n"
  },
  {
    "path": "languages/tolk/types/strings.mdx",
    "content": "---\ntitle: \"Strings as slices\"\nsidebarTitle: \"Strings\"\n---\n\n[TVM](/tvm/overview) does not have a dedicated string type. Instead, [slices](/languages/tolk/types/cells#slices) are used to encode string-like data.\n\n## Raw string literals\n\nString literals produce a binary slice where each character is encoded with its [ASCII](https://en.wikipedia.org/wiki/ASCII) character number:\n\n```tolk\n// `slice` with 4 bytes: 97,98,99,100 (0x61626364)\nconst SLICE1 = \"abcd\"\n```\n\nLiterals cannot exceed 127 ASCII characters because a cell can contain up to 1023 bits.\n\n## Compile-time functions\n\n[Several functions](/languages/tolk/features/standard-library#compile-time-calculations-and-embedding) operate on constant strings and string literals at compile time. The produced values are embedded in the contract as constants.\n\n```tolk\n// `int` with a CRC32 checksum\nstringCrc32(\"some_str\") // 4013618352 = 0xEF3AF4B0\n\n// `int` with a CRC16 checksum\nstringCrc16(\"some_str\") // 53407 = 0xD09F\n\n// `int` with a full SHA256 checksum\nstringSha256(\"some_crypto_key\")\n\n// `int` with first 32 bits of a SHA256 checksum\nstringSha256_32(\"some_crypto_key\")\n\n// `int` with N-chars ASCII in base 256\nstringToBase256(\"AB\") // 16706 (65*256 + 66)\n```\n\n### Embed hexadecimal data\n\nTo embed hexadecimal binary data, use `stringHexToSlice(\"...\")`:\n\n```tolk\n// `slice` with 2 bytes: 16,32 (0x1020)\nconst SLICE2 = stringHexToSlice(\"1020\")\n```\n\n### Embed human-readable address strings\n\nThe `address(\"...\")` function inserts a constant slice containing a standard internal contract address:\n\n```tolk\nconst REFUND_ADDR = address(\"EQCRDM9h4k3UJdOePPuyX40mCgA4vxge5Dc5vjBR8djbEKC5\")\n```\n\nSuch slices hold 267 bits of data and have no refs.\n\n## Concatenate string literals\n\nThere are no compile-time means to concatenate string literals. Instead, concatenation can be performed at runtime via a [builder](/languages/tolk/types/cells#builders):\n\n```tolk\nval concat: slice = beginCell()\n    .storeSlice(\"ab\")\n    .storeSlice(\"cd\")\n    .asSlice();\n```\n\n## Serialization\n\nPlain slices cannot be serialized directly: they require a fixed-width type or custom serialization rules. Similarly, string-like data must use an explicit encoding to be stored on-chain or returned from contracts.\n\n### Fixed-size strings via `bitsN`\n\nIf a string size is fixed and does not exceed 1023 bits, use fixed-size encodings: `bitsN` or `bytesN`, where `N` cannot go beyond 1023 or 127, respectively.\n\n```tolk\nstruct Response1 {\n    someData: uint8\n    str: bits32\n}\n\nfun generateResponse(): Response1 {\n    return {\n        someData: 0xFF,\n        str: \"abcd\" as bits32,\n    }\n}\n```\n\n### Snake strings\n\nFor arbitrary strings, the so-called _snake string_ or tail string encoding is often used.\n\nSnake encoding works by storing a portion of data in the current cell and storing the rest in the first ref cell, recursively. The process repeats until all the data is stored in a chain of cells.\n\nFor instance, a string `xxxxyyyyzzzz` can be split into three parts and stored as a snake string:\n\n```tolk\n\"xxxx\".ref(\"yyyy\".ref(\"zzzz\"))\n```\n\nSuch chaining can be implemented as follows:\n\n```tolk\ntype MyTailString = RemainingBitsAndRefs\n\nstruct Response2 {\n    someData: int8\n    str: MyTailString\n}\n\nfun slice.ref(self, other: slice): slice {\n    return beginCell()\n        .storeSlice(self)\n        .storeSlice(other)\n        .asSlice();\n}\n\nfun generateResponse(): Response2 {\n    return {\n        someData: 0xFF,\n        str: \"xxxx\".ref(\"yyyy\".ref(\"zzzz\")),\n    }\n}\n```\n\nThere, `MyTailString` is a type alias to `RemainingBitsAndRefs`, which is a slice that holds the [remainder of the data when read](/languages/tolk/types/cells#remaining-slice-when-reading). On-chain decoding of such strings does not require iteration over nested references.\n\n### Variable-length encoding\n\nEncoding of variable-length strings can also be implemented manually using a type alias over `slice` and its custom serializers.\n\nFor example, short strings like `\"abcd\"` can be stored as 8 bits for `N`, where `N` is the string length, followed by `N` bits of data:\n\n```tolk\ntype ShortString = slice\n\nfun ShortString.packToBuilder(self, mutate b: builder) {\n    val nBits = self.remainingBitsCount();\n    b.storeUint(nBits, 8);\n    b.storeSlice(self);\n}\n\nfun ShortString.unpackFromSlice(mutate s: slice) {\n    val nBits = s.loadUint(8);\n    return s.loadBits(nBits);\n}\n```\n\nThen, `ShortString` can be used as a regular type and enjoy auto-serialization:\n\n```tolk\nstruct Response3 {\n    someData: int8\n    str: ShortString\n}\n\nfun generateResponse(): Response3 {\n    return {\n        someData: 0xFF,\n        str: \"abcd\",\n    }\n}\n```\n"
  },
  {
    "path": "languages/tolk/types/structures.mdx",
    "content": "---\ntitle: \"Structures\"\n---\n\nTolk supports structures.\n\n```tolk\nstruct Point {\n    x: int\n    y: int\n}\n\nfun calcMaxCoord(p: Point) {\n    return p.x > p.y ? p.x : p.y\n}\n\nfun demo() {\n    // declared using object-literal syntax\n    var p: Point = { x: 10, y: 20 };\n    calcMaxCoord(p);\n\n    // constructed using object-literal syntax\n    calcMaxCoord({ x: 10, y: 20 });\n}\n```\n\n## Distinct structure types\n\nStructures with identical fields are not assignable to each other:\n\n```tolk\nstruct SomeA { v: int }\nstruct SomeB { v: int }\n\nfun acceptA(a: SomeA) {}\n\nfun demo(a: SomeA, b: SomeB) {\n    b = a;      // error, can not assign `SomeA` to `SomeB`\n    acceptA(b); // error, can not pass `SomeB` to `SomeA`\n}\n```\n\nEven though `SomeA` and `SomeB` have identical layouts, they represent distinct types.\n\n## Contextual type inference\n\nThe compiler infers types from context. In the example below, the compiler determines that `{ ... }` has type `StoredInfo` based on the parameter type:\n\n```tolk\nfun store(info: StoredInfo) {\n    // ...\n}\n\nfun demo() {\n    store({\n        counterValue: ...,\n        ownerAddress: ...,\n    });\n}\n```\n\nThe same applies to return values and assignments:\n\n```tolk\nfun loadData(): StoredInfo {\n    return {\n        counterValue: ...,\n        ownerAddress: ...,\n    }\n}\n\nfun demo() {\n    var s: StoredInfo = { counterValue, ... };\n    var s: (int, StoredInfo) = (0, { counterValue, ... });\n}\n```\n\n## Explicit type hints\n\nExplicit type hints are available. In addition to the plain `{ ... }` syntax, the form `StructName { ... }` can be used. The snippet below is equivalent to the previous example:\n\n```tolk\nfun loadData() {\n    return StoredInfo {\n        counterValue: ...,\n        ownerAddress: ...,\n    }\n}\n\nfun demo() {\n    var s = StoredInfo { counterValue, ... };\n    var s = (0, StoredInfo { counterValue, ... });\n}\n```\n\nWhen neither contextual information nor an explicit type hint is available, the type cannot be inferred and an error is produced.\n\n```tolk\nval o = { x: 10, y: 20 };    // error, what type is it?\n```\n\n## Methods\n\nMethods are declared as extension functions:\n\n```tolk\nfun Point.calcSquare(self) {\n    return self.x * self.y\n}\n```\n\nWithout `self` parameter, a [method](/languages/tolk/syntax/functions-methods) will be static. By default, `self` is immutable. The form `mutate self` enables mutation.\n\n## Serialization prefixes\n\nSerialization prefixes do not affect typing or layout. The syntax `struct (PREFIX) Name { ... }` specifies a serialization prefix. The prefix affects only the binary representation; all other aspects remain unchanged.\n\n```tolk\nstruct (0x12345678) CounterIncrement {\n    byValue: uint32\n}\n\nfun demo(inc: CounterIncrement) {\n    // `inc` has one field; the prefix is not a property\n    inc.byValue\n    // `inc` is still one TVM `INT` on the stack\n}\n```\n\n## Structure syntax\n\n[Structure syntax](/languages/tolk/syntax/structures-fields) includes:\n\n- shorthand field syntax `{ x, y }`;\n- default field values (`a: int32 = 10`);\n- `private` and `readonly` fields;\n- serialization prefixes (opcodes).\n\n## Stack layout and serialization\n\nFields are placed on the [stack](/languages/tolk/types/overall-tvm-stack) sequentially and [are serialized](/languages/tolk/types/overall-serialization) in the same order. If a struct has a prefix, it is written first.\n"
  },
  {
    "path": "languages/tolk/types/tensors.mdx",
    "content": "---\ntitle: \"Tensors\"\nsidebarTitle: \"Tensors\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nTensors represent ordered collections of values and are written in the form `(T1, T2, ...)`. They occupy multiple [TVM stack entries](/languages/tolk/types/overall-tvm-stack) sequentially and are [serialized](/languages/tolk/types/overall-serialization) in the same order. For example, `(int, slice)` represents two values following one another.\n\nTensors are anonymous [structures](/languages/tolk/types/structures) and behave identically. Large tensors are impractical — use structures whenever possible.\n\n<Aside\n  type=\"caution\"\n>\n  In many general-purpose languages, syntax `(A, B, C, ...)` is used for _tuples_, not tensors, which are a different type. However, in TON, a [tuple](/languages/tolk/types/tuples) is a distinct TVM primitive that has its own syntax `[a, b, ...]` and semantics.\n\n  For example, a tensor `(int, int, int)` represents three integers on the stack, whereas a tuple `[int, int, int]` is a single stack entry that contains three integers within itself.\n</Aside>\n\n## Component access\n\nUse `tensor.{i}` to access tensor components by their index:\n\n```tolk\n// v's type is `(int, int, builder)`\nvar v = (1, 2, beginCell())\n\n// read\nv.0 // 1\n\n// write\nv.1 = 123 // v is now (1, 123, builder \"\")\nv.2.storeInt(v.0, 16) // v is now (1, 123, builder \"0x0001\")\n\n// COMPILATION ERROR!\nv.100500\n```\n\nThis syntax also works for nested tensors:\n\n```tolk\nfun getNested(): (int, (bool, coins)) {\n    // ...\n}\n\nfun demo() {\n    val v = getNested();\n    v.1.0 // bool\n}\n```\n\n## Tensors as anonymous structures\n\nThe struct `User` below and a tensor `(int, slice)` have identical stack layouts and serialization rules:\n\n```tolk\nstruct User {\n    id: int\n    name: slice\n}\n```\n\nFurthermore, `obj.{field}` is equivalent to `tensor.{i}`:\n\n```tolk\nstruct Storage {\n    lastUpdated: int\n    owner: User\n}\n\nfun demo(s: Storage) {\n    s.lastUpdated;       // s.0\n    s.owner.id;          // s.1.0\n}\n```\n\n## Destructuring assignments\n\nThe following syntax is valid:\n\n```tolk\nvar (i, j) = (10, 20)\n```\n\nThis is a 2-component tensor `(10, 20)` assigned to two variables:\n\n```tolk\nvar tensor = (10, 20)\nvar (i, j) = tensor\n```\n\nTensors `(\"abcd\", (10, 20))` and `(\"abcd\", 10, 20)` are placed identically as three stack entries containing the values `\"abcd\"` (as a slice), `10`, and `20`, respectively. However, Tolk treats `(slice, (int, int))` and `(slice, int, int)` as distinct types.\n\n```tolk\n// This will NOT compile\nvar (str, i, j) = (\"abcd\", (10, 20))\n\n// Yet, the following code is correct\nvar (str, (i, j)) = (\"abcd\", (10, 20))\n```\n\nA special placeholder `_` can be used on the left side to discard a destructured value:\n\n```tolk\n// j = 20, 10 is discarded\nvar (_, j) = (10, 20)\n```\n\n## Empty tensors\n\nEmpty tensors are valid values:\n\n```tolk\nval empty = ()\n```\n\nThis is analogous to creating an instance of an empty struct.\n\n<Aside type=\"note\">\n  In some programming languages, an empty value is known as _unit_, and functions that don’t return a value can be said to \"return a unit\". Tolk uses a special type called `void` for this purpose.\n\n  The `void` type is not compatible with empty tensors, despite both indicating the absence of a value.\n</Aside>\n"
  },
  {
    "path": "languages/tolk/types/tuples.mdx",
    "content": "---\ntitle: \"Tuples\"\nsidebarTitle: \"Tuples\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nIn [TVM](/tvm/overview), a tuple in the form `[T1, T2, ..., T255]` is a dynamic container that stores from 0 to 255 elements in a [single stack slot](/languages/tolk/types/overall-tvm-stack). Tuples cannot be [serialized to cells](/languages/tolk/types/overall-serialization) and are only present on the stack during [the compute phase](/foundations/phases). Yet they may be returned from get methods because contract getters operate directly on the stack.\n\nTolk supports two tuple types:\n\n- `tuple` — an opaque dynamic tuple with unknown shape;\n- `[T1, T2, ...]` — a typed tuple with a known shape.\n\n<Aside\n  type=\"caution\"\n>\n  In many general-purpose languages, syntax `[A, B, C, ...]` is used for array or list literals, while syntax `(A, B, C, ...)` is used for tuples. However, in TON, there are no arrays or lists. Tuple literals use the `[A, B, C, ...]` syntax, while `(A, B, C, ...)` is used by [tensors](/languages/tolk/types/tensors): a distinct type that represents ordered collections of values that occupy multiple TVM stack entries.\n\n  For example, a tuple `[int, int, int]` is a single stack entry containing three integers. In contrast, a tensor `(int, int, int)` signifies three separate integers that occupy individual stack entries or are serialized sequentially.\n</Aside>\n\n## Dynamic tuples\n\nA `tuple` stores from 0 to 255 elements in one stack slot:\n\n```tolk\nvar t: tuple = createEmptyTuple();\nt.push(10);\nt.push(beginCell());\nt.push(null);\n\nt.size(); // 3\n```\n\n## Typed tuples\n\nUse `[T1, T2, ...]` to describe a tuple with a known shape, with non-primitive values not permitted:\n\n```tolk\n// The type is `[int, int, builder]`\nval t = [1, 2, beginCell()];\n\n// Read\nt.0; // 1\n\n// Write\nt.1 = 123;\nt.2.storeInt(t.0, 16);\n\n// t is now [1, 123, builder \"0x0001\"]\nt.100500 // compilation error!\n```\n\nA typed tuple may be destructured into multiple variables:\n\n```tolk\nfun sumFirstTwo(t: [int, int, builder]) {\n    val [first, second, _] = t;\n    return first + second;\n}\n```\n\n## Component access\n\nThe `get()` method accesses a value by an index. When calling it on opaque dynamic tuples, explicitly provide a type of the retrieved value or rely on the compiler's type inference:\n\n```tolk\n// Explicit int type\nval first = t.get<int>(0);\n\n// Type inference based on desired variable type\nval first: int = t.get(0);\n```\n\nThe syntax `tuple.{i}` is permitted when the type is evident:\n\n```tolk\nval first: int = t.0;\n```\n\nThe `set()` method writes a new value at an index. It does not create new elements — instead, it overrides existing ones.\n\n```tolk\nval t = [1, 7];\n\n// t is now [42, 7]\nt.set(0, 42);\n```\n\nIf index is out of bounds in `get()` or `set()`, an exception is thrown:\n\n```tolk\nt.set(value, 100500);    // throws errCode=5\nt.100500 = value;        // throws errCode=5\n```\n\n<Aside type=\"note\">\n  Accessing a tuple value takes a single TVM instruction, whereas accessing a [tensor](/languages/tolk/types/tensors) value requires stack shuffling.\n</Aside>\n\nAdditional methods such as `last()`, `pop()`, and others are [available in the standard library](/languages/tolk/features/standard-library#tuples).\n\n## Allowed values\n\nConsider the following structure:\n\n```tolk\nstruct Point3d {\n    x: int\n    y: int\n    z: int\n}\n```\n\nAn attempt to call `t.push(somePoint)` where `somePoint` is an instance of that structure raises an error — values that take more than one stack slot cannot be placed in a tuple. That is, only [primitive, atomic types](/languages/tolk/types/list-of-types) can be set:\n\n```tolk\nt.push(somePoint.x);  // ok (int)\nt.push(somePoint);    // error\n```\n\n## Conversion to and from composites\n\nFor composite types, there are generic built-in methods `T.toTuple()` and `T.fromTuple()` which convert composites to and from tuples. Length of the resulting tuple is equal to the number of stack slots occupies by a value of the converted type: if it occupies N stack slots, the resulting tuple has size N.\n\n```tolk\nstruct Point3d {\n    x: int\n    y: int\n    z: int\n}\n\nfun demo(p: Point3d) {\n    val t = p.toTuple();       // a tuple with 3 elements\n    t.get<int>(2);             // z\n    p = Point3d.fromTuple(t);  // back to a struct\n}\n```\n\n## Lisp-style lists\n\nLisp-style lists in Tolk are nested two-element tuples. For instance, `[1, [2, [3, null]]]` represents the list `[1, 2, 3]`. An empty list is conventionally represented as `null`. From the type system perspective, a Lisp-style list is a `tuple?` with dynamic contents.\n\nProcess such lists using the following standard library module:\n\n```tolk\nimport \"@stdlib/lisp-lists\"\n```\n\nLisp-style lists allow storing and manipulating more than 255 elements, but they do not have fast element access. If there is a clear upper bound on the number of elements, use [maps](/languages/tolk/types/maps) instead. Otherwise, prefer [contract sharding](/contract-dev/contract-sharding).\n"
  },
  {
    "path": "languages/tolk/types/type-checks-and-casts.mdx",
    "content": "---\ntitle: \"Type checks and casts\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nTolk supports type conversions: either automatic or explicit via the `as` operator.\n\n## Automatic conversions\n\nAssignable types can be provided explicitly:\n\n```tolk\nfun takeOptInt(v: int?) {}\n\nfun main() {\n    takeOptInt(100);    // ok, `int` to `int?`\n    takeOptInt(null);   // ok, `null` to `int?`\n}\n```\n\nCertain conversions are automatic:\n\n- `int` to `intN`.\n- `AliasForT` and `T` (bidirectional).\n- `Cell<T>` to `cell`.\n\n```tolk\nfun autocast() {\n    var number: int32 = 100;   // auto cast `int` to `int32`\n}\n```\n\nNon-assignable types cause a compilation error:\n\n```tolk\nfun main() {\n    var number: int = true;\n}\n/// file.tolk:2:23: error: can not assign `bool` to variable of type `int`\n///            hint: use `as` operator for UNSAFE casting: `<some_expr> as int`\n///\n///     // in function `main`\n///    2 |     var number: int = true;\n///      |                       ^^^^\n```\n\n## Smart casts\n\nOnce a variable is checked, the compiler narrows its type. For instance, if a variable [could be `null`](/languages/tolk/types/nullable) before the check, and the condition is confirmed to be true, the variable's type will not allow `null` in the true block anymore.\n\n```tolk\nif (lastCell != null) {\n    // here lastCell is `cell`, not `cell?`\n}\n```\n\n## Operator `is` for union types\n\nGiven a [union type](/languages/tolk/types/unions) `T1 | T2 | ...`, the `is` operator performs a runtime type test, narrowing the type.\n\n```tolk\nfun demo(v: int | Point | cell) {\n    if (v is Point) {\n        return v.x + v.y;\n    }\n    // v is `int | cell` here\n}\n```\n\n## Non-null assertion with operator `!`\n\nThe `!` operator bypasses the compiler's nullability check. It is similar to `!` in TypeScript and `!!` in Kotlin.\n\n```tolk\nfun doSmth(c: cell) {}\n\nfun analyzeStorage(nCells: int, lastCell: cell?) {\n    // Say, according to the logic of this program,\n    // having non-zero number of `nCells` must mean\n    // that the `lastCell` is not `null`\n    if (nCells) {\n        // Therefore, one can explicitly instruct\n        // the compiler to recognize that fact\n        doSmth(lastCell!);\n    }\n}\n```\n\n## Unsafe cast with operator `as`\n\nWhen non-trivial type transformations are required, the `as` operator overrides the restrictions by performing an unsafe type cast.\n\nFor instance, `bool` cannot be assigned directly to `int`. However, a direct cast using the `as` operator is valid since booleans are represented as [TVM](/tvm/overview) integers: `true` is -1, and `false` is 0.\n\n```tolk\nvar number: int = true as int; // -1\n```\n\n<Aside\n  type=\"caution\"\n>\n  The `as` operator skips type checking and performs no validation at runtime — it is purely a compile-time type cast.\n\n  This can lead to sudden errors and hidden bugs. For example, if one cast a slice as `address` and that slice did not hold a valid address, subsequent program becomes undefined and may error whenever that new \"address\" is used.\n</Aside>\n\nNot all transformations are possible. For example, `42 as cell` is invalid. When a cast is inappropriate, the compiler indicates this in diagnostic messages.\n\nThe `as` operator converts types that share the same TVM representation:\n\n- `address` is a TVM slice, so `someAddr as slice` is valid.\n  - Conversely, `someSlice as address` is valid.\n- `bitsN`, where `N` is between 1 and 1023, is a TVM slice, so `someSlice as bitsN` is valid.\n- `intN`, where `N` is between 1 and 257, is a TVM integer, so `someInt64 as int32` is valid.\n- `bool` is as TVM integer, so `someBool as int` and `someBool as int32` result in -1 or 0.\n- Enums are TVM integers, so `someColor as int` is valid.\n\nFinally, the `as` operator cannot be applied to unions: `v as Point` is incorrect. Use the `is` operator and smart casts.\n"
  },
  {
    "path": "languages/tolk/types/unions.mdx",
    "content": "---\ntitle: \"Union types\"\n---\n\nTolk supports union types such as `T1 | T2 | T3`.\n\nA union type represents a value that can be one of several types. [Pattern matching](/languages/tolk/syntax/pattern-matching) is used to distinguish union variants. A special case `T | null` is written as `T?` and referred to as a [nullable type](/languages/tolk/types/nullable).\n\n```tolk\nstruct (0x12345678) Increment { /* ... */ }\nstruct (0x23456789) Reset { /* ... */ }\n\ntype IncomingMsg = Increment | Reset\n\nfun handle(m: IncomingMsg) {\n    match (m) {\n        Increment => { /* here m is `Increment` */ }\n        Reset =>     { /* here m is `Reset` */     }\n    }\n}\n```\n\n## Arbitrary union types\n\nUnion types are not limited to structures. Any types can be combined into a union. The following union types are valid:\n\n- `int | slice`;\n- `address | Point | null`;\n- `Increment | Reset | coins`;\n- `int8 | int16 | int32 | int64`.\n\nUnion types are automatically flattened:\n\n```tolk\ntype Int8Or16 = int8 | int16\n\nstruct Demo {\n    t1: Int8Or16 | int32?   // int8 | int16 | int32 | null\n    t2: int | int           // int\n}\n```\n\nUnion types support assignment based on subtype relations. For example, a value of type `B | C` can be passed to or assigned to `A | B | C | D`:\n\n```tolk\nfun take(v: bits2 | bits4 | bits8 | bits16) {}\n\nfun demo() {\n    take(someSlice as bits4);    // ok\n    take(anotherV);              // ok for `bits2 | bits16`\n}\n```\n\n## Exhaustive pattern matching\n\nA `match` expression must cover all possible cases. It must be exhaustive.\n\n```tolk\nfun errDemo(v: int | slice | Point) {\n    match (v) {\n        slice => { v.loadAddress() }\n        int => { v * 2 }\n        // error: missing `Point`\n    }\n}\n```\n\n`match` can be used with nullable types, since `T?` is equivalent to `T | null`. It can also be used as an expression:\n\n```tolk\nfun replaceNullWith0(maybeInt: int?): int {\n    return match (maybeInt) {\n        null => 0,\n        int => maybeInt,\n    }\n}\n```\n\n## Union type inference errors\n\nAuto-inference of a union type results in an error. If `match` arms produce values of different types, the inferred result is a union, which is typically not intended:\n\n```tolk\nvar a = match (...) {\n    ... => beginCell(),\n    ... => 123,\n};\n```\n\nThe type of `a` is inferred as `builder | int`. In most cases, this indicates an error in the code. In such cases, the compiler emits the following message:\n\n```ansi\nerror: type of `match` was inferred as `builder | int`; probably, it's not what you expected\nassign it to a variable `var a: <type> = match (...) { ... }` manually\n```\n\nTo resolve this, either explicitly declare `a` as a union type or fix the code if the union is unintended.\n\nThe same rule applies to other cases, such as return type inference:\n\n```tolk\nfun f() {\n    if (...) { return someInt64 }\n    else { return someInt32 }\n}\n```\n\nThe result is inferred as `int32 | int64`. While it is valid, a single integer type is usually expected. The compiler reports an error. To fix it, explicitly declare the return type:\n\n```tolk\nfun f(): int {\n    if (...) { return someInt64 }\n    else { return someInt32 }\n}\n```\n\nDeclaring return types is recommended practice.\n\n## `is` and `!is` operators\n\nUnion types can be tested using the `is` operator:\n\n```tolk\nfun demo(v: A | B) {\n    if (v is A) {\n        v.aMethod();\n    } else {\n        v.bMethod();\n    }\n}\n```\n\n## `lazy` matching for unions\n\nIn [message-handling](/languages/tolk/features/message-handling), union values are commonly parsed using `lazy`:\n\n```tolk\nfun onInternalMessage(in: InMessage) {\n    val msg = lazy MyUnion.fromSlice(in.body);\n    match (msg) {\n        // ...\n    }\n}\n```\n\nThis pattern is referred to as [`lazy` match](/languages/tolk/features/lazy-loading):\n\n1. No union is allocated on the stack upfront; loading is deferred until needed.\n1. `match` operates by inspecting the slice prefix (opcode), instead of checking a type identifier on the stack.\n\nUnion types continue to work correctly without `lazy` and follow the same type-system rules.\n\n## Stack layout and serialization\n\nUnion types have a complex [stack layout](/languages/tolk/types/overall-tvm-stack), commonly referred to as tagged unions.\n\n[Serialization](/languages/tolk/types/overall-serialization) depends on whether the union consists of structures with manual serialization prefixes:\n\n- if yes; for example, `struct (0x1234) A`, those prefixes are used;\n- if no, the compiler automatically generates a prefix tree; for example, `T1 | T2` is called `Either` type: `0` + `T1` or `1` + `T2`.\n"
  },
  {
    "path": "languages/tolk/types/void-never.mdx",
    "content": "---\ntitle: \"Void and never types\"\nsidebarTitle: \"Void and never\"\n---\n\nTolk provides the types `void` and `never`, which both describe the absence of a value, but with different semantics.\n\n## `void`\n\nA function that returns nothing is `void`. Both functions below return `void`:\n\n```tolk\nfun demo1() {\n    debug.print(globalVar);\n}\n\nfun demo2() {\n    if (random.uint256() == 0) {\n        return;\n    }\n    globalVar = 123;\n}\n```\n\nWhen a function return type is not specified, it is inferred from the return statements. A `return` without a value indicates a `void` return type.\n\nExplicitly specifying `fun(...): void` behaves identically:\n\n```tolk\nfun demo1(): void {\n    // ...\n}\n```\n\n### `void`-typed fields\n\nA structure field with type `void` is treated as non-existent. This pattern is used with generics such as `<T = void>` to model optional fields in structure types.\n\n```tolk\nstruct WithOptionalField<T> {\n    a: int\n    b: T\n    c: slice\n}\n\ntype OnlyAC = WithOptionalField<void>\n\nfun demo() {\n    // field `b` may be omitted\n    val v: OnlyAC = { a: 10, c: \"\" };\n}\n```\n\n## `never`\n\nA function that never returns is `never`. A function whose execution always terminates by throwing an error has return type `never`:\n\n```tolk\nfun accessDenied(): never {\n    throw 403\n}\n\nfun validate(userId: int) {\n    if (userId > 0) {\n        return userId;\n    }\n    accessDenied();\n    // no `return` statement is needed\n}\n```\n\nIn a `match` expression, branches that do not return are inferred as `never`:\n\n```tolk\nval result = match (ownerKey) {\n    ADMIN_KEY => true,     // `bool`\n    else => throw 403,     // `never`\n};\n// result is `bool`\n```\n\n### Implicit `never` in unreachable branches\n\nThe type `never` represents values that cannot exist. It occurs implicitly in branches that the type system can prove to be unreachable.\n\nHere, the condition cannot be satisfied:\n\n```tolk\nfun demo(v: int | slice) {\n    if (v is builder) {\n        // v is `never`\n    }\n}\n```\n\nAnother case arises when a non-nullable type is checked against `null`:\n\n```tolk\nfun demo(v: int) {\n    if (v == null) {\n        // v is `never`\n        v + 10;   // error, can not apply `+` `never` and `int`\n    }\n    // v is `int` again\n}\n```\n\nEncountering `never` in a compilation error typically indicates an issue in the preceding code.\n\n## Stack layout and serialization\n\nBoth `void` and `never` represent the absence of a value. At the TVM level, neither type produces a value on the stack and occupies zero stack slots and zero bits. For example, a function with return type `void` does not place any value onto the [stack](/languages/tolk/types/overall-tvm-stack).\n"
  },
  {
    "path": "more-tutorials.mdx",
    "content": "---\ntitle: \"Other resources\"\n---\n\nThis page collects additional learning resources beyond this documentation. You'll find a mix of official content not hosted in this documentation and community-created materials to help you continue your journey.\n\nWhether you prefer structured courses, in-depth articles, video tutorials, or real code examples, there is something here to match your learning style and current skill level.\n\n## Courses\n\n### Blockchain basics with TON\n\n<Badge color=\"red\">Deprecated</Badge>\n\nThis course introduces blockchain basics, focusing on practical skills in the TON ecosystem. You will understand how blockchain functions and its diverse applications.\n\nThis course is for junior developers, people new to crypto, non-technical IT professionals, and anyone curious about blockchains.\n\n- [English](https://stepik.org/course/201294/promo)\n- [Chinese](https://stepik.org/course/200976/promo)\n- [Russian](https://stepik.org/course/202221/promo)\n\n### TON & Telegram Blockchain development\n\n<Badge color=\"red\">Deprecated</Badge>\n\nThe course is aimed at developers and IT specialists interested in gaining practical knowledge about the technologies and concepts of the TON Blockchain, such as FunC, dApps, decentralization, smart contracts, contract testing, as well as the creation of Mini Apps within Telegram.\n\n- [English](https://stepik.org/course/176754/promo)\n- [Chinese](https://stepik.org/course/201638/promo)\n- [Russian](https://stepik.org/course/201855/promo)\n\n## Articles\n\nIntroductory:\n\n- [How a Blockchain Can Help You on a Deserted Island](https://talkol.medium.com/why-decentralized-consensus-blockchain-is-good-for-business-5ff263468210)\n\nBeginner-friendly:\n\n- [What is Blockchain? What is a Smart Contract? What is Gas?](https://blog.ton.org/what_is_blockchain)\n\n### \"Hello World\" guide series\n\nA step-by-step tutorial series that starts with creating a new TON wallet and ends with a working, test-covered, and deployed smart contract, along with a Telegram Mini App frontend for it.\n\n- [Part 1: Working with your first TON wallet](https://helloworld.tonstudio.io/01-wallet/)\n- [Part 2: Writing your first smart contract](https://helloworld.tonstudio.io/02-contract/)\n- [Part 3: Building your first web client](https://helloworld.tonstudio.io/03-client/)\n- [Part 4: Testing your first smart contract](https://helloworld.tonstudio.io/04-testing/)\n\n## Videos\n\nIntroductory:\n\n- [Crypto Networks and Why They Matter](https://www.youtube.com/watch?v=2wxtiNgXBaU)\n\n### Playlists\n\nBeginner-friendly:\n\n- [TON Development with Tact](https://www.youtube.com/watch?v=Vf3Fx7qgL6k\\&list=PLQ5rEj25H3U2P5qp7nsgVtNGYxEojnnez)\n\n{/* NOTE: ## Podcasts */}\n\n## Interactive learning\n\n### Code playgrounds\n\n- [TxTracer](https://txtracer.ton.org/) - Trace and analyze TON Blockchain transactions with tools to visualize execution, inspect and debug smart contracts with a code editor and user-friendly interface.\n- [Assembly Playground](https://txtracer.ton.org/play/) - Experiment with TVM assembly code directly in your browser. Write, test, and debug assembly instructions with real-time execution.\n- [Code Explorer](https://txtracer.ton.org/code-explorer/) - Compile FunC or Tolk code to assembly and explore the generated bytecode to understand how your smart contracts work under the hood.\n- [TVM Instruction table](https://txtracer.ton.org/spec/) - Browse the TVM instruction reference with detailed descriptions, opcodes, stack effects, and control flow information for every instruction.\n- [Sandbox](https://txtracer.ton.org/sandbox/) - Inspect transactions produced by your local tests using the `@ton/sandbox` package. Visualize messages, transaction info, VM logs and exit codes with an interactive UI.\n\n{/* NOTE: ### Tours */}\n\n### Challenges and exercises\n\n- [Hack the TON](https://www.hacktheton.com/en) - TON-based wargame inspired by The Ethernaut, played in the TON Virtual Machine. Each level is a smart contract that needs to be hacked. Our goal is to help you to learn how to develop safe TON smart contracts and build a thriving community around this craft.\n\n## Smart contract examples\n\nExamples of smart contracts on TON include wallets, electors (which manage validator elections on TON), multi-signature wallets, and many more. They can serve as an excellent reference for those studying on real projects.\n\n- [Tolk benchmark contracts](https://github.com/ton-blockchain/tolk-bench) - Tolk vs. FunC gas benchmarks and, simultaneously, reference Tolk contracts.\n\n## Join the community\n\n- [All TON communities](https://ton.org/en/community)\n- [Telegram Dev chats](https://t.me/addlist/1r5Vcb8eljk5Yzcy)\n"
  },
  {
    "path": "old.mdx",
    "content": "---\ntitle: \"Old documentation\"\nurl: \"https://old-docs.ton.org/\"\n---\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"ton-docs\",\n  \"private\": true,\n  \"scripts\": {\n    \"start\": \"npx mint dev\",\n    \"start:no-open\": \"mint dev --no-open\",\n    \"check:openapi\": \"mint openapi-check ecosystem/api/toncenter/v2.json && mint openapi-check ecosystem/api/toncenter/v3.yaml\",\n    \"check:links\": \"mint broken-links\",\n    \"check:redirects\": \"node scripts/check-redirects.mjs\",\n    \"check:navigation\": \"node scripts/check-navigation.mjs\",\n    \"check:fs\": \"echo 'https://github.com/ton-org/docs/issues/1182'\",\n    \"check:fmt\": \"remark . -e mdx,md --no-stdout --quiet --frail\",\n    \"check:fmt:some\": \"remark --no-stdout --quiet --frail --silently-ignore\",\n    \"check:spell\": \"cspell --no-progress --show-suggestions .\",\n    \"check:all\": \"npm run check:openapi && npm run check:links && npm run check:redirects && npm run check:fs && npm run check:fmt && npm run check:spell\",\n    \"fmt\": \"remark . -e mdx,md -o --silent\",\n    \"fmt:some\": \"remark -o --silent --silently-ignore\",\n    \"spell\": \"cspell lint --no-progress --show-suggestions .\",\n    \"spell:some\": \"cspell lint\",\n    \"lint:all\": \"npm run check:all\",\n    \"gen:mdx-for-openapi:toncenter-v2\": \"npx @mintlify/scraping@latest openapi-file -w ecosystem/api/toncenter/v2.json -o ecosystem/api/toncenter/v2\",\n    \"gen:mdx-for-openapi:toncenter-v3\": \"npx @mintlify/scraping@latest openapi-file -w ecosystem/api/toncenter/v3.yaml -o ecosystem/api/toncenter/v3\",\n    \"stats\": \"python3 scripts/stats.py\",\n    \"prepare\": \"husky\"\n  },\n  \"dependencies\": {\n    \"astring\": \"=1.9.0\",\n    \"cspell\": \"^9.7.0\",\n    \"husky\": \"^9.1.7\",\n    \"mint\": \"^4.2.446\",\n    \"remark\": \"^15.0.1\",\n    \"remark-cli\": \"^12.0.1\",\n    \"remark-frontmatter\": \"^5.0.0\",\n    \"remark-gfm\": \"^4.0.1\",\n    \"remark-math\": \"^6.0.0\",\n    \"remark-mdx\": \"^3.1.1\",\n    \"string-width\": \"=8.1.0\",\n    \"unified-consistency\": \"=2.0.0\",\n    \"unist-util-visit-parents\": \"^6.0.2\"\n  },\n  \"engines\": {\n    \"node\": \">=20.17\",\n    \"npm\": \">=9\"\n  },\n  \"packageManager\": \"npm@9.9.4\"\n}\n"
  },
  {
    "path": "payments/jettons.mdx",
    "content": "---\ntitle: \"Jettons payments processing\"\nsidebarTitle: \"Jettons\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\n\nProcessing jetton payments requires understanding TON's sharded token architecture. Unlike single-contract token systems, each jetton type consists of a master contract and individual wallet contracts for each holder.\n\n<Aside type=\"note\">\n  Jettons are fungible tokens on TON. Each jetton has a master contract (minter) and separate wallet contracts for every holder. Read more in [How Jettons Work](/standard/tokens/jettons/how-it-works).\n</Aside>\n\n<Aside\n  type=\"caution\"\n>\n  Jetton processing is security-critical. Incorrect validation of jetton wallet addresses or transfer notifications can lead to accepting fake tokens or crediting wrong amounts.\n</Aside>\n\n## Key concepts\n\nBefore implementing jetton payment processing, understand these core concepts:\n\n**Jetton architecture**: Each jetton type has one master contract that stores metadata and total supply. Each address holding the jetton has a separate jetton wallet contract at a deterministic address derived from the master contract and owner address.\n\n**Transfer flow**: Jetton transfers involve multiple messages. A user sends a `transfer` message to their jetton wallet, which sends an `internal_transfer` to the recipient's jetton wallet, which then sends a `transfer_notification` to the recipient's address if `forward_ton_amount > 0`.\n\n<Aside\n  type=\"caution\"\n>\n  Jetton transfers are considered successful only when the recipient receives `transfer_notification`. Services must set `forward_ton_amount` to at least 0.000000001 TON (1 nanoton) when sending tokens to trigger notifications. Without this, transfers won't be compliant and may not be processed by exchanges and other services.\n</Aside>\n\n**Security model**: Always validate that jetton wallets belong to the expected master contract. Anyone can deploy fake jetton wallet contracts with arbitrary balances.\n\nThis article covers processing jetton deposits using transfer notifications. All approaches require maintaining an allowlist of trusted jetton master contracts.\n\nFor architectural patterns and deposit methods comparison, see [Toncoin processing](/payments/toncoin).\n\n## Processing deposits\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  Skipping any validation step or changing their order can lead to incorrect deposit processing and potential loss of funds.\n</Aside>\n\n### Setup\n\nProcessing jetton deposits requires:\n\n- **Allowlist of trusted jetton masters**: List of jetton master contract addresses to accept\n- **Deposit wallet address**: Service wallet (e.g., wallet v4 or v5)\n\n### Initial configuration\n\n1. For each allowlisted jetton master, derive the jetton wallet address for the deposit wallet using the master contract's `get_wallet_address()` method\n1. Store the mapping of `jetton master` → `jetton wallet` → `deposit wallet` in the database\n1. Begin monitoring transactions to the deposit wallet address\n\n### Processing incoming transactions\n\nWhen a transaction arrives at the deposit wallet:\n\n1. Check that `tx.in_msg.source` matches a known jetton wallet for this deposit wallet\n1. Verify the master → jetton wallet relationship:\n   - Call `get_wallet_address(deposit-wallet)` on the master contract\n   - Confirm the returned address matches the sender\n1. Verify there are no outgoing messages (`tx.out_msgs.length === 0`)\n1. Parse the message body:\n   - Check the opcode (first 32 bits of `tx.in_msg.body`) equals `0x7362d09c` (transfer\\_notification)\n   - Extract `query_id`, `amount`, `sender`, and `forward_payload` [according to TL-B](/standard/tokens/jettons/api)\n1. Verify the amount matches the expected value\n\n### Crediting user accounts\n\nAfter validation, extract deposit information:\n\n- For [invoice-based deposits][inv-dep]: Parse the invoice ID from `forward_payload`, match it against the database, and credit the corresponding user account.\n- For [address-based deposits][add-dep]: Match the `deposit-wallet` address against the database and credit the user account.\n\n<Aside type=\"note\">\n  Not production-ready code, use only for educational purposes:\n\n  - [Invoice-based jetton deposits][inv-dep]\n  - [Unique address jetton deposits][add-dep]\n</Aside>\n\n[inv-dep]: https://github.com/ton-org/docs-examples/blob/jetton-processing-only/guidebook/jetton-processing/src/deposits/jetton-invoices.ts\n[add-dep]: https://github.com/ton-org/docs-examples/blob/jetton-processing-only/guidebook/jetton-processing/src/deposits/jetton-unique-addresses.ts\n\n## Security considerations\n\n### Master-wallet verification\n\nNever trust jetton wallet addresses without verification. Always perform these checks:\n\n1. Get the jetton master address from the allowlist\n1. Call `jetton_master.get_wallet_address(owner_address)`\n1. Verify the returned address matches the jetton wallet that sent the notification\n\n### Transfer notification validation\n\nWhen processing deposits via `transfer_notification`:\n\n- Verify the opcode is exactly `0x7362d09c`\n- Check the sender address is an expected jetton wallet\n- Extract `amount` in base units (not decimal)\n- Validate the `sender` field against expected user addresses\n- Parse `forward_payload` carefully—it may be malformed\n- Check for bounce indicators (single outgoing message back to sender)\n\n### Fake jetton detection\n\nAttackers can deploy jettons with identical names, symbols, and images:\n\n- Always verify the jetton master address against the allowlist\n- Never trust metadata (name, symbol, image) for authentication\n- Display the master contract address in admin interfaces\n- Implement a manual approval workflow for adding new jettons\n\n## Common attack patterns\n\n### Fake jetton wallets\n\n**Attack**: Attacker deploys a contract claiming to be a jetton wallet with an inflated balance.\n\n**Mitigation**: Verify the master-wallet relationship by calling `get_wallet_address()` on the master contract.\n\n### Invoice ID reuse\n\n**Attack**: User attempts to reuse a settled invoice identifier.\n\n**Mitigation**: Mark invoices as used after the first successful deposit.\n\n### Master contract spoofing\n\n**Attack**: Deploying a fake master contract that validates the attacker's fake jetton wallets.\n\n**Mitigation**: Maintain a strict allowlist of trusted master contracts and verify all jetton wallets against it.\n\n## Implementation checklist\n\nBefore enabling jetton processing in production:\n\n### Testing\n\n1. Deploy and test on testnet with real user scenarios\n1. Verify master-wallet relationships for all allowlisted jettons\n1. Test with fake jetton wallets to confirm rejection\n1. Validate transfer notification parsing with various payload formats\n1. Test bounce detection and handling\n1. Test invoice ID collision and reuse scenarios\n1. Test full flow: deposit → credit → withdrawal → confirmation\n"
  },
  {
    "path": "payments/overview.mdx",
    "content": "---\ntitle: \"Payment processing overview\"\nsidebarTitle: \"Overview\"\n---\n\nPayment processing on TON refers to monitoring and handling blockchain transactions for business applications. While simple use cases can rely entirely on smart contracts, most real-world payment systems require off-chain processing to track deposits, manage user balances, send confirmations, and integrate with existing business logic.\n\n## On-chain vs off-chain processing\n\nOn-chain processing executes all payment logic within smart contracts. When a user sends TON or Jettons to a contract, the contract immediately processes the payment and updates state. This works for simple scenarios like direct peer-to-peer transfers or automated market makers, but becomes impractical when you need user accounts, payment history, refunds, or integration with external systems.\n\nOff-chain processing monitors blockchain state changes from outside the network. Your application observes transactions, verifies their validity, updates internal databases, and triggers business logic. Exchanges, merchants, and payment processors use this approach because it provides flexibility to implement complex workflows, maintain user data, and integrate with traditional systems.\n\n## Transaction finality\n\nTON achieves transaction [finality](https://en.wikipedia.org/wiki/Blockchain#Finality) after a single masterchain block confirmation, typically within 5 seconds. Once a transaction from a shardchain appears in a masterchain block, it becomes irreversible. This differs from blockchains like Ethereum where merchants wait for multiple confirmations (usually 12-15 blocks, taking 2-3 minutes) or Bitcoin where 6 confirmations are standard (about 60 minutes).\n\nThe masterchain coordinates all workchain activity and produces blocks approximately every 5 seconds. When monitoring payments, you need to verify that the transaction was included in a masterchain block rather than just in a shardchain. Most TON APIs provide methods to check whether a transaction has achieved masterchain finality or, better yet, only consider transaction included in masterchain as finalized by the network.\n\n## Supported assets\n\nTON supports several asset types for payment processing:\n\n**Toncoin** is the native currency of the network. Every wallet can receive Toncoin directly without additional setup. Transfers are simple value transfers between addresses, making Toncoin the easiest asset to process.\n\n[**Jettons**](/standard/tokens/jettons/overview) are fungible tokens following the TON Enhancement Proposal 74 (TEP-74) standard. Each Jetton type has a master contract and individual wallet contracts for each holder. When processing Jetton payments, you monitor the Jetton wallet contract associated with your deposit address. Transfer notifications include sender information and transfer amounts.\n\nRead more about [how Jettons work](/standard/tokens/jettons/how-it-works).\n\n- [Toncoin processing](/payments/toncoin)\n- [Jetton processing](/payments/jettons)\n\n## Implementation approaches\n\nThree main approaches exist for implementing payment processing on TON:\n\n**Self-built solution**: You run your own service that connects to some TON API or [liteserver](/ecosystem/api/overview), monitors blocks for relevant transactions, and maintains a database of payment events. This requires building infrastructure to fetch blocks, parse transactions, handle reconnections, and manage state. The advantage is complete control over the implementation and no dependency on external services. The disadvantage is significant development and maintenance effort.\n\n**Self-hosted payment processor**: Open-source payment processors like [Bicycle](https://github.com/gobicycle/bicycle) and [Spice harvester](https://github.com/txsociety/spice-harvester) provide ready-to-deploy solutions that handle blockchain monitoring and expose APIs for your application. You deploy the processor on your infrastructure, configure it for your wallet addresses and asset types, and consume its API to track payments. This balances control with reduced development effort, though you still manage the infrastructure.\n\n**Third-party payment processor**: External services handle all blockchain interaction and provide simple APIs or webhooks for payment notifications. You integrate their SDK or API, and they manage infrastructure, monitoring, and maintenance. This is fastest to implement but introduces dependency on the service provider and typically involves transaction fees.\n\nThe choice depends on your requirements for control, development resources, and operational complexity. High-volume applications often build custom solutions, while smaller merchants prefer third-party services.\n\n## Monitoring payments\n\nPayment monitoring requires polling for new blocks and filtering transactions that affect your addresses. For Toncoin, you check for incoming messages to your wallet address. For Jettons, you monitor the Jetton wallet contract associated with your address for transfer notifications.\n\nThe typical monitoring flow involves fetching the latest workchain blocks, retrieving all transactions from them, filtering for transactions involving your addresses, parsing transaction data to extract amounts and metadata, verifying the transaction reached finality, and updating your internal payment records.\n\nMost applications poll for new blocks every few seconds. More sophisticated systems use multiple strategies: polling for recent data, webhooks from indexing services for real-time notifications, and periodic reconciliation to catch any missed transactions.\n"
  },
  {
    "path": "payments/toncoin.mdx",
    "content": "---\ntitle: \"Toncoin payments processing\"\nsidebarTitle: \"Toncoin\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\n\nProcessing Toncoin payments requires choosing between two architectural approaches:\n\n- invoice-based deposits to a single address, common to all users\n- unique deposit addresses per user.\n\n<Aside type=\"tip\">\n  Wallets in Ton are smart-contracts, not external accounts [like in Ethereum](/from-ethereum#account-model). Each wallet has its own address, code, and storage. Deposits are incoming messages to these wallet contracts.\n</Aside>\n\n<Aside\n  type=\"caution\"\n>\n  Do not send funds to a wallet address that you cannot initialize. Derive addresses deterministically based on contracts [initial state](/foundations/addresses/overview).\n</Aside>\n\n## Deposit methods comparison\n\n**Invoice-based flow**\n\n```mermaid\ngraph LR\n  U1[User A] -- invoice UUID --> SW[Shared Wallet]\n  U2[User B] -- invoice UUID --> SW\n  SW --> EX[Exchange Ledger]\n```\n\n**Unique deposit address flow**\n\n```mermaid\ngraph LR\n  U1[User A] --> W1[Wallet A]\n  W1 --> EX[Exchange Ledger]\n  U2[User B] --> W2[Wallet B]\n  W2 --> EX\n```\n\n**Comparison table**\n\n| Criteria                     | Invoice-based deposits                                                                                      | Unique deposit addresses                                                                 |\n| ---------------------------- | ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |\n| Security exposure            | One shared hot wallet; a key leak drains the full pool                                                      | Each wallet isolates funds; compromise affects only the impacted user                    |\n| User input requirements      | User must include an invoice ID comment; missing or malformed comments need manual recovery workflows       | User only needs the destination address                                                  |\n| Parsing and validation       | Backend parses comments on every deposit and matches to invoices                                            | No parsing; deposit attribution is address-based                                         |\n| Deployment and storage costs | Deploy and maintain a single wallet; [storage rent](/foundations/fees#storage-fee) limited to that contract | Deploy many wallets; storage rent and deployment gas scale with user count               |\n| Monitoring workload          | Poll one address; comment parsing adds CPU but [RPC calls](/ecosystem/api/overview) stay low                | Track many addresses; RPC queries and state tracking grow with the active user base      |\n| Withdrawal handling          | [Highload wallet](/standard/wallets/highload/overview) can batch withdrawals from one balance               | Need sweeps or coordinated withdrawals from many wallets; extra gas and sequencing logic |\n| Sharding behavior            | All activity hits [one shard](/foundations/shards); throughput limited by that shard                        | Wallets are distributed across shards; helps spread load                                 |\n\n## Invoice-based deposits\n\nInvoice-based processing uses one wallet address to receive payments from all users. Each payment includes a unique identifier in the transaction comment field, allowing the service to attribute deposits to specific users.\n\nThe implementation deploys one wallet contract (typically [Highload](/standard/wallets/highload/overview)) and generates unique invoice identifiers for each deposit. Users send Toncoin to this shared address with their invoice identifier as the comment. The service polls the wallet's transaction history, extracts comments from incoming messages, matches them against stored invoices, and credits user accounts accordingly.\n\nTransaction comments in TON use the text message format; read more in [How TON wallets work](/standard/wallets/how-it-works).\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  Risk: deposits without the correct invoice identifier may be lost.\n  Scope: incoming transfers to the shared deposit address.\n  Mitigation: enforce invoice format; reject or hold unmatched deposits; provide a recovery workflow; document comment entry in the UI.\n  Environment: validate the full flow on testnet before enabling mainnet.\n</Aside>\n\n**Advantages**:\n\n- Single wallet simplifies key management\n- Reduced gas costs for deployments\n- Withdrawals can batch multiple user requests into one transaction using a Highload wallet\n\n**Disadvantages**:\n\n- Access leak to the single hot wallet could lead to all user funds loss\n- Users must correctly input the invoice identifier, and mistakes result in lost or misdirected funds\n- Comment parsing adds complexity\n- Some user wallet applications don't support comments, limiting accessibility\n- Single wallet network load [won't be sharded](/foundations/shards)\n\nUse the following TypeScript implementation for educational purposes only: [invoice-based Toncoin deposits](https://github.com/ton-org/docs-examples/blob/processing/guidebook/toncoin-processing/src/deposits/invoices.ts).\n\n## Unique deposit addresses\n\nUnique address deposits use a separate wallet contract for each user. The user deposits to their dedicated address, and the service monitors all deployed wallets for incoming transactions. No comment parsing is required since each address maps to exactly one user.\n\nImplementation requires a wallet generation strategy. A common approach uses a deterministic scheme based on a single master [keypair](/standard/wallets/mnemonics) and user identifiers, deriving unique addresses for V4 and V5 wallets using different [`subwallet_id`](/standard/wallets/how-it-works#subwallet-id) values. Alternatively, generate a unique keypair per user, though this increases key management complexity.\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  Funds sent to a [non-existent or wrong address](/foundations/addresses/overview) are irrecoverable. Derive addresses deterministically and double check.\n</Aside>\n\nWallet deployment happens lazily when users first request their deposit address. Generate the address deterministically without deploying the contract. When the user sends their first deposit to the not deployed address, send the transaction in [non-bounceable mode](/foundations/messages/overview). The contract doesn't exist yet, so bounceable messages would return the funds. After the first deposit arrives, deploy the contract using funds from that deposit or from an external source.\n\n<Aside>\n  Sending non-bounceable messages to nonexistent accounts without testing it first is particularly bad practice. Always test to ensure the address is correct and the deployment flow works as expected.\n</Aside>\n\nMonitor all user wallets by maintaining a list of deployed addresses and polling their transactions. For large user bases, this becomes resource-intensive. Optimization strategies include monitoring only active wallets (those with recent deposits), using batched RPC calls to check multiple wallets per request.\n\nTON's sharding mechanism splits the network across multiple chains based on address prefixes. The shard prefix comes from the first bits of the address hash. Deploying wallets in the same shard reduces cross-shard communication overhead.\n\n<Aside\n  type=\"danger\"\n  title=\"Keys and funds at risk\"\n>\n  Risk: leaked or mishandled private keys enable wallet takeover and fund loss.\n  Scope: generation, storage, and access to per-user wallet keys and deployment workflow.\n  Mitigation: encrypt keys at rest; restrict access; rotate keys; monitor deployment status; verify destination addresses before crediting deposits.\n  Environment: validate key management and deployment flow on testnet before mainnet.\n</Aside>\n\nWithdrawal processing must gather funds from multiple wallets. Either maintain a minimum balance in each wallet for gas fees or implement a fund collection system that periodically sweeps deposits to a central hot wallet. Highload wallets handle batch withdrawals efficiently, while standard V4/V5 wallets process messages sequentially using `seqno`, creating bottlenecks under high load.\n\n**Advantages**:\n\n- No comment parsing removes a major source of user error\n- Better security since each user has a unique keypair\n- Transaction monitoring is straightforward - any incoming transaction to a user's address is their deposit\n\n**Disadvantages**:\n\n- Higher operational complexity managing multiple wallets\n- Deployment costs multiply by the number of users\n- Withdrawal processing requires coordination across wallets\n- Storage fees apply to each deployed contract (currently \\~0.001 TON per year per contract)\n\nUse the following TypeScript implementation for educational purposes only: [unique address Toncoin deposits](https://github.com/ton-org/docs-examples/blob/processing/guidebook/toncoin-processing/src/deposits/unique-addresses.ts).\n\n## Withdrawal batching\n\n<Aside\n  type=\"caution\"\n>\n  When withdrawing, do not send funds to a wallet address that you cannot initialize later, based on contracts [initial state](/foundations/addresses/overview).\n</Aside>\n\n[Highload wallets](/standard/wallets/highload/overview) support parallel message processing by storing processed request identifiers instead of sequential `seqno`. This enables batching multiple withdrawals into one transaction, reducing fees and improving throughput.\n\n## Common abuse patterns\n\n- Reusing a previously settled invoice identifier to trigger duplicate credits when the backend does not invalidate the invoice after the first use.\n- Changing the Toncoin amount but leaving the original invoice identifier to obtain services at a lower price if expected amounts are not enforced.\n- Crafting comments that mimic another users invoice identifier in order to hijack their pending credit.\n- Submitting large numbers of dust payments to inflate processing costs or exhaust rate limits on transaction polling.\n\n## Monitoring best practices\n\nImplement exponential backoff for RPC failures. Network issues or node maintenance can interrupt transaction polling. When [`getTransactions`](/ecosystem/api/toncenter/v2/accounts/list-account-transactions) fails, wait before retrying with increasing delays to avoid overwhelming the endpoint.\n\nStore transaction state persistently. Record the last processed `lt` value (`lt` here is logical time) and transaction hash to resume monitoring after restarts without reprocessing transactions. This prevents duplicate deposit credits.\n\nUse multiple RPC endpoints for reliability. TON has several public API providers and liteserver networks. Implement fallback logic to switch endpoints if the primary becomes unavailable. Compare results across endpoints to detect potential inconsistencies.\n\nLog all processing decisions including deposit credits, withdrawal submissions, and failed transactions. These logs are essential for debugging user reports and auditing system behavior. Include transaction hashes, logical times, amounts, and user identifiers in logs.\n"
  },
  {
    "path": "resources/dictionaries/ban.txt",
    "content": "# The ! prefix forbids words: marks them as prohibited / not allowed.\n# If the banned word has a clear and correct replacement, place it inside\n# the flagWords property of the .cspell.jsonc file in the root instead.\n"
  },
  {
    "path": "resources/dictionaries/custom.txt",
    "content": "#   Custom dictionaries support a few special characters:\n# ! is a prefix that forbids a word — use -ban.txt files for those.\n# * is a prefix/suffix that tells the spell checker that a word can be combined with another word.\n# + is a prefix/suffix that tells the spell checker that a word MUST be combined with another word to be valid.\n# ~ is a prefix that tells the spell checker to only use the word when case sensitivity is turned off.\n+-ary\n+-tos\nabelian\nABI*\naccountchain\nAccountchain\naccountchains\naddon\nadnl\nADNL\nagentic\nAgentic\nAigerim\naigerimu\nAiogram\nakifoq\nAlefman\nAlejandbel\nAlexG\nalgorithm\nAliaksandr\nAlibaba\nallowlist\nallowlists\naltcoin\nAltcoin\naltcoins\nAMM*\nAndr\nandrei\nAndrew\nAndrey\nantecessor\nantecessors\nAnton\nAntonoff\nAppender\nAppenders\nanycast\napi\nappender\nappenders\nAPI\nAPIs\nAPY\narith\narity\nArkworks\nasin\nasm\nasms\nasynchrony\nautogenerates\nAvacoin\nAVX\naxios\nAxios\nB4ckSl4sh\nBahdanau\nBaranov\nbasechain\nBasechain\nBCM\nBCP\nBemo\nbene\nBFT\nBidask\nBinance\nbirational\nbirationally\nBirman\nbitcode\nbitmask\nBitmask\nBitshares\nbitshift\nbitstring\nbitstrings\nbitwise\nblazingly\nblockchain\nBlockchain\nblockchains\nblockquote\nblockquotes\nBlockscout\nBLS\nbmTON\nBoC\nBoCs\nbooleans\nBooleans\nbounceability\nbounceable\nBounceable\nBrodie\nbrowseability\nBrujn\nbuildx\nBuildx\nbundler\nBurnosov\nButerin\ncallables\nCallables\ncallee\ncallout\ncallouts\ncanonicalization\ncatchain\nCatchain\ncatchains\nCatchains\ncatchchain\nCatizen\ncbcast\ncbcasts\nCCITT\ncelldb\nCertik\nCEX\nCEXes\nCEXs\nchainable\nChainbase\ncheatsheet\nChichigin\nchksig\nchrono\nciphertexts\nCiphertexts\ncircom\nCircom\nclcf\nCLion\nCMake\nCMC\ncNFT\ncNFTs\nCoalus\ncodegen\ncodepage\nCodepage\ncodepages\nCodepages\nCodepoint\ncodepoints\ncodespace\ncodespaces\nCodespaces\nCodium\ncodomain\ncofactor\ncofactors\nCoinbase\ncombinator\nCombinator\ncombinators\nCombinators\ncomponentwise\ncomposable\nconcatenative\nconfigs\nConfigs\nconfigurator\nConfigurator\nconsortiums\nconstructivization\nconstructivized\ncooldown\nCoq\ncounterparty\nCPUs\ncron\ncrosschain\nCrosschain\nCrowdin\ncrypto\nCryptobot\ncryptocurrencies\nCryptocurrencies\ncryptocurrency\ncryptosystem\nCryptosystem\ncryptosystems\nCryptosystems\ncryptowallet\ncta\nCTA\nCTAs\nd3fl4t3\nDaniil\ndApp\nDApp\ndApps\nDApps\ndatacenters\ndatagram\nDatagram\ndatagrams\nDCA\ndeclarator\ndecodable\ndecompiled\nDecompiled\nDecompiler\ndeduplicate\ndeduplicates\ndeduplicating\ndeduplication\nDeduplication\nDedust\nDehasher\ndelegators\nden_lavi\ndenylist\ndeployer\nDeployer\ndequeued\ndequeueing\ndereference\ndereferenced\ndeserialization\ndeserialized\ndeserializes\ndeserializing\ndevnet\nDEX\nDEXes\nDEXs\nDHT\nDHTs\nDNAT\nDiffie\ndockerize\nDockerize\ndockerized\nDockerized\nDodis\nDomínguez\ndotenv\ndTON\nDuif\nDurov\nDyor\nDYOR\nDYX\nEIP\nEmelyanenko\nenablement\nendian\nEndian\nenqueued\nEnums\nEOA\nEOAs\nERC\nEruda\nEthena\nEthereum\nEthernaut\nEthers\nEtherscan\netl\nETL*\nEVAA\nEverscale\nEVM\nEVMs\nfailover\nFavour\nfavourkelvin17\nfift\nFift\nFigma\nFlappy\nforall\nfrontmatter\nFrontmatter\nFTs\ngabriel-fallen\nGanache\ngasless\ngatekeeping\nGbps\ngeo\ngetgems\ngetters\nGigadrop\ngigaton\nGigatons\nGilmanova\ngitbook\nGitpod\nglobals\nGoldschlag\nGolev\nGrafana\ngrammY\nGTon\nGunicorn\ngusarich\nGutarev\ngwei\nhackathon\nHackathon\nhackathons\nHackenProof\nhard-code\nhardcode\nhard-coded\nhardcoded\nhardfork\nhashmap\nHashmap\nHashmaps\nHasse\nHéctor\nHetzner\nhighload\nHighload\nHipo\nHomotopy\nhostname\niconUrl\nident\nIHR\nImedashvili\nimpactful\nincentivizes\ninclusivity\nInclusivity\nindeterministic\ninfobox\ninit\ninitializer\nInitializer\ninjective\ninjectivity\ninlined\ninlines\ninlining\nInterchain\ninvolutive\nIPFS\nisogeny\nJDK\njemalloc\njeshecdom\nJesús\nJetbrains\njettons\nJettons\nKademlia\nKaladin13\nKarkarmath\nKelmer\nKelvin\nkeyblock\nKeyblock\nkeyblocks\nKeyblocks\nkeypair\nkeystore\nkeystores\nkube\nKiayas\nKiB\nKol\nKolya\nKombat\nKYC\nLamport\nLange\nLarimer\nLateinit\nLatinisms\nLavinia\nleaderboard\nLeaderboard\nLebedev\nlifecheck\nlinkability\nLiskov\nliteclient\nLiteclient\nLitecoin\nliteserver\nLiteserver\nliteservers\nLiteservers\nliveness\nLLM\nllms\nlockdown\nlookups\nlottie\nLottie\nLSB\nLSP\nLuby\nLuhn\nLuma\nLynis\nmainnet\nMainnet\nmasterchain\nMasterchain\nmasterchains\nmatchers\nmathbb\nmathbf\nmathlib\nMaymounkov\nMazières\nMCP\nmemearchivarius\nmemecoin\nmemoization\nMemoizing\nmempool\nMempool\nmergesort\nmerkle\nMerkle\nmetafile\nMetafile\nMetalLB\nMetaverse\nmicropayment\nmicropayments\nMicropayments\nmicroton\nmicrotransaction\nMicrotransaction\nmicrotransactions\nmilli\nminimalistic\nMinimalistic\nminmax\nmintable\nmintless\nMintlify\nmintmachine\nmisclick\nmisclicks\nmisconfiguration\nmisconfigured\nmisti\nmitigations\nMonero\nmonoid\nmonorepo\nmonospace\nmonospaced\nmontgomery\nMPP\nMTon\nMTProto\nmultibyte\nmulticast\nMulticasting\nmultichain\nMultichain\nmultiplatform\nMultiplatform\nmultiset\nmultisig\nmultisignature\nmytoncore\nmytonctrl\nMytonctrl\nNakamoto\nnamespace\nNamespace\nnamespaces\nNamespaces\nnano\nnanogram\nnanoton\nnanoTon\nnanotoncoin\nnanoToncoin\nnanotoncoins\nnanotons\nnavbar\nNavbar\nNeovim\nNFA\nnft\nnginx\nNFTs\nNginx\nNiels\nNikolay\nNoname\nnonexist\nNOPs\nnota\nNota\nNotcoin\nNovus\nnovusnota\nNowarp\nnullability\nNullability\nnullable\nNullable\nnullables\nNullables\nnullary\nNVMe\nOCaml\noffchain\nOffchaining\nOleg\nOmniston\nonwards\nOpenCL\nopenlib\nopenrouter\noutcoming\nOVH\nparam\nparameterization\npasteable\nPavel\nPay\npaywalled\nPDFs\nPease\nperformant\npermissionless\nPermissionless\nPeyton\nPhaser\nPitaya\nplaintext\nplaintexts\nplsc\npluggable\npostprocessed\npragma\npragmas\nPragmas\nprecommitted\nPrecompiled\npreconfigure\npreconfigured\npreconfigures\npredefines\nprefetch\npreimages\npreloading\npreloads\nPreloads\nPRNG\nPRNGs\nprojectId\nProlog\nprometheus\nPrometheus\nproxying\npseudocode\nPseudocode\npseudorandom\npseudorandomly\npushgateway\nPushgateway\npyAndr3w\nPyth\nQodo\nqueryable\nragpull\nRatelance\nreconnections\nrecv\nredeclaration\nredeclared\nredistributable\nRedistributable\nreindex\nReindex\nreindexes\nReindexes\nreindexing\nReindexing\nreinitializes\nreinstalls\nrelatedly\nRelatedly\nrelayer\nReputational\nresharding\nresynced\nReth\nretracer\nRetracer\nreveloper\nRevm\nRIST\nRistretto\nRLDP\nrollup\nRollup\nRPCs\nRTT\nruleset\nrunbooks\nruntimes\nSánchez\nsandboxing\nsatoshi\nsavelist\nsavelists\nSBT\nSBTs\nscannability\nScannability\nSCCCG\nSchnorr\nSDKs\nSECD\nsecp\nSedov\nSELinux\nsemver\nsendBoc\nSEO\nseqno\nseqnos\nSerializable\nserializer\nserializers\nsetwebpass\nshardable\nshardchain\nshardchains\nsharded\nsharding\nSharding\nsharedlibrary\nShokrollahi\nshorteners\nShostak\nsidechain\nsidechains\nSild\nsilddev\nSinglechain\nskillset\nskywardboundd\nsmartcont\nSolana\nSoulbound\nSpellbook\nsse\nSSEA\nstablecoin\nStablecoin\nstablecoins\nStablecoins\nstakers\nstdlib\nSTON.fi\nstyleguide\nsubarrays\nsubcase\nsubcases\nsubcell\nsubcolumn\nsubcolumnTblkch\nsubdictionaries\nsubdictionary\nsubexpression\nsubexpressions\nsubfolder\nsubfolders\nsubgraph\nsubinterval\nsubnet\nsubnets\nsubnetwork\nsubnetworks\nsubpage\nsubqueries\nsubresolver\nsubslice\nsubslices\nsubstring\nsubtransactions\nsubtree\nsubtrees\nsubwallet\nsubwallets\nsudo\nsuperserver\nSVM\nswappable\nsystemd\nSyverson\ntagless\nTal\nTalpas\nTanenbaum\nTanja\ntApp\ntApps\nTASM\nTblkch\ntelemint\nTencent\nTEP\nTEPs\nTES\nTestgiver\ntestnet\nTestnet\nTezos\ntimepoint\nTMA\nTMAs\ntock\nTock\ntokenomics\nTokenomics\ntolk\nTolk\nTON\nTON.cx\nTONCO\nToncoin\ntoncoin.org\nTonkeeper\ntonlib\nTonscan\ntonscan.com\ntonscan.org\nTonstakers\nTonviewer\ntonviewer.com\ntoolchain\ntoolset\ntracebacks\nTradoor\nTransactionDescr\ntrie\nTrunov\ntruthy\ntsUSDe\nTVL\nTVM\nTVMs\nTxTracer\nuint\nUint\nUIs\nUiua\nunary\nUnary\nunblockable\nunbounceable\nundecodable\nunderload\nUnderload\nunderperforming\nundiscussed\nunencrypted\nunenveloped\nunforgeable\nuninit\nUninit\nunintuitive\nuniswap\nUniversa\nunixtime\nunpair\nunparsed\nunsplit\nunstake\nunstaking\nuntrusted\nuntyped\nunvoted\nupdatable\nUpgradability\nuptimes\nURIs\nUSDe\nUSDt\nutils\nutime\nVadim\nvalidator\nValidator\nvalidators\nValidators\nvariadic\nvaruint*\nvCPUs\nverytactical\nViem\nvirtualized\nVladas\nVladimir\nVMs\nVolkov\nVPNs\nVSCodium\nVSX\nVultr\nWagmi\nwalkthrough\nWalkthrough\nWalletconnect\nwargame\nWatchlist\nWDK\nwebserver\nWebserver\nwebview\nWeil\nwhitepaper\nwhitepapers\nworkchain\nworkchains\nXia\nXMM\nXMODEM\nXMPL\nXORing\nYolo\nYung\nZakrevskis\nZellic\nzerostate\nZK-proof\nGbit\nMbit\ntonstatus\ntestnetstatus\nZK-proofs\n"
  },
  {
    "path": "resources/dictionaries/tvm-instructions.txt",
    "content": "-ROLLX\n-ROT\nABS\nACCEPT\nADD\nADDCONST\nADDDIVMOD\nADDDIVMODC\nADDDIVMODR\nADDINT\nADDRAND\nADDRSHIFT\nADDRSHIFTC\nADDRSHIFTCMOD\nADDRSHIFTMOD\nADDRSHIFTMODC\nADDRSHIFTMODR\nADDRSHIFTR\nADDRSHIFTRMOD\nAGAIN\nAGAINBRK\nAGAINEND\nAGAINENDBRK\nAGGREGATEVERIFY\nAND\nATEXIT\nATEXITALT\nBALANCE\nBBITREFS\nBBITS\nBCHKBITREFS\nBCHKBITREFSQ\nBCHKBITS\nBCHKBITSQ\nBCHKBITSQ_VAR\nBCHKBITS_VAR\nBCHKREFS\nBCHKREFSQ\nBCONCAT\nBCONCATQ\nBDEPTH\nBITSIZE\nBLESS\nBLESSARGS\nBLESSNUMARGS\nBLESSVARARGS\nBLKDROP\nBLKDROP2\nBLKPUSH\nBLKSWAP\nBLKSWX\nBLOCKLT\nBOOLAND\nBOOLEVAL\nBOOLOR\nBRANCH\nBREFS\nBREMBITREFS\nBREMBITS\nBREMREFS\nCADDR\nCADR\nCALLCC\nCALLCCARGS\nCALLCCVARARGS\nCALLDICT\nCALLDICT_LONG\nCALLREF\nCALLX\nCALLXARGS\nCALLXARGS_VAR\nCALLXVARARGS\nCDATASIZE\nCDATASIZEQ\nCDDDR\nCDDR\nCDEPTH\nCDEPTHI\nCDEPTHIX\nCHANGELIB\nCHASHI\nCHASHIX\nCHKBIT\nCHKBOOL\nCHKDEPTH\nCHKNAN\nCHKSIGNS\nCHKSIGNU\nCHKTUPLE\nCLEVEL\nCLEVELMASK\nCMP\nCOMMIT\nCOMPOS\nCOMPOSALT\nCOMPOSBOTH\nCONDSEL\nCONDSELCHK\nCONFIGDICT\nCONFIGOPTPARAM\nCONFIGPARAM\nCONFIGROOT\nCTOS\nDEBUG\nDEBUGSTR\nDEBUGSTRI\nDEC\nDEPTH\nDICTADD\nDICTADDB\nDICTADDGET\nDICTADDGETB\nDICTADDGETREF\nDICTADDREF\nDICTDEL\nDICTDELGET\nDICTDELGETREF\nDICTEMPTY\nDICTGET\nDICTGETNEXT\nDICTGETNEXTEQ\nDICTGETOPTREF\nDICTGETPREV\nDICTGETPREVEQ\nDICTGETREF\nDICTIADD\nDICTIADDB\nDICTIADDGET\nDICTIADDGETB\nDICTIADDGETREF\nDICTIADDREF\nDICTIDEL\nDICTIDELGET\nDICTIDELGETREF\nDICTIGET\nDICTIGETEXEC\nDICTIGETEXECZ\nDICTIGETJMP\nDICTIGETJMPZ\nDICTIGETNEXT\nDICTIGETNEXTEQ\nDICTIGETOPTREF\nDICTIGETPREV\nDICTIGETPREVEQ\nDICTIGETREF\nDICTIMAX\nDICTIMAXREF\nDICTIMIN\nDICTIMINREF\nDICTIREMMAX\nDICTIREMMAXREF\nDICTIREMMIN\nDICTIREMMINREF\nDICTIREPLACE\nDICTIREPLACEB\nDICTIREPLACEGET\nDICTIREPLACEGETB\nDICTIREPLACEGETREF\nDICTIREPLACEREF\nDICTISET\nDICTISETB\nDICTISETGET\nDICTISETGETB\nDICTISETGETOPTREF\nDICTISETGETREF\nDICTISETREF\nDICTMAX\nDICTMAXREF\nDICTMIN\nDICTMINREF\nDICTPUSHCONST\nDICTREMMAX\nDICTREMMAXREF\nDICTREMMIN\nDICTREMMINREF\nDICTREPLACE\nDICTREPLACEB\nDICTREPLACEGET\nDICTREPLACEGETB\nDICTREPLACEGETREF\nDICTREPLACEREF\nDICTSET\nDICTSETB\nDICTSETGET\nDICTSETGETB\nDICTSETGETOPTREF\nDICTSETGETREF\nDICTSETREF\nDICTUADD\nDICTUADDB\nDICTUADDGET\nDICTUADDGETB\nDICTUADDGETREF\nDICTUADDREF\nDICTUDEL\nDICTUDELGET\nDICTUDELGETREF\nDICTUGET\nDICTUGETEXEC\nDICTUGETEXECZ\nDICTUGETJMP\nDICTUGETJMPZ\nDICTUGETNEXT\nDICTUGETNEXTEQ\nDICTUGETOPTREF\nDICTUGETPREV\nDICTUGETPREVEQ\nDICTUGETREF\nDICTUMAX\nDICTUMAXREF\nDICTUMIN\nDICTUMINREF\nDICTUREMMAX\nDICTUREMMAXREF\nDICTUREMMIN\nDICTUREMMINREF\nDICTUREPLACE\nDICTUREPLACEB\nDICTUREPLACEGET\nDICTUREPLACEGETB\nDICTUREPLACEGETREF\nDICTUREPLACEREF\nDICTUSET\nDICTUSETB\nDICTUSETGET\nDICTUSETGETB\nDICTUSETGETOPTREF\nDICTUSETGETREF\nDICTUSETREF\nDIV\nDIVC\nDIVMOD\nDIVMODC\nDIVMODR\nDIVR\nDIV_BASE\nDROP\nDROP2\nDROPX\nDUEPAYMENT\nDUMP\nDUMPSTK\nDUP\nDUP2\nECRECOVER\nEDFA\nEDFB\nENDC\nENDCST\nENDS\nENDXC\nEQINT\nEQUAL\nEXECUTE\nEXPLODE\nEXPLODEVAR\nFASTAGGREGATEVERIFY\nFIRST\nFIRSTQ\nFITS\nFITSX\nGASCONSUMED\nGEQ\nGEQINT\nGETFORWARDFEE\nGETFORWARDFEESIMPLE\nGETGASFEE\nGETGASFEESIMPLE\nGETGLOB\nGETGLOBVAR\nGETORIGINALFWDFEE\nGETPARAM\nGETPRECOMPILEDGAS\nGETSTORAGEFEE\nGLOBALID\nGREATER\nGTINT\nHASHBU\nHASHCU\nHASHEXT\nHASHEXTAR_BLAKE\nHASHEXTAR_BLAKE2B\nHASHEXTAR_KECCAK\nHASHEXTAR_KECCAK256\nHASHEXTAR_KECCAK512\nHASHEXTAR_SHA\nHASHEXTAR_SHA256\nHASHEXTAR_SHA512\nHASHEXTA_BLAKE\nHASHEXTA_BLAKE2B\nHASHEXTA_KECCAK\nHASHEXTA_KECCAK256\nHASHEXTA_KECCAK512\nHASHEXTA_SHA256\nHASHEXTA_SHA512\nHASHEXTR_BLAKE2B\nHASHEXTR_KECCAK256\nHASHEXTR_KECCAK512\nHASHEXTR_SHA256\nHASHEXTR_SHA512\nHASHEXT_BLAKE2B\nHASHEXT_KECCAK256\nHASHEXT_KECCAK512\nHASHEXT_SHA256\nHASHEXT_SHA512\nHASHSU\nIF\nIFBITJMP\nIFBITJMPREF\nIFELSE\nIFELSEREF\nIFJMP\nIFJMPREF\nIFNBITJMP\nIFNBITJMPREF\nIFNOT\nIFNOTJMP\nIFNOTJMPREF\nIFNOTREF\nIFNOTRET\nIFNOTRETALT\nIFREF\nIFREFELSE\nIFREFELSEREF\nIFRET\nIFRETALT\nINC\nINCOMINGVALUE\nINDEX\nINDEX2\nINDEX3\nINDEXQ\nINDEXVAR\nINDEXVARQ\nINMSGPARAMS\nINTSORT\nINVERT\nISNAN\nISNEG\nISNNEG\nISNPOS\nISNULL\nISPOS\nISTUPLE\nISZERO\nJMPDICT\nJMPREF\nJMPREFDATA\nJMPX\nJMPXARGS\nJMPXDATA\nJMPXVARARGS\nKECCAK\nLAST\nLDDICT\nLDDICTQ\nLDDICTS\nLDGRAMS\nLDI\nLDILE4\nLDILE4Q\nLDILE8\nLDILE8Q\nLDIQ\nLDIX\nLDIXQ\nLDI_ALT\nLDMSGADDR\nLDMSGADDRQ\nLDONES\nLDOPTREF\nLDREF\nLDREFRTOS\nLDSAME\nLDSLICE\nLDSLICEQ\nLDSLICEX\nLDSLICEXQ\nLDSLICE_ALT\nLDU\nLDULE4\nLDULE4Q\nLDULE8\nLDULE8Q\nLDUQ\nLDUX\nLDUXQ\nLDU_ALT\nLDVARINT\nLDVARINT16\nLDVARUINT\nLDZEROES\nLEQ\nLEQINT\nLESS\nLESSINT\nLSHIFT\nLSHIFTADDDIVMOD\nLSHIFTADDDIVMODC\nLSHIFTADDDIVMODR\nLSHIFTDIV\nLSHIFTDIVC\nLSHIFTDIVC_VAR\nLSHIFTDIVMOD\nLSHIFTDIVMODC\nLSHIFTDIVMODR\nLSHIFTDIVR\nLSHIFTDIVR_VAR\nLSHIFTDIV_VAR\nLSHIFTMOD\nLSHIFTMODC\nLSHIFTMODR\nLSHIFT_VAR\nLTIME\nMAX\nMIN\nMINMAX\nMOD\nMODC\nMODPOW2\nMODR\nMUL\nMULADDDIVMOD\nMULADDDIVMODC\nMULADDDIVMODR\nMULADDRSHIFT\nMULADDRSHIFTC\nMULADDRSHIFTCMOD\nMULADDRSHIFTMOD\nMULADDRSHIFTR\nMULADDRSHIFTRMOD\nMULCONST\nMULDIV\nMULDIVC\nMULDIVMOD\nMULDIVMODC\nMULDIVMODR\nMULDIVR\nMULINT\nMULMOD\nMULMODC\nMULMODPOW\nMULMODR\nMULRSHIFT\nMULRSHIFTC\nMULRSHIFTCMOD\nMULRSHIFTC_VAR\nMULRSHIFTMOD\nMULRSHIFTR\nMULRSHIFTRMOD\nMULRSHIFTR_VAR\nMULRSHIFT_VAR\nMULTIEXP\nMYADDR\nMYCODE\nNEGATE\nNEQ\nNEQINT\nNEWC\nNEWDICT\nNIL\nNIP\nNOP\nNOT\nNOW\nNULL\nNULLROTRIF\nNULLROTRIF2\nNULLROTRIFNOT\nNULLROTRIFNOT2\nNULLSWAPIF\nNULLSWAPIF2\nNULLSWAPIFNOT\nNULLSWAPIFNOT2\nONE\nONLYTOPX\nONLYX\nOR\nOVER\nOVER2\nP256_CHKSIGNS\nP256_CHKSIGNU\nPAIR\nPARSEMSGADDR\nPARSEMSGADDRQ\nPFXDICTADD\nPFXDICTCONSTGETJMP\nPFXDICTDEL\nPFXDICTGET\nPFXDICTGETEXEC\nPFXDICTGETJMP\nPFXDICTGETQ\nPFXDICTREPLACE\nPFXDICTSET\nPFXDICTSWITCH\nPICK\nPLDDICT\nPLDDICTQ\nPLDDICTS\nPLDI\nPLDILE4\nPLDILE4Q\nPLDILE8\nPLDILE8Q\nPLDIQ\nPLDIX\nPLDIXQ\nPLDOPTREF\nPLDREF\nPLDREFIDX\nPLDREFVAR\nPLDSLICE\nPLDSLICEQ\nPLDSLICEX\nPLDSLICEXQ\nPLDU\nPLDULE\nPLDULE4\nPLDULE4Q\nPLDULE8\nPLDULE8Q\nPLDUQ\nPLDUX\nPLDUXQ\nPLDUZ\nPOP\nPOPCTR\nPOPCTRSAVE\nPOPCTRX\nPOPROOT\nPOPSAVE\nPOP_LONG\nPOW2\nPREPAREDICT\nPREVBLOCKSINFOTUPLE\nPREVKEYBLOCK\nPREVKEYBLOCKS\nPREVMCBLOCKS\nPU2XC\nPUSH\nPUSH2\nPUSH3\nPUSHCONT\nPUSHCONT_SHORT\nPUSHCTR\nPUSHCTRX\nPUSHINT\nPUSHINT_16\nPUSHINT_4\nPUSHINT_8\nPUSHINT_LONG\nPUSHNAN\nPUSHNEGPOW2\nPUSHNULL\nPUSHPOW2\nPUSHPOW2DEC\nPUSHR\nPUSHREF\nPUSHREFCONT\nPUSHREFSLICE\nPUSHROOT\nPUSHSLICE\nPUSHSLICE_LONG\nPUSHSLICE_REFS\nPUSHX\nPUSH_LONG\nPUXC\nPUXC2\nPUXCPU\nQADD\nQADDDIVMOD\nQADDDIVMODC\nQADDDIVMODR\nQADDRSHIFT\nQADDRSHIFTC\nQADDRSHIFTCMOD\nQADDRSHIFTMOD\nQADDRSHIFTMODC\nQADDRSHIFTMODR\nQADDRSHIFTR\nQADDRSHIFTRMOD\nQAND\nQDEC\nQDIV\nQDIVC\nQDIVMOD\nQDIVMODC\nQDIVMODR\nQDIVR\nQFITS\nQFITSX\nQINC\nQLSHIFT\nQLSHIFTADDDIVMOD\nQLSHIFTADDDIVMODC\nQLSHIFTADDDIVMODR\nQLSHIFTDIV\nQLSHIFTDIVC\nQLSHIFTDIVMOD\nQLSHIFTDIVMODC\nQLSHIFTDIVMODR\nQLSHIFTDIVR\nQLSHIFTMOD\nQLSHIFTMODC\nQLSHIFTMODR\nQMOD\nQMODC\nQMODPOW\nQMODR\nQMUL\nQMULADDDIVMOD\nQMULADDDIVMODC\nQMULADDDIVMODR\nQMULADDRSHIFT\nQMULADDRSHIFTC\nQMULADDRSHIFTCMOD\nQMULADDRSHIFTMOD\nQMULADDRSHIFTR\nQMULADDRSHIFTRMOD\nQMULDIV\nQMULDIVC\nQMULDIVMOD\nQMULDIVMODC\nQMULDIVMODR\nQMULDIVR\nQMULMOD\nQMULMODC\nQMULMODPOW\nQMULMODR\nQMULRSHIFT\nQMULRSHIFTC\nQMULRSHIFTCMOD\nQMULRSHIFTMOD\nQMULRSHIFTR\nQMULRSHIFTRMOD\nQNEGATE\nQNOT\nQOR\nQPOW2\nQRSHIFT\nQRSHIFTC\nQRSHIFTCMOD\nQRSHIFTMOD\nQRSHIFTMODC\nQRSHIFTMODR\nQRSHIFTR\nQRSHIFTRMOD\nQSUB\nQSUBR\nQTLEN\nQUFITS\nQUFITSX\nQXOR\nRAND\nRANDSEED\nRANDU\nRANDU256\nRAWRESERVE\nRAWRESERVEX\nREPEAT\nREPEATBRK\nREPEATEND\nREPEATENDBRK\nRET\nRETALT\nRETARGS\nRETBOOL\nRETDATA\nRETFALSE\nRETTRUE\nRETURNARGS\nRETURNVARARGS\nRETVARARGS\nREVERSE\nREVX\nREWRITESTDADDR\nREWRITESTDADDRQ\nREWRITEVARADDR\nREWRITEVARADDRQ\nRIST255_ADD\nRIST255_FROMHASH\nRIST255_MUL\nRIST255_MULBASE\nRIST255_PUSHL\nRIST255_QADD\nRIST255_QMUL\nRIST255_QMULBASE\nRIST255_QSUB\nRIST255_QVALIDATE\nRIST255_SUB\nRIST255_VALIDATE\nROLL\nROLLREV\nROLLREVX\nROLLX\nROT\nROT2\nROTREV\nRSHIFT\nRSHIFTC\nRSHIFTCMOD\nRSHIFTC_VAR\nRSHIFTMOD\nRSHIFTMODC\nRSHIFTMODR\nRSHIFTR\nRSHIFTRMOD\nRSHIFTR_VAR\nRSHIFT_VAR\nRUNVM\nRUNVMX\nSAMEALT\nSAMEALTSAVE\nSAVE\nSAVEALT\nSAVEALTCTR\nSAVEBOTH\nSAVEBOTHCTR\nSAVECTR\nSBITREFS\nSBITS\nSCHKBITREFS\nSCHKBITREFSQ\nSCHKBITS\nSCHKBITSQ\nSCHKREFS\nSCHKREFSQ\nSCUTFIRST\nSCUTLAST\nSDATASIZE\nSDATASIZEQ\nSDBEGINS\nSDBEGINSQ\nSDBEGINSX\nSDBEGINSXQ\nSDCNTLEAD0\nSDCNTLEAD1\nSDCNTTRAIL0\nSDCNTTRAIL1\nSDCUTFIRST\nSDCUTLAST\nSDEMPTY\nSDEPTH\nSDEQ\nSDFIRST\nSDLEXCMP\nSDPFX\nSDPFXREV\nSDPPFX\nSDPPFXREV\nSDPSFX\nSDPSFXREV\nSDSFX\nSDSFXREV\nSDSKIPFIRST\nSDSKIPLAST\nSDSUBSTR\nSECG\nSECOND\nSECONDQ\nSECP256K1_XONLY_PUBKEY_TWEAK_ADD\nSEMPTY\nSENDMSG\nSENDRAWMSG\nSETALTCTR\nSETCODE\nSETCONT\nSETCONTARGS\nSETCONTARGS_N\nSETCONTCTR\nSETCONTCTRX\nSETCONTVARARGS\nSETCP\nSETCP0\nSETCPX\nSETCP_SPECIAL\nSETEXITALT\nSETFIRST\nSETFIRSTQ\nSETGASLIMIT\nSETGLOB\nSETGLOBVAR\nSETINDEX\nSETINDEXQ\nSETINDEXVAR\nSETINDEXVARQ\nSETLIBCODE\nSETNUMARGS\nSETNUMVARARGS\nSETRAND\nSETRETCTR\nSETSECOND\nSETSECONDQ\nSETTHIRD\nSETTHIRDQ\nSGN\nSHA256U\nSINGLE\nSKIPDICT\nSKIPOPTREF\nSPLIT\nSPLITQ\nSREFS\nSREMPTY\nSSKIPFIRST\nSSKIPLAST\nSTB\nSTBQ\nSTBR\nSTBREF\nSTBREFQ\nSTBREFR\nSTBREFRQ\nSTBREFR_ALT\nSTBRQ\nSTDICT\nSTDICTS\nSTGRAMS\nSTI\nSTILE4\nSTILE8\nSTIQ\nSTIR\nSTIRQ\nSTIX\nSTIXQ\nSTIXR\nSTIXRQ\nSTI_ALT\nSTONE\nSTONES\nSTOPTREF\nSTORAGEFEES\nSTRDUMP\nSTREF\nSTREF2CONST\nSTREFCONST\nSTREFQ\nSTREFR\nSTREFRQ\nSTREF_ALT\nSTSAME\nSTSLICE\nSTSLICECONST\nSTSLICEQ\nSTSLICER\nSTSLICERQ\nSTSLICE_ALT\nSTU\nSTULE\nSTULE4\nSTULE8\nSTUQ\nSTUR\nSTURQ\nSTUX\nSTUXQ\nSTUXR\nSTUXRQ\nSTU_ALT\nSTVARINT\nSTVARINT16\nSTVARUINT\nSTZERO\nSTZEROES\nSUB\nSUBCONST\nSUBDICTGET\nSUBDICTIGET\nSUBDICTIRPGET\nSUBDICTRPGET\nSUBDICTUGET\nSUBDICTURPGET\nSUBINT\nSUBR\nSUBSLICE\nSWAP\nSWAP2\nTEN\nTHENRET\nTHENRETALT\nTHIRD\nTHIRDQ\nTHROW\nTHROWANY\nTHROWANYIF\nTHROWANYIFNOT\nTHROWARG\nTHROWARGANY\nTHROWARGANYIF\nTHROWARGANYIFNOT\nTHROWARGIF\nTHROWARGIFNOT\nTHROWIF\nTHROWIFNOT\nTHROWIFNOT_SHORT\nTHROWIF_SHORT\nTHROW_SHORT\nTLEN\nTPOP\nTPUSH\nTRIPLE\nTRUE\nTRY\nTRYARGS\nTUCK\nTUPLE\nTUPLEVAR\nTWO\nUBITSIZE\nUFITS\nUFITSX\nUNPACKEDCONFIGTUPLE\nUNPACKFIRST\nUNPACKFIRSTVAR\nUNPAIR\nUNSINGLE\nUNTIL\nUNTILBRK\nUNTILEND\nUNTILENDBRK\nUNTRIPLE\nUNTUPLE\nUNTUPLEVAR\nWHILE\nWHILEBRK\nWHILEEND\nWHILEENDBRK\nXC2PU\nXCHG\nXCHG2\nXCHG3\nXCHG3_ALT\nXCHGX\nXCHG_0I\nXCHG_0I_LONG\nXCHG_1I\nXCHG_IJ\nXCPU\nXCPU2\nXCPUXC\nXCTOS\nXLOAD\nXLOADQ\nXOR\nZERO\nGETSET  \nGETADD  \nGETREPLACE  \nGETMIN  \nGETMAX  \nREMOVEMIN  \nREMOVEMAX  \nGETNEXT  \nGETPREV  \nGETSUBDICT  \nREPLACESUBDICT  \nDELETESUBDICT  \nFOREACHREV  \nTREEREDUCE "
  },
  {
    "path": "resources/dictionaries/two-letter-words-ban.txt",
    "content": "# This file forbids most of the two character words.\n# If such word is part of some bigger word that should be allowed, then instead of removing it from this list, add the allowed word to custom.txt file. For example, \"CL\" is banned here, but as it is a part of \"OpenCL\", the !CL ban stays and the OpenCL word is added to custom.txt.\n!aa\n!Aa\n!AA\n!aA\n!ab\n!Ab\n!AB\n!aB\n!ac\n!Ac\n!AC\n!aC\n!AD\n!aD\n!ae\n!Ae\n!AE\n!aE\n!af\n!Af\n!AF\n!aF\n!ag\n!Ag\n!AG\n!aG\n!ah\n!Ah\n!AH\n!aH\n!aj\n!Aj\n!AJ\n!aJ\n!ak\n!Ak\n!AK\n!aK\n!Al\n!AL\n!aL\n!ao\n!Ao\n!AO\n!aO\n!ap\n!Ap\n!AP\n!aP\n!aq\n!Aq\n!AQ\n!aQ\n!ar\n!Ar\n!AR\n!aR\n!au\n!Au\n!AU\n!aU\n!av\n!Av\n!AV\n!aV\n!aw\n!Aw\n!AW\n!aW\n!ax\n!Ax\n!AX\n!aX\n!ay\n!Ay\n!AY\n!aY\n!az\n!Az\n!AZ\n!aZ\n!ba\n!Ba\n!BA\n!bA\n!bb\n!Bb\n!BB\n!bB\n!bc\n!Bc\n!BC\n!bC\n!bd\n!Bd\n!BD\n!bD\n!bf\n!Bf\n!BF\n!bF\n!bg\n!Bg\n!BG\n!bG\n!bh\n!Bh\n!BH\n!bH\n!BI\n!bI\n!bj\n!Bj\n!BJ\n!bJ\n!bk\n!Bk\n!BK\n!bK\n!bl\n!Bl\n!BL\n!bL\n!bm\n!Bm\n!BM\n!bM\n!bn\n!Bn\n!BN\n!bN\n!bo\n!Bo\n!BO\n!bO\n!bp\n!Bp\n!BP\n!bP\n!bq\n!Bq\n!BQ\n!bQ\n!Br\n!BR\n!bR\n!bs\n!Bs\n!BS\n!bS\n!bt\n!Bt\n!BT\n!bT\n!bu\n!Bu\n!BU\n!bU\n!bv\n!Bv\n!BV\n!bV\n!bw\n!Bw\n!BW\n!bW\n!bx\n!Bx\n!BX\n!bX\n!bz\n!Bz\n!BZ\n!bZ\n!ca\n!Ca\n!CA\n!cA\n!cb\n!Cb\n!CB\n!cB\n!cc\n!Cc\n!cC\n!cd\n!Cd\n!cD\n!ce\n!Ce\n!CE\n!cE\n!Cf\n!CF\n!cF\n!cg\n!Cg\n!CG\n!cG\n!ch\n!Ch\n!CH\n!cH\n!ci\n!Ci\n!cI\n!cj\n!Cj\n!CJ\n!cJ\n!ck\n!Ck\n!CK\n!cK\n!cl\n!Cl\n!CL\n!cL\n!cm\n!Cm\n!CM\n!cM\n!cn\n!Cn\n!CN\n!cN\n!co\n!Co\n!CO\n!cO\n!cp\n!Cp\n!CP\n!cP\n!cq\n!Cq\n!CQ\n!cQ\n!cr\n!Cr\n!cR\n!cs\n!Cs\n!cS\n!ct\n!Ct\n!CT\n!cT\n!cu\n!Cu\n!CU\n!cU\n!cv\n!Cv\n!CV\n!cV\n!cw\n!Cw\n!CW\n!cW\n!cx\n!Cx\n!CX\n!cX\n!cy\n!Cy\n!CY\n!cY\n!cz\n!Cz\n!CZ\n!cZ\n!da\n!Da\n!DA\n!dA\n!db\n!Db\n!dB\n!dc\n!Dc\n!DC\n!dC\n!dd\n!Dd\n!DD\n!dD\n!DE\n!dE\n!df\n!Df\n!DF\n!dF\n!dg\n!Dg\n!DG\n!dG\n!dh\n!Dh\n!DH\n!dH\n!di\n!Di\n!DI\n!dI\n!dj\n!Dj\n!DJ\n!dJ\n!dk\n!Dk\n!DK\n!dK\n!dl\n!Dl\n!DL\n!dL\n!dm\n!Dm\n!DM\n!dM\n!dn\n!Dn\n!DN\n!dN\n!dp\n!Dp\n!DP\n!dP\n!dq\n!Dq\n!DQ\n!dQ\n!dr\n!DR\n!dR\n!ds\n!Ds\n!DS\n!dS\n!dt\n!Dt\n!DT\n!dT\n!du\n!Du\n!DU\n!dU\n!dv\n!Dv\n!DV\n!dV\n!dw\n!Dw\n!DW\n!dW\n!dx\n!Dx\n!DX\n!dX\n!dy\n!Dy\n!DY\n!dY\n!dz\n!Dz\n!DZ\n!dZ\n!ea\n!Ea\n!EA\n!eA\n!eb\n!Eb\n!EB\n!eB\n!ec\n!Ec\n!EC\n!eC\n!Ed\n!ED\n!eD\n!ee\n!Ee\n!EE\n!eE\n!ef\n!Ef\n!EF\n!eF\n!eg\n!Eg\n!EG\n!eG\n!eh\n!Eh\n!EH\n!eH\n!ei\n!Ei\n!EI\n!eI\n!ej\n!Ej\n!EJ\n!eJ\n!ek\n!Ek\n!EK\n!eK\n!el\n!El\n!EL\n!eL\n!Em\n!EM\n!eM\n!en\n!En\n!eN\n!eo\n!Eo\n!EO\n!eO\n!ep\n!Ep\n!EP\n!eP\n!eq\n!Eq\n!EQ\n!eQ\n!er\n!Er\n!ER\n!eR\n!Es\n!ES\n!eS\n!Et\n!ET\n!eT\n!eu\n!Eu\n!eU\n!ev\n!Ev\n!EV\n!eV\n!ew\n!Ew\n!EW\n!eW\n!ey\n!Ey\n!EY\n!eY\n!ez\n!Ez\n!EZ\n!eZ\n!fa\n!Fa\n!FA\n!fA\n!fb\n!Fb\n!FB\n!fB\n!Fc\n!FC\n!fC\n!fd\n!Fd\n!FD\n!fD\n!fe\n!Fe\n!FE\n!fE\n!ff\n!Ff\n!FF\n!fF\n!fg\n!Fg\n!FG\n!fG\n!fh\n!Fh\n!FH\n!fH\n!fj\n!Fj\n!FJ\n!fJ\n!fk\n!Fk\n!FK\n!fK\n!fl\n!Fl\n!FL\n!fL\n!fm\n!Fm\n!FM\n!fM\n!fn\n!Fn\n!FN\n!fN\n!fo\n!Fo\n!FO\n!fO\n!fp\n!Fp\n!FP\n!fP\n!fq\n!Fq\n!FQ\n!fQ\n!fr\n!Fr\n!FR\n!fR\n!fs\n!Fs\n!FS\n!fS\n!ft\n!Ft\n!FT\n!fT\n!fu\n!Fu\n!FU\n!fU\n!fv\n!Fv\n!FV\n!fV\n!fw\n!Fw\n!FW\n!fW\n!fx\n!Fx\n!FX\n!fX\n!fy\n!Fy\n!FY\n!fY\n!fz\n!Fz\n!FZ\n!fZ\n!ga\n!Ga\n!GA\n!gA\n!gb\n!gB\n!gc\n!Gc\n!GC\n!gC\n!gd\n!Gd\n!GD\n!gD\n!ge\n!Ge\n!GE\n!gE\n!gf\n!Gf\n!GF\n!gF\n!gg\n!Gg\n!GG\n!gG\n!gh\n!Gh\n!GH\n!gH\n!gi\n!Gi\n!GI\n!gI\n!gj\n!Gj\n!GJ\n!gJ\n!gk\n!Gk\n!GK\n!gK\n!gl\n!Gl\n!GL\n!gL\n!gm\n!Gm\n!GM\n!gM\n!gn\n!Gn\n!GN\n!gN\n!gp\n!Gp\n!GP\n!gP\n!gq\n!Gq\n!GQ\n!gQ\n!gr\n!Gr\n!GR\n!gR\n!gs\n!Gs\n!GS\n!gS\n!gt\n!Gt\n!GT\n!gT\n!gu\n!Gu\n!GU\n!gU\n!gv\n!Gv\n!GV\n!gV\n!gw\n!Gw\n!GW\n!gW\n!gx\n!Gx\n!GX\n!gX\n!gy\n!Gy\n!GY\n!gY\n!gz\n!Gz\n!GZ\n!gZ\n!ha\n!Ha\n!HA\n!hA\n!hb\n!Hb\n!HB\n!hB\n!hc\n!Hc\n!HC\n!hC\n!hd\n!Hd\n!HD\n!hD\n!hf\n!Hf\n!HF\n!hF\n!hg\n!Hg\n!HG\n!hG\n!hh\n!Hh\n!HH\n!hH\n!hi\n!Hi\n!HI\n!hI\n!hj\n!Hj\n!HJ\n!hJ\n!hk\n!Hk\n!HK\n!hK\n!hl\n!Hl\n!HL\n!hL\n!hm\n!Hm\n!HM\n!hM\n!hn\n!Hn\n!HN\n!hN\n!ho\n!Ho\n!HO\n!hO\n!hp\n!Hp\n!HP\n!hP\n!hq\n!Hq\n!HQ\n!hQ\n!hs\n!Hs\n!HS\n!hS\n!ht\n!Ht\n!HT\n!hT\n!hu\n!Hu\n!HU\n!hU\n!hv\n!Hv\n!HV\n!hV\n!hw\n!Hw\n!HW\n!hW\n!hx\n!Hx\n!HX\n!hX\n!hy\n!Hy\n!HY\n!hY\n!hz\n!Hz\n!HZ\n!hZ\n!ia\n!Ia\n!IA\n!iA\n!ib\n!Ib\n!IB\n!iB\n!ic\n!Ic\n!IC\n!iC\n!iD\n!ie\n!Ie\n!iE\n!ig\n!Ig\n!IG\n!iG\n!ih\n!Ih\n!IH\n!iH\n!ii\n!Ii\n!II\n!iI\n!ij\n!Ij\n!IJ\n!iJ\n!ik\n!Ik\n!IK\n!iK\n!il\n!Il\n!IL\n!iL\n!im\n!Im\n!IM\n!iM\n!Io\n!iO\n!ip\n!Ip\n!iP\n!iq\n!Iq\n!IQ\n!iQ\n!ir\n!Ir\n!iR\n!iu\n!Iu\n!IU\n!iU\n!iv\n!Iv\n!IV\n!iV\n!iw\n!Iw\n!IW\n!iW\n!ix\n!Ix\n!IX\n!iX\n!iy\n!Iy\n!IY\n!iY\n!iz\n!Iz\n!IZ\n!iZ\n!ja\n!Ja\n!JA\n!jA\n!jb\n!Jb\n!JB\n!jB\n!jc\n!Jc\n!JC\n!jC\n!jd\n!Jd\n!JD\n!jD\n!je\n!Je\n!JE\n!jE\n!jf\n!Jf\n!JF\n!jF\n!jg\n!Jg\n!JG\n!jG\n!jh\n!Jh\n!JH\n!jH\n!ji\n!Ji\n!JI\n!jI\n!jj\n!Jj\n!JJ\n!jJ\n!jk\n!Jk\n!JK\n!jK\n!jl\n!Jl\n!JL\n!jL\n!jm\n!Jm\n!jM\n!jn\n!Jn\n!JN\n!jN\n!jo\n!Jo\n!JO\n!jO\n!jp\n!Jp\n!JP\n!jP\n!jq\n!Jq\n!JQ\n!jQ\n!jr\n!Jr\n!JR\n!jR\n!jt\n!Jt\n!JT\n!jT\n!ju\n!Ju\n!JU\n!jU\n!jv\n!Jv\n!JV\n!jV\n!jw\n!Jw\n!jW\n!jx\n!Jx\n!JX\n!jX\n!jy\n!Jy\n!JY\n!jY\n!jz\n!Jz\n!JZ\n!jZ\n!ka\n!Ka\n!KA\n!kA\n!kb\n!Kb\n!KB\n!kB\n!kc\n!Kc\n!KC\n!kC\n!kd\n!Kd\n!KD\n!kD\n!ke\n!Ke\n!KE\n!kE\n!kf\n!Kf\n!KF\n!kF\n!kg\n!Kg\n!KG\n!kG\n!kh\n!Kh\n!KH\n!kH\n!ki\n!Ki\n!KI\n!kI\n!kj\n!Kj\n!KJ\n!kJ\n!kk\n!Kk\n!KK\n!kK\n!kl\n!Kl\n!KL\n!kL\n!km\n!Km\n!KM\n!kM\n!kn\n!Kn\n!KN\n!kN\n!ko\n!Ko\n!KO\n!kO\n!kp\n!Kp\n!KP\n!kP\n!kq\n!Kq\n!KQ\n!kQ\n!kr\n!Kr\n!KR\n!kR\n!ks\n!Ks\n!KS\n!kS\n!kt\n!Kt\n!KT\n!kT\n!ku\n!Ku\n!KU\n!kU\n!kv\n!Kv\n!KV\n!kV\n!kw\n!Kw\n!KW\n!kW\n!kx\n!Kx\n!KX\n!kX\n!ky\n!Ky\n!KY\n!kY\n!kz\n!Kz\n!KZ\n!kZ\n!la\n!La\n!LA\n!lA\n!lb\n!Lb\n!lB\n!lc\n!Lc\n!LC\n!lC\n!ld\n!Ld\n!LD\n!lD\n!le\n!Le\n!LE\n!lE\n!lf\n!Lf\n!lF\n!lg\n!Lg\n!LG\n!lG\n!lh\n!Lh\n!LH\n!lH\n!Li\n!LI\n!lI\n!lj\n!Lj\n!LJ\n!lJ\n!lk\n!Lk\n!LK\n!lK\n!ll\n!Ll\n!LL\n!lL\n!lm\n!Lm\n!LM\n!lM\n!ln\n!Ln\n!LN\n!lN\n!lp\n!Lp\n!lP\n!lq\n!Lq\n!LQ\n!lQ\n!lr\n!Lr\n!LR\n!lR\n!Ls\n!lS\n!Lt\n!lT\n!lu\n!Lu\n!LU\n!lU\n!lv\n!Lv\n!LV\n!lV\n!lw\n!Lw\n!LW\n!lW\n!lx\n!Lx\n!LX\n!lX\n!ly\n!Ly\n!LY\n!lY\n!lz\n!Lz\n!LZ\n!lZ\n!ma\n!Ma\n!MA\n!mA\n!mb\n!mB\n!Mc\n!MC\n!mC\n!md\n!Md\n!MD\n!mD\n!mf\n!Mf\n!MF\n!mF\n!mg\n!Mg\n!MG\n!mG\n!mh\n!Mh\n!MH\n!mH\n!mi\n!Mi\n!MI\n!mI\n!mj\n!Mj\n!MJ\n!mJ\n!mk\n!Mk\n!MK\n!mK\n!ml\n!Ml\n!ML\n!mL\n!mm\n!Mm\n!MM\n!mM\n!mn\n!Mn\n!MN\n!mN\n!mo\n!Mo\n!MO\n!mO\n!mp\n!Mp\n!MP\n!mP\n!mq\n!Mq\n!MQ\n!mQ\n!mr\n!Mr\n!MR\n!mR\n!ms\n!Ms\n!MS\n!mS\n!mt\n!Mt\n!MT\n!mT\n!mu\n!Mu\n!MU\n!mU\n!mv\n!Mv\n!MV\n!mV\n!mw\n!Mw\n!MW\n!mW\n!mx\n!Mx\n!MX\n!mX\n!mz\n!Mz\n!MZ\n!mZ\n!na\n!Na\n!NA\n!nA\n!nb\n!Nb\n!NB\n!nB\n!nc\n!Nc\n!NC\n!nC\n!nd\n!Nd\n!ND\n!nD\n!ne\n!Ne\n!NE\n!nE\n!nf\n!Nf\n!NF\n!nF\n!ng\n!Ng\n!NG\n!nG\n!nh\n!Nh\n!NH\n!nH\n!ni\n!Ni\n!NI\n!nI\n!nj\n!Nj\n!NJ\n!nJ\n!nk\n!Nk\n!NK\n!nK\n!nl\n!Nl\n!NL\n!nL\n!nm\n!Nm\n!NM\n!nM\n!nn\n!Nn\n!NN\n!nN\n!np\n!Np\n!NP\n!nP\n!nq\n!Nq\n!NQ\n!nQ\n!nr\n!Nr\n!NR\n!nR\n!ns\n!Ns\n!NS\n!nS\n!nt\n!Nt\n!NT\n!nT\n!nu\n!Nu\n!NU\n!nU\n!nv\n!Nv\n!NV\n!nV\n!nw\n!Nw\n!NW\n!nW\n!nx\n!Nx\n!NX\n!nX\n!ny\n!Ny\n!NY\n!nY\n!nz\n!Nz\n!NZ\n!nZ\n!oa\n!Oa\n!OA\n!oA\n!ob\n!Ob\n!OB\n!oB\n!oc\n!Oc\n!OC\n!oC\n!od\n!Od\n!OD\n!oD\n!oe\n!Oe\n!OE\n!oE\n!Og\n!oG\n!oh\n!Oh\n!OH\n!oH\n!oi\n!Oi\n!OI\n!oI\n!oj\n!Oj\n!OJ\n!oJ\n!ol\n!Ol\n!OL\n!oL\n!om\n!Om\n!OM\n!oM\n!oo\n!Oo\n!OO\n!oO\n!Op\n!OP\n!oP\n!oq\n!Oq\n!OQ\n!oQ\n!os\n!Os\n!oS\n!ot\n!Ot\n!OT\n!oT\n!ou\n!Ou\n!OU\n!oU\n!ov\n!Ov\n!OV\n!oV\n!ow\n!Ow\n!OW\n!oW\n!ox\n!Ox\n!OX\n!oX\n!oy\n!Oy\n!OY\n!oY\n!oz\n!Oz\n!OZ\n!oZ\n!pa\n!Pa\n!PA\n!pA\n!pb\n!Pb\n!PB\n!pB\n!pc\n!Pc\n!PC\n!pC\n!pd\n!Pd\n!PD\n!pD\n!pe\n!Pe\n!PE\n!pE\n!pf\n!Pf\n!PF\n!pF\n!pg\n!Pg\n!PG\n!pG\n!ph\n!Ph\n!PH\n!pH\n!pi\n!Pi\n!PI\n!pI\n!pj\n!Pj\n!PJ\n!pJ\n!pk\n!Pk\n!PK\n!pK\n!pl\n!Pl\n!PL\n!pL\n!pm\n!Pm\n!PM\n!pM\n!pn\n!Pn\n!PN\n!pN\n!po\n!Po\n!PO\n!pO\n!pp\n!Pp\n!PP\n!pP\n!pq\n!Pq\n!PQ\n!pQ\n!ps\n!Ps\n!PS\n!pS\n!pt\n!Pt\n!PT\n!pT\n!pu\n!Pu\n!PU\n!pU\n!pv\n!Pv\n!PV\n!pV\n!pw\n!Pw\n!PW\n!pW\n!Px\n!PX\n!pX\n!py\n!Py\n!PY\n!pY\n!pz\n!Pz\n!PZ\n!pZ\n!qa\n!Qa\n!qA\n!qb\n!Qb\n!QB\n!qB\n!qc\n!Qc\n!QC\n!qC\n!qd\n!Qd\n!QD\n!qD\n!qe\n!Qe\n!QE\n!qE\n!qf\n!Qf\n!QF\n!qF\n!qg\n!Qg\n!QG\n!qG\n!qh\n!Qh\n!QH\n!qH\n!qi\n!Qi\n!QI\n!qI\n!qj\n!Qj\n!QJ\n!qJ\n!qk\n!Qk\n!QK\n!qK\n!ql\n!Ql\n!QL\n!qL\n!qm\n!Qm\n!QM\n!qM\n!qn\n!Qn\n!QN\n!qN\n!qo\n!Qo\n!QO\n!qO\n!qp\n!Qp\n!QP\n!qP\n!qq\n!Qq\n!QQ\n!qQ\n!qr\n!Qr\n!qR\n!qs\n!Qs\n!QS\n!qS\n!qt\n!Qt\n!QT\n!qT\n!qu\n!Qu\n!QU\n!qU\n!qv\n!Qv\n!QV\n!qV\n!qw\n!Qw\n!QW\n!qW\n!qx\n!Qx\n!QX\n!qX\n!qy\n!Qy\n!QY\n!qY\n!qz\n!Qz\n!QZ\n!qZ\n!ra\n!Ra\n!RA\n!rA\n!rb\n!Rb\n!RB\n!rB\n!rc\n!Rc\n!RC\n!rC\n!rd\n!Rd\n!RD\n!rD\n!rf\n!Rf\n!RF\n!rF\n!rg\n!Rg\n!RG\n!rG\n!rh\n!Rh\n!RH\n!rH\n!ri\n!Ri\n!RI\n!rI\n!rj\n!Rj\n!RJ\n!rJ\n!rk\n!Rk\n!RK\n!rK\n!rl\n!Rl\n!RL\n!rL\n!rm\n!Rm\n!RM\n!rM\n!rn\n!Rn\n!RN\n!rN\n!ro\n!Ro\n!RO\n!rO\n!rp\n!Rp\n!RP\n!rP\n!rq\n!Rq\n!RQ\n!rQ\n!rr\n!Rr\n!RR\n!rR\n!rs\n!Rs\n!RS\n!rS\n!rt\n!Rt\n!RT\n!rT\n!ru\n!Ru\n!rU\n!rv\n!Rv\n!RV\n!rV\n!rw\n!Rw\n!RW\n!rW\n!rx\n!Rx\n!RX\n!rX\n!ry\n!Ry\n!RY\n!rY\n!rz\n!Rz\n!RZ\n!rZ\n!sa\n!Sa\n!sA\n!sb\n!Sb\n!SB\n!sB\n!sc\n!Sc\n!SC\n!sC\n!sd\n!Sd\n!SD\n!sD\n!se\n!Se\n!SE\n!sE\n!sf\n!Sf\n!SF\n!sF\n!sg\n!Sg\n!SG\n!sG\n!sh\n!Sh\n!SH\n!sH\n!si\n!Si\n!SI\n!sI\n!sj\n!Sj\n!SJ\n!sJ\n!sk\n!Sk\n!SK\n!sK\n!sl\n!Sl\n!SL\n!sL\n!sm\n!Sm\n!SM\n!sM\n!sn\n!Sn\n!SN\n!sN\n!sp\n!Sp\n!SP\n!sP\n!sq\n!Sq\n!SQ\n!sQ\n!sr\n!Sr\n!SR\n!sR\n!ss\n!Ss\n!SS\n!sS\n!st\n!St\n!ST\n!sT\n!su\n!Su\n!SU\n!sU\n!sv\n!Sv\n!SV\n!sV\n!sw\n!Sw\n!SW\n!sW\n!sx\n!Sx\n!SX\n!sX\n!sy\n!Sy\n!SY\n!sY\n!sz\n!Sz\n!SZ\n!sZ\n!ta\n!Ta\n!TA\n!tA\n!tb\n!tB\n!tc\n!Tc\n!TC\n!tC\n!Td\n!TD\n!tD\n!te\n!Te\n!TE\n!tE\n!tf\n!Tf\n!TF\n!tF\n!tg\n!Tg\n!TG\n!tG\n!Th\n!TH\n!tH\n!ti\n!Ti\n!TI\n!tI\n!tj\n!Tj\n!TJ\n!tJ\n!tk\n!Tk\n!TK\n!tK\n!tl\n!Tl\n!tL\n!tm\n!Tm\n!TM\n!tM\n!tn\n!Tn\n!TN\n!tN\n!tp\n!Tp\n!TP\n!tP\n!tq\n!Tq\n!TQ\n!tQ\n!Tr\n!TR\n!tR\n!tt\n!Tt\n!TT\n!tT\n!tu\n!Tu\n!TU\n!tU\n!tv\n!Tv\n!TV\n!tV\n!tw\n!Tw\n!TW\n!tW\n!ty\n!Ty\n!TY\n!tY\n!tz\n!Tz\n!TZ\n!tZ\n!ua\n!Ua\n!UA\n!uA\n!ub\n!Ub\n!uB\n!uc\n!Uc\n!UC\n!uC\n!ud\n!Ud\n!UD\n!uD\n!ue\n!Ue\n!UE\n!uE\n!uf\n!Uf\n!UF\n!uF\n!ug\n!Ug\n!UG\n!uG\n!uh\n!Uh\n!UH\n!uH\n!uj\n!Uj\n!UJ\n!uJ\n!uk\n!Uk\n!UK\n!uK\n!Ul\n!UL\n!uL\n!um\n!Um\n!UM\n!uM\n!un\n!Un\n!UN\n!uN\n!uo\n!Uo\n!UO\n!uO\n!uq\n!Uq\n!UQ\n!uQ\n!ur\n!Ur\n!UR\n!uR\n!ut\n!Ut\n!UT\n!uT\n!uu\n!Uu\n!UU\n!uU\n!uv\n!Uv\n!UV\n!uV\n!uw\n!Uw\n!UW\n!uW\n!uy\n!Uy\n!UY\n!uY\n!uz\n!Uz\n!UZ\n!uZ\n!va\n!Va\n!VA\n!vA\n!vb\n!Vb\n!VB\n!vB\n!vc\n!Vc\n!VC\n!vC\n!vd\n!Vd\n!VD\n!vD\n!ve\n!Ve\n!VE\n!vE\n!vf\n!Vf\n!VF\n!vF\n!vg\n!Vg\n!VG\n!vG\n!vh\n!Vh\n!VH\n!vH\n!vi\n!Vi\n!VI\n!vI\n!vj\n!Vj\n!VJ\n!vJ\n!vk\n!Vk\n!vK\n!vl\n!Vl\n!VL\n!vL\n!vn\n!Vn\n!VN\n!vN\n!vo\n!Vo\n!VO\n!vO\n!vp\n!Vp\n!VP\n!vP\n!vq\n!Vq\n!VQ\n!vQ\n!vr\n!Vr\n!VR\n!vR\n!Vs\n!vS\n!vt\n!Vt\n!VT\n!vT\n!vu\n!Vu\n!VU\n!vU\n!vv\n!Vv\n!VV\n!vV\n!vw\n!Vw\n!VW\n!vW\n!vx\n!Vx\n!VX\n!vX\n!vy\n!Vy\n!VY\n!vY\n!vz\n!Vz\n!VZ\n!vZ\n!wa\n!Wa\n!WA\n!wA\n!wb\n!Wb\n!WB\n!wB\n!Wc\n!wC\n!wd\n!Wd\n!WD\n!wD\n!wf\n!Wf\n!WF\n!wF\n!wg\n!Wg\n!WG\n!wG\n!wh\n!Wh\n!WH\n!wH\n!wi\n!Wi\n!WI\n!wI\n!wj\n!Wj\n!WJ\n!wJ\n!wk\n!Wk\n!WK\n!wK\n!wl\n!Wl\n!WL\n!wL\n!wm\n!Wm\n!WM\n!wM\n!wn\n!Wn\n!WN\n!wN\n!wo\n!Wo\n!WO\n!wO\n!wp\n!Wp\n!WP\n!wP\n!wq\n!Wq\n!WQ\n!wQ\n!wr\n!Wr\n!WR\n!wR\n!ws\n!Ws\n!WS\n!wS\n!wt\n!Wt\n!WT\n!wT\n!wu\n!Wu\n!WU\n!wU\n!wv\n!Wv\n!WV\n!wV\n!ww\n!Ww\n!WW\n!wW\n!wx\n!Wx\n!WX\n!wX\n!wy\n!Wy\n!WY\n!wY\n!wz\n!Wz\n!WZ\n!wZ\n!xa\n!Xa\n!XA\n!xA\n!xb\n!Xb\n!XB\n!xB\n!xc\n!Xc\n!XC\n!xC\n!xd\n!Xd\n!XD\n!xD\n!xe\n!Xe\n!XE\n!xE\n!xf\n!Xf\n!XF\n!xF\n!xg\n!Xg\n!XG\n!xG\n!xh\n!Xh\n!XH\n!xH\n!xi\n!Xi\n!XI\n!xI\n!xj\n!Xj\n!XJ\n!xJ\n!xk\n!Xk\n!XK\n!xK\n!xl\n!Xl\n!XL\n!xL\n!xm\n!Xm\n!XM\n!xM\n!xn\n!Xn\n!XN\n!xN\n!xo\n!Xo\n!XO\n!xO\n!xp\n!Xp\n!XP\n!xP\n!xq\n!Xq\n!XQ\n!xQ\n!xr\n!Xr\n!XR\n!xR\n!xs\n!Xs\n!XS\n!xS\n!xt\n!Xt\n!XT\n!xT\n!xu\n!Xu\n!XU\n!xU\n!xv\n!Xv\n!XV\n!xV\n!xw\n!Xw\n!XW\n!xW\n!xx\n!Xx\n!XX\n!xX\n!xy\n!Xy\n!XY\n!xY\n!xz\n!Xz\n!XZ\n!xZ\n!ya\n!Ya\n!YA\n!yA\n!yb\n!Yb\n!YB\n!yB\n!yc\n!Yc\n!YC\n!yC\n!yd\n!Yd\n!YD\n!yD\n!ye\n!Ye\n!YE\n!yE\n!yf\n!Yf\n!YF\n!yF\n!yg\n!Yg\n!YG\n!yG\n!yh\n!Yh\n!YH\n!yH\n!yi\n!Yi\n!YI\n!yI\n!yj\n!Yj\n!YJ\n!yJ\n!yk\n!Yk\n!YK\n!yK\n!yl\n!Yl\n!YL\n!yL\n!ym\n!Ym\n!YM\n!yM\n!yn\n!Yn\n!YN\n!yN\n!yo\n!Yo\n!YO\n!yO\n!yp\n!Yp\n!YP\n!yP\n!yq\n!Yq\n!YQ\n!yQ\n!yr\n!Yr\n!YR\n!yR\n!ys\n!Ys\n!YS\n!yS\n!yt\n!Yt\n!YT\n!yT\n!yu\n!YU\n!yU\n!yv\n!Yv\n!YV\n!yV\n!yw\n!Yw\n!YW\n!yW\n!yx\n!Yx\n!YX\n!yX\n!yy\n!Yy\n!YY\n!yY\n!yz\n!Yz\n!YZ\n!yZ\n!za\n!Za\n!ZA\n!zA\n!zb\n!Zb\n!ZB\n!zB\n!zc\n!Zc\n!ZC\n!zC\n!zd\n!Zd\n!ZD\n!zD\n!ze\n!Ze\n!ZE\n!zE\n!zf\n!Zf\n!ZF\n!zF\n!zg\n!Zg\n!ZG\n!zG\n!zh\n!Zh\n!zH\n!zi\n!Zi\n!ZI\n!zI\n!zj\n!Zj\n!ZJ\n!zJ\n!zk\n!Zk\n!ZK\n!zK\n!zl\n!Zl\n!ZL\n!zL\n!zm\n!Zm\n!ZM\n!zM\n!zn\n!Zn\n!zN\n!zo\n!Zo\n!ZO\n!zO\n!zp\n!Zp\n!ZP\n!zP\n!zq\n!Zq\n!ZQ\n!zQ\n!zr\n!Zr\n!ZR\n!zR\n!zs\n!Zs\n!ZS\n!zS\n!zt\n!Zt\n!ZT\n!zT\n!zu\n!Zu\n!ZU\n!zU\n!zv\n!Zv\n!ZV\n!zV\n!zw\n!Zw\n!ZW\n!zW\n!zx\n!Zx\n!ZX\n!zX\n!zy\n!Zy\n!ZY\n!zY\n!zz\n!Zz\n!ZZ\n!zZ\n"
  },
  {
    "path": "resources/tvm/cp0.txt",
    "content": "{\"$schema\":\"./schema.json\",\"aliases\":[{\"alias_of\":\"XCHG_0I\",\"description\":\"<p>Same as <code>s1 XCHG0</code>.</p>\\n\",\"doc_fift\":\"SWAP\",\"doc_stack\":\"x y - y x\",\"mnemonic\":\"SWAP\",\"operands\":{\"i\":1}},{\"alias_of\":\"PUSH\",\"description\":\"<p>Same as <code>s0 PUSH</code>.</p>\\n\",\"doc_fift\":\"DUP\",\"doc_stack\":\"x - x x\",\"mnemonic\":\"DUP\",\"operands\":{\"i\":0}},{\"alias_of\":\"PUSH\",\"description\":\"<p>Same as <code>s1 PUSH</code>.</p>\\n\",\"doc_fift\":\"OVER\",\"doc_stack\":\"x y - x y x\",\"mnemonic\":\"OVER\",\"operands\":{\"i\":1}},{\"alias_of\":\"POP\",\"description\":\"<p>Same as <code>s0 POP</code>, discards the top-of-stack value.</p>\\n\",\"doc_fift\":\"DROP\",\"doc_stack\":\"x -\",\"mnemonic\":\"DROP\",\"operands\":{\"i\":0}},{\"alias_of\":\"POP\",\"description\":\"<p>Same as <code>s1 POP</code>.</p>\\n\",\"doc_fift\":\"NIP\",\"doc_stack\":\"x y - y\",\"mnemonic\":\"NIP\",\"operands\":{\"i\":1}},{\"alias_of\":\"BLKSWAP\",\"description\":\"<p>Rotates the three topmost pairs of stack entries.</p>\\n\",\"doc_fift\":\"ROT2\\n2ROT\",\"doc_stack\":\"a b c d e f - c d e f a b\",\"mnemonic\":\"ROT2\",\"operands\":{\"i\":1,\"j\":3}},{\"alias_of\":\"BLKSWAP\",\"description\":\"<p>Rotates the top <code>i+1</code> stack entries.\\nEquivalent to <code>1 [i+1] BLKSWAP</code>.</p>\\n\",\"doc_fift\":\"[i+1] ROLL\",\"doc_stack\":\"\",\"mnemonic\":\"ROLL\",\"operands\":{\"i\":0}},{\"alias_of\":\"BLKSWAP\",\"description\":\"<p>Rotates the top <code>i+1</code> stack entries in the other direction.\\nEquivalent to <code>[i+1] 1 BLKSWAP</code>.</p>\\n\",\"doc_fift\":\"[i+1] -ROLL\\n[i+1] ROLLREV\",\"doc_stack\":\"\",\"mnemonic\":\"ROLLREV\",\"operands\":{\"j\":0}},{\"alias_of\":\"TUPLE\",\"description\":\"<p>Pushes the only <em>Tuple</em> <code>t=()</code> of length zero.</p>\\n\",\"doc_fift\":\"NIL\",\"doc_stack\":\"- t\",\"mnemonic\":\"NIL\",\"operands\":{\"n\":0}},{\"alias_of\":\"TUPLE\",\"description\":\"<p>Creates a singleton <code>t:=(x)</code>, i.e., a <em>Tuple</em> of length one.</p>\\n\",\"doc_fift\":\"SINGLE\",\"doc_stack\":\"x - t\",\"mnemonic\":\"SINGLE\",\"operands\":{\"n\":1}},{\"alias_of\":\"TUPLE\",\"description\":\"<p>Creates pair <code>t:=(x,y)</code>.</p>\\n\",\"doc_fift\":\"PAIR\\nCONS\",\"doc_stack\":\"x y - t\",\"mnemonic\":\"PAIR\",\"operands\":{\"n\":2}},{\"alias_of\":\"TUPLE\",\"description\":\"<p>Creates triple <code>t:=(x,y,z)</code>.</p>\\n\",\"doc_fift\":\"TRIPLE\",\"doc_stack\":\"x y z - t\",\"mnemonic\":\"TRIPLE\",\"operands\":{\"n\":3}},{\"alias_of\":\"INDEX\",\"description\":\"<p>Returns the first element of a <em>Tuple</em>.</p>\\n\",\"doc_fift\":\"FIRST\\nCAR\",\"doc_stack\":\"t - x\",\"mnemonic\":\"FIRST\",\"operands\":{\"k\":0}},{\"alias_of\":\"INDEX\",\"description\":\"<p>Returns the second element of a <em>Tuple</em>.</p>\\n\",\"doc_fift\":\"SECOND\\nCDR\",\"doc_stack\":\"t - y\",\"mnemonic\":\"SECOND\",\"operands\":{\"k\":1}},{\"alias_of\":\"INDEX\",\"description\":\"<p>Returns the third element of a <em>Tuple</em>.</p>\\n\",\"doc_fift\":\"THIRD\",\"doc_stack\":\"t - z\",\"mnemonic\":\"THIRD\",\"operands\":{\"k\":2}},{\"alias_of\":\"UNTUPLE\",\"description\":\"<p>Unpacks a singleton <code>t=(x)</code>.</p>\\n\",\"doc_fift\":\"UNSINGLE\",\"doc_stack\":\"t - x\",\"mnemonic\":\"UNSINGLE\",\"operands\":{\"n\":1}},{\"alias_of\":\"UNTUPLE\",\"description\":\"<p>Unpacks a pair <code>t=(x,y)</code>.</p>\\n\",\"doc_fift\":\"UNPAIR\\nUNCONS\",\"doc_stack\":\"t - x y\",\"mnemonic\":\"UNPAIR\",\"operands\":{\"n\":2}},{\"alias_of\":\"UNTUPLE\",\"description\":\"<p>Unpacks a triple <code>t=(x,y,z)</code>.</p>\\n\",\"doc_fift\":\"UNTRIPLE\",\"doc_stack\":\"t - x y z\",\"mnemonic\":\"UNTRIPLE\",\"operands\":{\"n\":3}},{\"alias_of\":\"UNPACKFIRST\",\"description\":\"<p>Checks whether <code>t</code> is a <em>Tuple</em>. If not, throws a type check exception.</p>\\n\",\"doc_fift\":\"CHKTUPLE\",\"doc_stack\":\"t -\",\"mnemonic\":\"CHKTUPLE\",\"operands\":{\"k\":0}},{\"alias_of\":\"SETINDEX\",\"description\":\"<p>Sets the first component of <em>Tuple</em> <code>t</code> to <code>x</code> and returns the resulting <em>Tuple</em> <code>t'</code>.</p>\\n\",\"doc_fift\":\"SETFIRST\",\"doc_stack\":\"t x - t'\",\"mnemonic\":\"SETFIRST\",\"operands\":{\"k\":0}},{\"alias_of\":\"SETINDEX\",\"description\":\"<p>Sets the second component of <em>Tuple</em> <code>t</code> to <code>x</code> and returns the resulting <em>Tuple</em> <code>t'</code>.</p>\\n\",\"doc_fift\":\"SETSECOND\",\"doc_stack\":\"t x - t'\",\"mnemonic\":\"SETSECOND\",\"operands\":{\"k\":1}},{\"alias_of\":\"SETINDEX\",\"description\":\"<p>Sets the third component of <em>Tuple</em> <code>t</code> to <code>x</code> and returns the resulting <em>Tuple</em> <code>t'</code>.</p>\\n\",\"doc_fift\":\"SETTHIRD\",\"doc_stack\":\"t x - t'\",\"mnemonic\":\"SETTHIRD\",\"operands\":{\"k\":2}},{\"alias_of\":\"INDEXQ\",\"description\":\"<p>Returns the first element of a <em>Tuple</em>.</p>\\n\",\"doc_fift\":\"FIRSTQ\\nCARQ\",\"doc_stack\":\"t - x\",\"mnemonic\":\"FIRSTQ\",\"operands\":{\"k\":0}},{\"alias_of\":\"INDEXQ\",\"description\":\"<p>Returns the second element of a <em>Tuple</em>.</p>\\n\",\"doc_fift\":\"SECONDQ\\nCDRQ\",\"doc_stack\":\"t - y\",\"mnemonic\":\"SECONDQ\",\"operands\":{\"k\":1}},{\"alias_of\":\"INDEXQ\",\"description\":\"<p>Returns the third element of a <em>Tuple</em>.</p>\\n\",\"doc_fift\":\"THIRDQ\",\"doc_stack\":\"t - z\",\"mnemonic\":\"THIRDQ\",\"operands\":{\"k\":2}},{\"alias_of\":\"SETINDEXQ\",\"description\":\"<p>Sets the first component of <em>Tuple</em> <code>t</code> to <code>x</code> and returns the resulting <em>Tuple</em> <code>t'</code>.</p>\\n\",\"doc_fift\":\"SETFIRSTQ\",\"doc_stack\":\"t x - t'\",\"mnemonic\":\"SETFIRSTQ\",\"operands\":{\"k\":0}},{\"alias_of\":\"SETINDEXQ\",\"description\":\"<p>Sets the second component of <em>Tuple</em> <code>t</code> to <code>x</code> and returns the resulting <em>Tuple</em> <code>t'</code>.</p>\\n\",\"doc_fift\":\"SETSECONDQ\",\"doc_stack\":\"t x - t'\",\"mnemonic\":\"SETSECONDQ\",\"operands\":{\"k\":1}},{\"alias_of\":\"SETINDEXQ\",\"description\":\"<p>Sets the third component of <em>Tuple</em> <code>t</code> to <code>x</code> and returns the resulting <em>Tuple</em> <code>t'</code>.</p>\\n\",\"doc_fift\":\"SETTHIRDQ\",\"doc_stack\":\"t x - t'\",\"mnemonic\":\"SETTHIRDQ\",\"operands\":{\"k\":2}},{\"alias_of\":\"INDEX2\",\"description\":\"<p>Recovers <code>x=(t_2)_1</code>.</p>\\n\",\"doc_fift\":\"CADR\",\"doc_stack\":\"t - x\",\"mnemonic\":\"CADR\",\"operands\":{\"i\":1,\"j\":0}},{\"alias_of\":\"INDEX2\",\"description\":\"<p>Recovers <code>x=(t_2)_2</code>.</p>\\n\",\"doc_fift\":\"CDDR\",\"doc_stack\":\"t - x\",\"mnemonic\":\"CDDR\",\"operands\":{\"i\":1,\"j\":1}},{\"alias_of\":\"INDEX3\",\"description\":\"<p>Recovers <code>x=t_2_2_1</code>.</p>\\n\",\"doc_fift\":\"CADDR\",\"doc_stack\":\"t - x\",\"mnemonic\":\"CADDR\",\"operands\":{\"i\":1,\"j\":1,\"k\":0}},{\"alias_of\":\"INDEX3\",\"description\":\"<p>Recovers <code>x=t_2_2_2</code>.</p>\\n\",\"doc_fift\":\"CDDDR\",\"doc_stack\":\"t - x\",\"mnemonic\":\"CDDDR\",\"operands\":{\"i\":1,\"j\":1,\"k\":1}},{\"alias_of\":\"PUSHINT_4\",\"description\":\"\",\"doc_fift\":\"ZERO\\nFALSE\",\"doc_stack\":\"- 0\",\"mnemonic\":\"ZERO\",\"operands\":{\"i\":0}},{\"alias_of\":\"PUSHINT_4\",\"description\":\"\",\"doc_fift\":\"ONE\",\"doc_stack\":\"- 1\",\"mnemonic\":\"ONE\",\"operands\":{\"i\":1}},{\"alias_of\":\"PUSHINT_4\",\"description\":\"\",\"doc_fift\":\"TWO\",\"doc_stack\":\"- 2\",\"mnemonic\":\"TWO\",\"operands\":{\"i\":2}},{\"alias_of\":\"PUSHINT_4\",\"description\":\"\",\"doc_fift\":\"TEN\",\"doc_stack\":\"- 10\",\"mnemonic\":\"TEN\",\"operands\":{\"i\":10}},{\"alias_of\":\"PUSHINT_4\",\"description\":\"\",\"doc_fift\":\"TRUE\",\"doc_stack\":\"- -1\",\"mnemonic\":\"TRUE\",\"operands\":{\"i\":15}},{\"alias_of\":\"FITS\",\"description\":\"<p>Checks whether <code>x</code> is a ''boolean value'' (i.e., either 0 or -1).</p>\\n\",\"doc_fift\":\"CHKBOOL\",\"doc_stack\":\"x - x\",\"mnemonic\":\"CHKBOOL\",\"operands\":{\"c\":0}},{\"alias_of\":\"UFITS\",\"description\":\"<p>Checks whether <code>x</code> is a binary digit (i.e., zero or one).</p>\\n\",\"doc_fift\":\"CHKBIT\",\"doc_stack\":\"x - x\",\"mnemonic\":\"CHKBIT\",\"operands\":{\"c\":0}},{\"alias_of\":\"EQINT\",\"description\":\"<p>Checks whether an integer is zero. Corresponds to Forth's <code>0=</code>.</p>\\n\",\"doc_fift\":\"ISZERO\",\"doc_stack\":\"x - x=0\",\"mnemonic\":\"ISZERO\",\"operands\":{\"y\":0}},{\"alias_of\":\"LESSINT\",\"description\":\"<p>Checks whether an integer is negative. Corresponds to Forth's <code>0&lt;</code>.</p>\\n\",\"doc_fift\":\"ISNEG\",\"doc_stack\":\"x - x<0\",\"mnemonic\":\"ISNEG\",\"operands\":{\"y\":0}},{\"alias_of\":\"LESSINT\",\"description\":\"<p>Checks whether an integer is non-positive.</p>\\n\",\"doc_fift\":\"ISNPOS\",\"doc_stack\":\"x - x<=0\",\"mnemonic\":\"ISNPOS\",\"operands\":{\"y\":1}},{\"alias_of\":\"GTINT\",\"description\":\"<p>Checks whether an integer is positive. Corresponds to Forth's <code>0&gt;</code>.</p>\\n\",\"doc_fift\":\"ISPOS\",\"doc_stack\":\"x - x>0\",\"mnemonic\":\"ISPOS\",\"operands\":{\"y\":0}},{\"alias_of\":\"GTINT\",\"description\":\"<p>Checks whether an integer is non-negative.</p>\\n\",\"doc_fift\":\"ISNNEG\",\"doc_stack\":\"x - x >=0\",\"mnemonic\":\"ISNNEG\",\"operands\":{\"y\":-1}},{\"alias_of\":\"STSLICECONST\",\"description\":\"<p>Stores one binary zero.</p>\\n\",\"doc_fift\":\"STZERO\",\"doc_stack\":\"b - b'\",\"mnemonic\":\"STZERO\",\"operands\":{\"sss\":\"0\",\"x\":0,\"y\":0}},{\"alias_of\":\"STSLICECONST\",\"description\":\"<p>Stores one binary one.</p>\\n\",\"doc_fift\":\"STONE\",\"doc_stack\":\"b - b'\",\"mnemonic\":\"STONE\",\"operands\":{\"sss\":\"1\",\"x\":0,\"y\":0}},{\"alias_of\":\"PLDREFIDX\",\"description\":\"<p>Preloads the first cell reference of a <em>Slice</em>.</p>\\n\",\"doc_fift\":\"PLDREF\",\"doc_stack\":\"s - c\",\"mnemonic\":\"PLDREF\",\"operands\":{\"n\":0}},{\"alias_of\":\"SETCONTARGS_N\",\"description\":\"<p>Sets <code>c.nargs</code> to <code>n</code> plus the current depth of <code>c</code>'s stack, where <code>0 &lt;= n &lt;= 14</code>. If <code>c.nargs</code> is already set to a non-negative value, does nothing.</p>\\n\",\"doc_fift\":\"[n] SETNUMARGS\",\"doc_stack\":\"c - c'\",\"mnemonic\":\"SETNUMARGS\",\"operands\":{\"r\":0}},{\"alias_of\":\"SETCONTARGS_N\",\"description\":\"<p>Pushes <code>0 &lt;= r &lt;= 15</code> values <code>x_1...x_r</code> into the stack of (a copy of) the continuation <code>c</code>, starting with <code>x_1</code>. If the final depth of <code>c</code>'s stack turns out to be greater than <code>c.nargs</code>, a stack overflow exception is generated.</p>\\n\",\"doc_fift\":\"[r] -1 SETCONTARGS\",\"doc_stack\":\"x_1 x_2...x_r c - c'\",\"mnemonic\":\"SETCONTARGS\",\"operands\":{\"n\":-1}},{\"alias_of\":\"BLESSARGS\",\"description\":\"<p>Also transforms a <em>Slice</em> <code>s</code> into a <em>Continuation</em> <code>c</code>, but sets <code>c.nargs</code> to <code>0 &lt;= n &lt;= 14</code>.</p>\\n\",\"doc_fift\":\"[n] BLESSNUMARGS\",\"doc_stack\":\"s - c\",\"mnemonic\":\"BLESSNUMARGS\",\"operands\":{\"r\":0}},{\"alias_of\":\"PUSHCTR\",\"description\":\"<p>Pushes the ''global data root'' cell reference, thus enabling access to persistent smart-contract data.</p>\\n\",\"doc_fift\":\"c4 PUSHCTR\\nc4 PUSH\",\"doc_stack\":\"- x\",\"mnemonic\":\"PUSHROOT\",\"operands\":{\"i\":4}},{\"alias_of\":\"POPCTR\",\"description\":\"<p>Sets the ''global data root'' cell reference, thus allowing modification of persistent smart-contract data.</p>\\n\",\"doc_fift\":\"c4 POPCTR\\nc4 POP\",\"doc_stack\":\"x -\",\"mnemonic\":\"POPROOT\",\"operands\":{\"i\":4}},{\"alias_of\":\"NULL\",\"description\":\"<p>Returns a new empty dictionary.\\nIt is an alternative mnemonics for <code>PUSHNULL</code>.</p>\\n\",\"doc_fift\":\"NEWDICT\",\"doc_stack\":\" - D\",\"mnemonic\":\"NEWDICT\",\"operands\":{}},{\"alias_of\":\"ISNULL\",\"description\":\"<p>Checks whether dictionary <code>D</code> is empty, and returns <code>-1</code> or <code>0</code> accordingly.\\nIt is an alternative mnemonics for <code>ISNULL</code>.</p>\\n\",\"doc_fift\":\"DICTEMPTY\",\"doc_stack\":\"D - ?\",\"mnemonic\":\"DICTEMPTY\",\"operands\":{}},{\"alias_of\":\"STSLICE\",\"description\":\"<p>Stores a <em>Slice</em>-represented dictionary <code>s</code> into <em>Builder</em> <code>b</code>.\\nIt is actually a synonym for <code>STSLICE</code>.</p>\\n\",\"doc_fift\":\"STDICTS\\n\",\"doc_stack\":\"s b - b'\",\"mnemonic\":\"STDICTS\",\"operands\":{}},{\"alias_of\":\"GETPARAM\",\"description\":\"<p>Returns the current Unix time as an <em>Integer</em>. If it is impossible to recover the requested value starting from <code>c7</code>, throws a type checking or range checking exception as appropriate.\\nEquivalent to <code>3 GETPARAM</code>.</p>\\n\",\"doc_fift\":\"NOW\",\"doc_stack\":\" - x\",\"mnemonic\":\"NOW\",\"operands\":{\"i\":3}},{\"alias_of\":\"GETPARAM\",\"description\":\"<p>Returns the starting logical time of the current block.\\nEquivalent to <code>4 GETPARAM</code>.</p>\\n\",\"doc_fift\":\"BLOCKLT\",\"doc_stack\":\" - x\",\"mnemonic\":\"BLOCKLT\",\"operands\":{\"i\":4}},{\"alias_of\":\"GETPARAM\",\"description\":\"<p>Returns the logical time of the current transaction.\\nEquivalent to <code>5 GETPARAM</code>.</p>\\n\",\"doc_fift\":\"LTIME\",\"doc_stack\":\" - x\",\"mnemonic\":\"LTIME\",\"operands\":{\"i\":5}},{\"alias_of\":\"GETPARAM\",\"description\":\"<p>Returns the current random seed as an unsigned 256-bit <em>Integer</em>.\\nEquivalent to <code>6 GETPARAM</code>.</p>\\n\",\"doc_fift\":\"RANDSEED\",\"doc_stack\":\" - x\",\"mnemonic\":\"RANDSEED\",\"operands\":{\"i\":6}},{\"alias_of\":\"GETPARAM\",\"description\":\"<p>Returns the remaining balance of the smart contract as a <em>Tuple</em> consisting of an <em>Integer</em> (the remaining Gram balance in nanograms) and a <em>Maybe Cell</em> (a dictionary with 32-bit keys representing the balance of ''extra currencies'').\\nEquivalent to <code>7 GETPARAM</code>.\\nNote that <code>RAW</code> primitives such as <code>SENDRAWMSG</code> do not update this field.</p>\\n\",\"doc_fift\":\"BALANCE\",\"doc_stack\":\" - t\",\"mnemonic\":\"BALANCE\",\"operands\":{\"i\":7}},{\"alias_of\":\"GETPARAM\",\"description\":\"<p>Returns the internal address of the current smart contract as a <em>Slice</em> with a <code>MsgAddressInt</code>. If necessary, it can be parsed further using primitives such as <code>PARSEMSGADDR</code> or <code>REWRITESTDADDR</code>.\\nEquivalent to <code>8 GETPARAM</code>.</p>\\n\",\"doc_fift\":\"MYADDR\",\"doc_stack\":\" - s\",\"mnemonic\":\"MYADDR\",\"operands\":{\"i\":8}},{\"alias_of\":\"GETPARAM\",\"description\":\"<p>Returns the <em>Maybe Cell</em> <code>D</code> with the current global configuration dictionary. Equivalent to <code>9 GETPARAM </code>.</p>\\n\",\"doc_fift\":\"CONFIGROOT\",\"doc_stack\":\" - D\",\"mnemonic\":\"CONFIGROOT\",\"operands\":{\"i\":9}},{\"alias_of\":\"GETPARAM\",\"description\":\"<p>Retrieves code of smart-contract from c7. Equivalent to <code>10 GETPARAM </code>.</p>\\n\",\"doc_fift\":\"MYCODE\",\"doc_stack\":\" - c\",\"mnemonic\":\"MYCODE\",\"operands\":{\"i\":10}},{\"alias_of\":\"GETPARAM\",\"description\":\"<p>Retrieves value of incoming message from c7. Equivalent to <code>11 GETPARAM </code>.</p>\\n\",\"doc_fift\":\"INCOMINGVALUE\",\"doc_stack\":\" - t\",\"mnemonic\":\"INCOMINGVALUE\",\"operands\":{\"i\":11}},{\"alias_of\":\"GETPARAM\",\"description\":\"<p>Retrieves value of storage phase fees from c7. Equivalent to <code>12 GETPARAM </code>.</p>\\n\",\"doc_fift\":\"STORAGEFEES\",\"doc_stack\":\" - i\",\"mnemonic\":\"STORAGEFEES\",\"operands\":{\"i\":12}},{\"alias_of\":\"GETPARAM\",\"description\":\"<p>Retrives PrevBlocksInfo: <code>[last_mc_blocks, prev_key_block]</code> from c7. Equivalent to <code>13 GETPARAM </code>.</p>\\n\",\"doc_fift\":\"PREVBLOCKSINFOTUPLE\",\"doc_stack\":\" - t\",\"mnemonic\":\"PREVBLOCKSINFOTUPLE\",\"operands\":{\"i\":13}},{\"alias_of\":\"GETPARAM\",\"description\":\"<p>Retrives tuple that contains some config parameters as cell slices. If the parameter is absent from the config, the value is null. Values:</p>\\n<ul>\\n<li><strong>0</strong>: <code>StoragePrices</code> from <code>ConfigParam 18</code>. Not the whole dict, but only the one StoragePrices entry (one which corresponds to the current time).\\n<ul>\\n<li><strong>1</strong>: <code>ConfigParam 19</code> (global id).</li>\\n<li><strong>2</strong>: <code>ConfigParam 20</code> (mc gas prices).</li>\\n<li><strong>3</strong>: <code>ConfigParam 21</code> (gas prices).</li>\\n<li><strong>4</strong>: <code>ConfigParam 24</code> (mc fwd fees).</li>\\n<li><strong>5</strong>: <code>ConfigParam 25</code> (fwd fees).</li>\\n<li><strong>6</strong>: <code>ConfigParam 43</code> (size limits).</li>\\n</ul>\\n</li>\\n</ul>\\n\",\"doc_fift\":\"UNPACKEDCONFIGTUPLE\",\"doc_stack\":\" - t\",\"mnemonic\":\"UNPACKEDCONFIGTUPLE\",\"operands\":{\"i\":14}},{\"alias_of\":\"GETPARAM\",\"description\":\"<p>Retrives current debt for storage fee (nanotons).</p>\\n\",\"doc_fift\":\"DUEPAYMENT\",\"doc_stack\":\" - t\",\"mnemonic\":\"DUEPAYMENT\",\"operands\":{\"i\":15}},{\"alias_of\":\"INMSGPARAM\",\"description\":\"<p>Retrives <code>bounce</code> flag of incoming message.</p>\\n\",\"doc_fift\":\"INMSG_BOUNCE\",\"doc_stack\":\" - x\",\"mnemonic\":\"INMSG_BOUNCE\",\"operands\":{\"i\":0}},{\"alias_of\":\"INMSGPARAM\",\"description\":\"<p>Retrives <code>bounced</code> flag of incoming message.</p>\\n\",\"doc_fift\":\"INMSG_BOUNCED\",\"doc_stack\":\" - x\",\"mnemonic\":\"INMSG_BOUNCED\",\"operands\":{\"i\":1}},{\"alias_of\":\"INMSGPARAM\",\"description\":\"<p>Retrives <code>src</code> flag of incoming message.</p>\\n\",\"doc_fift\":\"INMSG_SRC\",\"doc_stack\":\" - x\",\"mnemonic\":\"INMSG_SRC\",\"operands\":{\"i\":2}},{\"alias_of\":\"INMSGPARAM\",\"description\":\"<p>Retrives <code>fwd_fee</code> field of incoming message.</p>\\n\",\"doc_fift\":\"INMSG_FWDFEE\",\"doc_stack\":\" - x\",\"mnemonic\":\"INMSG_FWDFEE\",\"operands\":{\"i\":3}},{\"alias_of\":\"INMSGPARAM\",\"description\":\"<p>Retrives <code>lt</code> field of incoming message.</p>\\n\",\"doc_fift\":\"INMSG_LT\",\"doc_stack\":\" - x\",\"mnemonic\":\"INMSG_LT\",\"operands\":{\"i\":4}},{\"alias_of\":\"INMSGPARAM\",\"description\":\"<p>Retrives <code>utime</code> field of incoming message.</p>\\n\",\"doc_fift\":\"INMSG_UTIME\",\"doc_stack\":\" - x\",\"mnemonic\":\"INMSG_UTIME\",\"operands\":{\"i\":5}},{\"alias_of\":\"INMSGPARAM\",\"description\":\"<p>Retrives original value of the message. This is sometimes different from the value in <code>INCOMINGVALUE</code> and TVM stack because of storage fees.</p>\\n\",\"doc_fift\":\"INMSG_ORIGVALUE\",\"doc_stack\":\" - x\",\"mnemonic\":\"INMSG_ORIGVALUE\",\"operands\":{\"i\":6}},{\"alias_of\":\"INMSGPARAM\",\"description\":\"<p>Retrives value of the message after deducting storage fees. This is same as in <code>INCOMINGVALUE</code> and TVM stack.</p>\\n\",\"doc_fift\":\"INMSG_VALUE\",\"doc_stack\":\" - x\",\"mnemonic\":\"INMSG_VALUE\",\"operands\":{\"i\":7}},{\"alias_of\":\"INMSGPARAM\",\"description\":\"<p>Same as in <code>INCOMINGVALUE</code>.</p>\\n\",\"doc_fift\":\"INMSG_VALUEEXTRA\",\"doc_stack\":\" - x\",\"mnemonic\":\"INMSG_VALUEEXTRA\",\"operands\":{\"i\":8}},{\"alias_of\":\"INMSGPARAM\",\"description\":\"<p>Retrieves <code>init</code> field of the incoming message.</p>\\n\",\"doc_fift\":\"INMSG_STATEINIT\",\"doc_stack\":\" - x\",\"mnemonic\":\"INMSG_STATEINIT\",\"operands\":{\"i\":9}},{\"alias_of\":\"DEBUG\",\"description\":\"<p>Dumps the stack (at most the top 255 values) and shows the total stack depth. Does nothing on production versions of TVM.</p>\\n\",\"doc_fift\":\"DUMPSTK\",\"doc_stack\":\"-\",\"mnemonic\":\"DUMPSTK\",\"operands\":{\"i\":0,\"j\":0}},{\"alias_of\":\"DEBUG\",\"description\":\"<p>Dumps slice with length divisible by 8 from top of stack as a string. Does nothing on production versions of TVM.</p>\\n\",\"doc_fift\":\"STRDUMP\",\"doc_stack\":\"-\",\"mnemonic\":\"STRDUMP\",\"operands\":{\"i\":1,\"j\":4}},{\"alias_of\":\"DEBUG\",\"description\":\"<p>Dumps slice with length divisible by 8 from top of stack as a string. Does nothing on production versions of TVM.</p>\\n\",\"doc_fift\":\"s[j] DUMP\",\"doc_stack\":\"-\",\"mnemonic\":\"DUMP\",\"operands\":{\"i\":2}},{\"alias_of\":\"SETCP\",\"description\":\"<p>Selects TVM (test) codepage zero as described in this document.</p>\\n\",\"doc_fift\":\"SETCP0\",\"doc_stack\":\"-\",\"mnemonic\":\"SETCP0\",\"operands\":{\"n\":0}}],\"instructions\":[{\"bytecode\":{\"operands\":[],\"prefix\":\"00\",\"tlb\":\"#00\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_basic\",\"description\":\"<p>Does nothing.</p>\\n\",\"fift\":\"NOP\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"00\",\"stack\":\"-\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_nop\",\"line\":28,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"NOP\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":1,\"name\":\"i\",\"size\":4,\"type\":\"uint\"}],\"operands_range_check\":{\"from\":1,\"length\":4,\"to\":15},\"prefix\":\"0\",\"tlb\":\"#0 i:(## 4) {1 <= i}\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_basic\",\"description\":\"<p>Interchanges <code>s0</code> with <code>s[i]</code>, <code>1 &lt;= i &lt;= 15</code>.</p>\\n\",\"fift\":\"s[i] XCHG0\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"0i\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_xchg0\",\"line\":43,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"XCHG_0I\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":1,\"name\":\"i\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"j\",\"size\":4,\"type\":\"uint\"}],\"operands_range_check\":{\"from\":1,\"length\":4,\"to\":15},\"prefix\":\"10\",\"tlb\":\"#10 i:(## 4) j:(## 4) {1 <= i} {i + 1 <= j}\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_basic\",\"description\":\"<p>Interchanges <code>s[i]</code> with <code>s[j]</code>, <code>1 &lt;= i &lt; j &lt;= 15</code>.</p>\\n\",\"fift\":\"s[i] s[j] XCHG\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"10ij\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_xchg\",\"line\":61,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"XCHG_IJ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":255,\"min_value\":0,\"name\":\"i\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"11\",\"tlb\":\"#11 ii:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_basic\",\"description\":\"<p>Interchanges <code>s0</code> with <code>s[ii]</code>, <code>0 &lt;= ii &lt;= 255</code>.</p>\\n\",\"fift\":\"s0 [ii] s() XCHG\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"11ii\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_xchg0_l\",\"line\":52,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"XCHG_0I_LONG\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":2,\"name\":\"i\",\"size\":4,\"type\":\"uint\"}],\"operands_range_check\":{\"from\":2,\"length\":4,\"to\":15},\"prefix\":\"1\",\"tlb\":\"#1 i:(## 4) {2 <= i}\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_basic\",\"description\":\"<p>Interchanges <code>s1</code> with <code>s[i]</code>, <code>2 &lt;= i &lt;= 15</code>.</p>\\n\",\"fift\":\"s1 s[i] XCHG\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"1i\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_xchg1\",\"line\":83,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"XCHG_1I\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"2\",\"tlb\":\"#2 i:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_basic\",\"description\":\"<p>Pushes a copy of the old <code>s[i]</code> into the stack.</p>\\n\",\"fift\":\"s[i] PUSH\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"2i\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_push\",\"line\":109,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"PUSH\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"3\",\"tlb\":\"#3 i:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_basic\",\"description\":\"<p>Pops the old <code>s0</code> value into the old <code>s[i]</code>.</p>\\n\",\"fift\":\"s[i] POP\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"3i\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_pop\",\"line\":143,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"POP\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"j\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"k\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"4\",\"tlb\":\"#4 i:uint4 j:uint4 k:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>s2 s[i] XCHG</code> <code>s1 s[j] XCHG</code> <code>s[k] XCHG0</code>.</p>\\n\",\"fift\":\"s[i] s[j] s[k] XCHG3\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"4ijk\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_xchg3\",\"line\":204,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"XCHG3\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"j\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"50\",\"tlb\":\"#50 i:uint4 j:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>s1 s[i] XCHG</code> <code>s[j] XCHG0</code>.</p>\\n\",\"fift\":\"s[i] s[j] XCHG2\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"50ij\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_xchg2\",\"line\":163,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"XCHG2\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"j\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"51\",\"tlb\":\"#51 i:uint4 j:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>s[i] XCHG0</code> <code>s[j] PUSH</code>.</p>\\n\",\"fift\":\"s[i] s[j] XCPU\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"51ij\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_xcpu\",\"line\":173,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"XCPU\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"},{\"type\":\"add\",\"value\":1}],\"max_value\":15,\"min_value\":0,\"name\":\"j\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"52\",\"tlb\":\"#52 i:uint4 j:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>s[i] PUSH</code> <code>SWAP</code> <code>s[j] XCHG0</code>.</p>\\n\",\"fift\":\"s[i] s[j-1] PUXC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"52ij\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_puxc\",\"line\":183,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"PUXC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"j\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"53\",\"tlb\":\"#53 i:uint4 j:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>s[i] PUSH</code> <code>s[j+1] PUSH</code>.</p>\\n\",\"fift\":\"s[i] s[j] PUSH2\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"53ij\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_push2\",\"line\":194,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"PUSH2\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"j\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"k\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"540\",\"tlb\":\"#540 i:uint4 j:uint4 k:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Long form of <code>XCHG3</code>.</p>\\n\",\"fift\":\"s[i] s[j] s[k] XCHG3_l\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"540ijk\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_xchg3\",\"line\":204,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"XCHG3_ALT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"j\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"k\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"541\",\"tlb\":\"#541 i:uint4 j:uint4 k:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>s[i] s[j] XCHG2</code> <code>s[k] PUSH</code>.</p>\\n\",\"fift\":\"s[i] s[j] s[k] XC2PU\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"541ijk\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_xc2pu\",\"line\":215,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"XC2PU\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"j\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"},{\"type\":\"add\",\"value\":1}],\"max_value\":15,\"min_value\":0,\"name\":\"k\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"542\",\"tlb\":\"#542 i:uint4 j:uint4 k:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>s1 s[i] XCHG</code> <code>s[j] s[k-1] PUXC</code>.</p>\\n\",\"fift\":\"s[i] s[j] s[k-1] XCPUXC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"542ijk\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_xcpuxc\",\"line\":226,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"XCPUXC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"j\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"k\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"543\",\"tlb\":\"#543 i:uint4 j:uint4 k:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>s[i] XCHG0</code> <code>s[j] s[k] PUSH2</code>.</p>\\n\",\"fift\":\"s[i] s[j] s[k] XCPU2\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"543ijk\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_xc2pu\",\"line\":215,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"XCPU2\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"},{\"type\":\"add\",\"value\":1}],\"max_value\":15,\"min_value\":0,\"name\":\"j\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"},{\"type\":\"add\",\"value\":1}],\"max_value\":15,\"min_value\":0,\"name\":\"k\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"544\",\"tlb\":\"#544 i:uint4 j:uint4 k:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>s[i] PUSH</code> <code>s2 XCHG0</code> <code>s[j] s[k] XCHG2</code>.</p>\\n\",\"fift\":\"s[i] s[j-1] s[k-1] PUXC2\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"544ijk\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_puxc2\",\"line\":249,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"PUXC2\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"},{\"type\":\"add\",\"value\":1}],\"max_value\":15,\"min_value\":0,\"name\":\"j\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"},{\"type\":\"add\",\"value\":1}],\"max_value\":15,\"min_value\":0,\"name\":\"k\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"545\",\"tlb\":\"#545 i:uint4 j:uint4 k:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>s[i] s[j-1] PUXC</code> <code>s[k] PUSH</code>.</p>\\n\",\"fift\":\"s[i] s[j-1] s[k-1] PUXCPU\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"545ijk\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_puxcpu\",\"line\":261,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"PUXCPU\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"},{\"type\":\"add\",\"value\":1}],\"max_value\":15,\"min_value\":0,\"name\":\"j\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"},{\"type\":\"add\",\"value\":2}],\"max_value\":15,\"min_value\":0,\"name\":\"k\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"546\",\"tlb\":\"#546 i:uint4 j:uint4 k:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>s[i] PUSH</code> <code>SWAP</code> <code>s[j] s[k-1] PUXC</code>.</p>\\n\",\"fift\":\"s[i] s[j-1] s[k-2] PU2XC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"546ijk\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_puxc2\",\"line\":249,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"PU2XC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"j\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":15,\"min_value\":0,\"name\":\"k\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"547\",\"tlb\":\"#547 i:uint4 j:uint4 k:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>s[i] PUSH</code> <code>s[j+1] s[k+1] PUSH2</code>.</p>\\n\",\"fift\":\"s[i] s[j] s[k] PUSH3\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"547ijk\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_push3\",\"line\":286,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"PUSH3\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"},{\"type\":\"add\",\"value\":1}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"stack\"},{\"type\":\"add\",\"value\":1}],\"max_value\":15,\"min_value\":0,\"name\":\"j\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"55\",\"tlb\":\"#55 i:uint4 j:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Permutes two blocks <code>s[j+i+1] ... s[j+1]</code> and <code>s[j] ... s0</code>.\\n<code>0 &lt;= i,j &lt;= 15</code>\\nEquivalent to <code>[i+1] [j+1] REVERSE</code> <code>[j+1] 0 REVERSE</code> <code>[i+j+2] 0 REVERSE</code>.</p>\\n\",\"fift\":\"[i+1] [j+1] BLKSWAP\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"55ij\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_blkswap\",\"line\":299,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"BLKSWAP\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":255,\"min_value\":0,\"name\":\"i\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"56\",\"tlb\":\"#56 ii:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Pushes a copy of the old <code>s[ii]</code> into the stack.\\n<code>0 &lt;= ii &lt;= 255</code></p>\\n\",\"fift\":\"[ii] s() PUSH\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"56ii\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_push_l\",\"line\":118,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"PUSH_LONG\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"stack\"}],\"max_value\":255,\"min_value\":0,\"name\":\"i\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"57\",\"tlb\":\"#57 ii:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Pops the old <code>s0</code> value into the old <code>s[ii]</code>.\\n<code>0 &lt;= ii &lt;= 255</code></p>\\n\",\"fift\":\"[ii] s() POP\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"57ii\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_pop_l\",\"line\":152,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"POP_LONG\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"58\",\"tlb\":\"#58\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>1 2 BLKSWAP</code> or to <code>s2 s1 XCHG2</code>.</p>\\n\",\"fift\":\"ROT\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"58\",\"stack\":\"a b c - b c a\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_rot\",\"line\":308,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"ROT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"59\",\"tlb\":\"#59\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>2 1 BLKSWAP</code> or to <code>s2 s2 XCHG2</code>.</p>\\n\",\"fift\":\"ROTREV\\n-ROT\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"59\",\"stack\":\"a b c - c a b\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_rotrev\",\"line\":317,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"ROTREV\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"5A\",\"tlb\":\"#5A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>2 2 BLKSWAP</code> or to <code>s3 s2 XCHG2</code>.</p>\\n\",\"fift\":\"SWAP2\\n2SWAP\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"5A\",\"stack\":\"a b c d - c d a b\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_2swap\",\"line\":326,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"SWAP2\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"5B\",\"tlb\":\"#5B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>DROP</code> <code>DROP</code>.</p>\\n\",\"fift\":\"DROP2\\n2DROP\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"5B\",\"stack\":\"a b - \"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_2drop\",\"line\":335,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"DROP2\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"5C\",\"tlb\":\"#5C\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>s1 s0 PUSH2</code>.</p>\\n\",\"fift\":\"DUP2\\n2DUP\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"5C\",\"stack\":\"a b - a b a b\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_2dup\",\"line\":344,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"DUP2\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"5D\",\"tlb\":\"#5D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>s3 s2 PUSH2</code>.</p>\\n\",\"fift\":\"OVER2\\n2OVER\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"5D\",\"stack\":\"a b c d - a b c d a b\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_2over\",\"line\":353,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"OVER2\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"j\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"5E\",\"tlb\":\"#5E i:uint4 j:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Reverses the order of <code>s[j+i+1] ... s[j]</code>.</p>\\n\",\"fift\":\"[i+2] [j] REVERSE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"5Eij\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_reverse\",\"line\":362,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"REVERSE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"5F0\",\"tlb\":\"#5F0 i:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>DROP</code> performed <code>i</code> times.</p>\\n\",\"fift\":\"[i] BLKDROP\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"5F0i\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_blkdrop\",\"line\":371,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"BLKDROP\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":1,\"name\":\"i\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"j\",\"size\":4,\"type\":\"uint\"}],\"operands_range_check\":{\"from\":1,\"length\":4,\"to\":15},\"prefix\":\"5F\",\"tlb\":\"#5F i:(## 4) j:uint4 {1 <= i}\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>PUSH s(j)</code> performed <code>i</code> times.\\n<code>1 &lt;= i &lt;= 15</code>, <code>0 &lt;= j &lt;= 15</code>.</p>\\n\",\"fift\":\"[i] [j] BLKPUSH\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"5Fij\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_blkpush\",\"line\":389,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"BLKPUSH\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"60\",\"tlb\":\"#60\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Pops integer <code>i</code> from the stack, then performs <code>s[i] PUSH</code>.</p>\\n\",\"fift\":\"PICK\\nPUSHX\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"60\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_pick\",\"line\":400,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"PICK\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"61\",\"tlb\":\"#61\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Pops integer <code>i</code> from the stack, then performs <code>1 [i] BLKSWAP</code>.</p>\\n\",\"fift\":\"ROLLX\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"61\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_roll\",\"line\":410,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"ROLLX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"62\",\"tlb\":\"#62\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Pops integer <code>i</code> from the stack, then performs <code>[i] 1 BLKSWAP</code>.</p>\\n\",\"fift\":\"-ROLLX\\nROLLREVX\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"62\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_rollrev\",\"line\":423,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"-ROLLX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"63\",\"tlb\":\"#63\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Pops integers <code>i</code>,<code>j</code> from the stack, then performs <code>[i] [j] BLKSWAP</code>.</p>\\n\",\"fift\":\"BLKSWX\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"63\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_blkswap_x\",\"line\":436,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"BLKSWX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"64\",\"tlb\":\"#64\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Pops integers <code>i</code>,<code>j</code> from the stack, then performs <code>[i] [j] REVERSE</code>.</p>\\n\",\"fift\":\"REVX\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"64\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_reverse_x\",\"line\":452,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"REVX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"65\",\"tlb\":\"#65\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Pops integer <code>i</code> from the stack, then performs <code>[i] BLKDROP</code>.</p>\\n\",\"fift\":\"DROPX\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"65\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_drop_x\",\"line\":464,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"DROPX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"66\",\"tlb\":\"#66\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Equivalent to <code>SWAP</code> <code>OVER</code> or to <code>s1 s1 XCPU</code>.</p>\\n\",\"fift\":\"TUCK\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"66\",\"stack\":\"a b - b a b\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_tuck\",\"line\":474,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"TUCK\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"67\",\"tlb\":\"#67\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Pops integer <code>i</code> from the stack, then performs <code>s[i] XCHG</code>.</p>\\n\",\"fift\":\"XCHGX\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"67\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_xchg_x\",\"line\":483,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"XCHGX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"68\",\"tlb\":\"#68\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Pushes the current depth of the stack.</p>\\n\",\"fift\":\"DEPTH\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"68\",\"stack\":\"- depth\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_depth\",\"line\":493,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"DEPTH\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"depth\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"69\",\"tlb\":\"#69\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Pops integer <code>i</code> from the stack, then checks whether there are at least <code>i</code> elements, generating a stack underflow exception otherwise.</p>\\n\",\"fift\":\"CHKDEPTH\",\"fift_examples\":[],\"gas\":\"18/58\",\"opcode\":\"69\",\"stack\":\"i -\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_chkdepth\",\"line\":500,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"CHKDEPTH\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6A\",\"tlb\":\"#6A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Pops integer <code>i</code> from the stack, then removes all but the top <code>i</code> elements.</p>\\n\",\"fift\":\"ONLYTOPX\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"6A\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_onlytop_x\",\"line\":509,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"ONLYTOPX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6B\",\"tlb\":\"#6B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Pops integer <code>i</code> from the stack, then leaves only the bottom <code>i</code> elements. Approximately equivalent to <code>DEPTH</code> <code>SWAP</code> <code>SUB</code> <code>DROPX</code>.</p>\\n\",\"fift\":\"ONLYX\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"6B\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_only_x\",\"line\":526,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"ONLYX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":1,\"name\":\"i\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"j\",\"size\":4,\"type\":\"uint\"}],\"operands_range_check\":{\"from\":1,\"length\":4,\"to\":15},\"prefix\":\"6C\",\"tlb\":\"#6C i:(## 4) j:uint4 {1 <= i}\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"stack_complex\",\"description\":\"<p>Drops <code>i</code> stack elements under the top <code>j</code> elements.\\n<code>1 &lt;= i &lt;= 15</code>, <code>0 &lt;= j &lt;= 15</code>\\nEquivalent to <code>[i+j] 0 REVERSE</code> <code>[i] BLKDROP</code> <code>[j] 0 REVERSE</code>.</p>\\n\",\"fift\":\"[i] [j] BLKDROP2\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"6Cij\",\"stack\":\"\"},\"implementation\":[{\"file\":\"stackops.cpp\",\"function_name\":\"exec_blkdrop2\",\"line\":380,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/stackops.cpp\"}],\"mnemonic\":\"BLKDROP2\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6D\",\"tlb\":\"#6D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Pushes the only value of type <em>Null</em>.</p>\\n\",\"fift\":\"NULL\\nPUSHNULL\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"6D\",\"stack\":\" - null\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_push_null\",\"line\":28,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"NULL\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"type\":\"const\",\"value\":null,\"value_type\":\"Null\"}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6E\",\"tlb\":\"#6E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Checks whether <code>x</code> is a <em>Null</em>, and returns <code>-1</code> or <code>0</code> accordingly.</p>\\n\",\"fift\":\"ISNULL\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"6E\",\"stack\":\"x - ?\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_is_null\",\"line\":34,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"ISNULL\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"n\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"6F0\",\"tlb\":\"#6F0 n:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Creates a new <em>Tuple</em> <code>t=(x_1, ... ,x_n)</code> containing <code>n</code> values <code>x_1</code>,..., <code>x_n</code>.\\n<code>0 &lt;= n &lt;= 15</code></p>\\n\",\"fift\":\"[n] TUPLE\",\"fift_examples\":[],\"gas\":\"26+n\",\"opcode\":\"6F0n\",\"stack\":\"x_1 ... x_n - t\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_mktuple_common\",\"line\":73,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"TUPLE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"x\",\"type\":\"simple\"}],\"length_var\":\"n\",\"name\":\"tuple_elements\",\"type\":\"array\"}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"k\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"6F1\",\"tlb\":\"#6F1 k:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Returns the <code>k</code>-th element of a <em>Tuple</em> <code>t</code>.\\n<code>0 &lt;= k &lt;= 15</code>.</p>\\n\",\"fift\":\"[k] INDEX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"6F1k\",\"stack\":\"t - x\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_tuple_index\",\"line\":106,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"INDEX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"n\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"6F2\",\"tlb\":\"#6F2 n:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Unpacks a <em>Tuple</em> <code>t=(x_1,...,x_n)</code> of length equal to <code>0 &lt;= n &lt;= 15</code>.\\nIf <code>t</code> is not a <em>Tuple</em>, or if <code>|t| != n</code>, a type check exception is thrown.</p>\\n\",\"fift\":\"[n] UNTUPLE\",\"fift_examples\":[],\"gas\":\"26+n\",\"opcode\":\"6F2n\",\"stack\":\"t - x_1 ... x_n\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_untuple\",\"line\":158,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"UNTUPLE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"x\",\"type\":\"simple\"}],\"length_var\":\"n\",\"name\":\"tuple_elements\",\"type\":\"array\"}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"k\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"6F3\",\"tlb\":\"#6F3 k:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Unpacks first <code>0 &lt;= k &lt;= 15</code> elements of a <em>Tuple</em> <code>t</code>.\\nIf <code>|t|&lt;k</code>, throws a type check exception.</p>\\n\",\"fift\":\"[k] UNPACKFIRST\",\"fift_examples\":[],\"gas\":\"26+k\",\"opcode\":\"6F3k\",\"stack\":\"t - x_1 ... x_k\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_untuple_first\",\"line\":175,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"UNPACKFIRST\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"x\",\"type\":\"simple\"}],\"length_var\":\"k\",\"name\":\"tuple_elements\",\"type\":\"array\"}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"n\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"6F4\",\"tlb\":\"#6F4 n:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Unpacks a <em>Tuple</em> <code>t=(x_1,...,x_m)</code> and returns its length <code>m</code>, but only if <code>m &lt;= n &lt;= 15</code>. Otherwise throws a type check exception.</p>\\n\",\"fift\":\"[n] EXPLODE\",\"fift_examples\":[],\"gas\":\"26+m\",\"opcode\":\"6F4n\",\"stack\":\"t - x_1 ... x_m m\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_explode_tuple\",\"line\":196,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"EXPLODE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"x\",\"type\":\"simple\"}],\"length_var\":\"m\",\"name\":\"tuple_elements\",\"type\":\"array\"},{\"name\":\"m\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"k\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"6F5\",\"tlb\":\"#6F5 k:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Computes <em>Tuple</em> <code>t'</code> that differs from <code>t</code> only at position <code>t'_{k+1}</code>, which is set to <code>x</code>.\\n<code>0 &lt;= k &lt;= 15</code>\\nIf <code>k &gt;= |t|</code>, throws a range check exception.</p>\\n\",\"fift\":\"[k] SETINDEX\",\"fift_examples\":[],\"gas\":\"26+|t|\",\"opcode\":\"6F5k\",\"stack\":\"t x - t'\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_tuple_set_index\",\"line\":222,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"SETINDEX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]},{\"name\":\"x\",\"type\":\"simple\"}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"t2\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"k\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"6F6\",\"tlb\":\"#6F6 k:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Returns the <code>k</code>-th element of a <em>Tuple</em> <code>t</code>, where <code>0 &lt;= k &lt;= 15</code>. In other words, returns <code>x_{k+1}</code> if <code>t=(x_1,...,x_n)</code>. If <code>k&gt;=n</code>, or if <code>t</code> is <em>Null</em>, returns a <em>Null</em> instead of <code>x</code>.</p>\\n\",\"fift\":\"[k] INDEXQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"6F6k\",\"stack\":\"t - x\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_tuple_quiet_index\",\"line\":124,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"INDEXQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\",\"Null\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"k\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"6F7\",\"tlb\":\"#6F7 k:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Sets the <code>k</code>-th component of <em>Tuple</em> <code>t</code> to <code>x</code>, where <code>0 &lt;= k &lt; 16</code>, and returns the resulting <em>Tuple</em> <code>t'</code>.\\nIf <code>|t| &lt;= k</code>, first extends the original <em>Tuple</em> to length <code>n'=k+1</code> by setting all new components to <em>Null</em>. If the original value of <code>t</code> is <em>Null</em>, treats it as an empty <em>Tuple</em>. If <code>t</code> is not <em>Null</em> or <em>Tuple</em>, throws an exception. If <code>x</code> is <em>Null</em> and either <code>|t| &lt;= k</code> or <code>t</code> is <em>Null</em>, then always returns <code>t'=t</code> (and does not consume tuple creation gas).</p>\\n\",\"fift\":\"[k] SETINDEXQ\",\"fift_examples\":[],\"gas\":\"26+|t'|\",\"opcode\":\"6F7k\",\"stack\":\"t x - t'\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_tuple_quiet_set_index\",\"line\":251,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"SETINDEXQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\",\"Null\"]},{\"name\":\"x\",\"type\":\"simple\"}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"t2\",\"type\":\"simple\",\"value_types\":[\"Tuple\",\"Null\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6F80\",\"tlb\":\"#6F80\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Creates a new <em>Tuple</em> <code>t</code> of length <code>n</code> similarly to <code>TUPLE</code>, but with <code>0 &lt;= n &lt;= 255</code> taken from the stack.</p>\\n\",\"fift\":\"TUPLEVAR\",\"fift_examples\":[],\"gas\":\"26+n\",\"opcode\":\"6F80\",\"stack\":\"x_1 ... x_n n - t\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_mktuple_var\",\"line\":94,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"TUPLEVAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"x\",\"type\":\"simple\"}],\"length_var\":\"n\",\"name\":\"tuple_elements\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6F81\",\"tlb\":\"#6F81\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Similar to <code>k INDEX</code>, but with <code>0 &lt;= k &lt;= 254</code> taken from the stack.</p>\\n\",\"fift\":\"INDEXVAR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"6F81\",\"stack\":\"t k - x\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_tuple_index_var\",\"line\":112,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"INDEXVAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6F82\",\"tlb\":\"#6F82\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Similar to <code>n UNTUPLE</code>, but with <code>0 &lt;= n &lt;= 255</code> taken from the stack.</p>\\n\",\"fift\":\"UNTUPLEVAR\",\"fift_examples\":[],\"gas\":\"26+n\",\"opcode\":\"6F82\",\"stack\":\"t n - x_1 ... x_n\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_untuple_var\",\"line\":164,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"UNTUPLEVAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"x\",\"type\":\"simple\"}],\"length_var\":\"n\",\"name\":\"tuple_elements\",\"type\":\"array\"}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6F83\",\"tlb\":\"#6F83\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Similar to <code>n UNPACKFIRST</code>, but with <code>0 &lt;= n &lt;= 255</code> taken from the stack.</p>\\n\",\"fift\":\"UNPACKFIRSTVAR\",\"fift_examples\":[],\"gas\":\"26+n\",\"opcode\":\"6F83\",\"stack\":\"t n - x_1 ... x_n\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_untuple_first_var\",\"line\":181,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"UNPACKFIRSTVAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"x\",\"type\":\"simple\"}],\"length_var\":\"n\",\"name\":\"tuple_elements\",\"type\":\"array\"}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6F84\",\"tlb\":\"#6F84\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Similar to <code>n EXPLODE</code>, but with <code>0 &lt;= n &lt;= 255</code> taken from the stack.</p>\\n\",\"fift\":\"EXPLODEVAR\",\"fift_examples\":[],\"gas\":\"26+m\",\"opcode\":\"6F84\",\"stack\":\"t n - x_1 ... x_m m\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_explode_tuple_var\",\"line\":202,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"EXPLODEVAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"x\",\"type\":\"simple\"}],\"length_var\":\"m\",\"name\":\"tuple_elements\",\"type\":\"array\"},{\"name\":\"m\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6F85\",\"tlb\":\"#6F85\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Similar to <code>k SETINDEX</code>, but with <code>0 &lt;= k &lt;= 254</code> taken from the stack.</p>\\n\",\"fift\":\"SETINDEXVAR\",\"fift_examples\":[],\"gas\":\"26+|t'|\",\"opcode\":\"6F85\",\"stack\":\"t x k - t'\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_tuple_set_index_var\",\"line\":229,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"SETINDEXVAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]},{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"t2\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6F86\",\"tlb\":\"#6F86\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Similar to <code>n INDEXQ</code>, but with <code>0 &lt;= k &lt;= 254</code> taken from the stack.</p>\\n\",\"fift\":\"INDEXVARQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"6F86\",\"stack\":\"t k - x\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_tuple_quiet_index_var\",\"line\":130,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"INDEXVARQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\",\"Null\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6F87\",\"tlb\":\"#6F87\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Similar to <code>k SETINDEXQ</code>, but with <code>0 &lt;= k &lt;= 254</code> taken from the stack.</p>\\n\",\"fift\":\"SETINDEXVARQ\",\"fift_examples\":[],\"gas\":\"26+|t'|\",\"opcode\":\"6F87\",\"stack\":\"t x k - t'\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_tuple_quiet_set_index_var\",\"line\":258,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"SETINDEXVARQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\",\"Null\"]},{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"t2\",\"type\":\"simple\",\"value_types\":[\"Tuple\",\"Null\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6F88\",\"tlb\":\"#6F88\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Returns the length of a <em>Tuple</em>.</p>\\n\",\"fift\":\"TLEN\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"6F88\",\"stack\":\"t - n\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_tuple_length\",\"line\":265,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"TLEN\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6F89\",\"tlb\":\"#6F89\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Similar to <code>TLEN</code>, but returns <code>-1</code> if <code>t</code> is not a <em>Tuple</em>.</p>\\n\",\"fift\":\"QTLEN\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"6F89\",\"stack\":\"t - n or -1\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_tuple_length_quiet\",\"line\":273,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"QTLEN\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6F8A\",\"tlb\":\"#6F8A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Returns <code>-1</code> or <code>0</code> depending on whether <code>t</code> is a <em>Tuple</em>.</p>\\n\",\"fift\":\"ISTUPLE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"6F8A\",\"stack\":\"t - ?\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_is_tuple\",\"line\":281,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"ISTUPLE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6F8B\",\"tlb\":\"#6F8B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Returns the last element of a non-empty <em>Tuple</em> <code>t</code>.</p>\\n\",\"fift\":\"LAST\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"6F8B\",\"stack\":\"t - x\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_tuple_last\",\"line\":288,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"LAST\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6F8C\",\"tlb\":\"#6F8C\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Appends a value <code>x</code> to a <em>Tuple</em> <code>t=(x_1,...,x_n)</code>, but only if the resulting <em>Tuple</em> <code>t'=(x_1,...,x_n,x)</code> is of length at most 255. Otherwise throws a type check exception.</p>\\n\",\"fift\":\"TPUSH\\nCOMMA\",\"fift_examples\":[],\"gas\":\"26+|t'|\",\"opcode\":\"6F8C\",\"stack\":\"t x - t'\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_tuple_push\",\"line\":296,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"TPUSH\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]},{\"name\":\"x\",\"type\":\"simple\"}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"t2\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6F8D\",\"tlb\":\"#6F8D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Detaches the last element <code>x=x_n</code> from a non-empty <em>Tuple</em> <code>t=(x_1,...,x_n)</code>, and returns both the resulting <em>Tuple</em> <code>t'=(x_1,...,x_{n-1})</code> and the original last element <code>x</code>.</p>\\n\",\"fift\":\"TPOP\",\"fift_examples\":[],\"gas\":\"26+|t'|\",\"opcode\":\"6F8D\",\"stack\":\"t - t' x\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_tuple_pop\",\"line\":308,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"TPOP\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"t2\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]},{\"name\":\"x\",\"type\":\"simple\"}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6FA0\",\"tlb\":\"#6FA0\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Pushes a <em>Null</em> under the topmost <em>Integer</em> <code>x</code>, but only if <code>x!=0</code>.</p>\\n\",\"fift\":\"NULLSWAPIF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"6FA0\",\"stack\":\"x - x or null x\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_null_swap_if\",\"line\":41,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"NULLSWAPIF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"else\":[{\"type\":\"const\",\"value\":null,\"value_type\":\"Null\"}],\"match\":[{\"stack\":[],\"value\":0}],\"name\":\"x\",\"type\":\"conditional\"},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6FA1\",\"tlb\":\"#6FA1\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Pushes a <em>Null</em> under the topmost <em>Integer</em> <code>x</code>, but only if <code>x=0</code>. May be used for stack alignment after quiet primitives such as <code>PLDUXQ</code>.</p>\\n\",\"fift\":\"NULLSWAPIFNOT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"6FA1\",\"stack\":\"x - x or null x\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_null_swap_if\",\"line\":41,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"NULLSWAPIFNOT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"else\":[],\"match\":[{\"stack\":[{\"type\":\"const\",\"value\":null,\"value_type\":\"Null\"}],\"value\":0}],\"name\":\"x\",\"type\":\"conditional\"},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6FA2\",\"tlb\":\"#6FA2\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Pushes a <em>Null</em> under the second stack entry from the top, but only if the topmost <em>Integer</em> <code>y</code> is non-zero.</p>\\n\",\"fift\":\"NULLROTRIF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"6FA2\",\"stack\":\"x y - x y or null x y\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_null_swap_if\",\"line\":41,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"NULLROTRIF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"else\":[{\"type\":\"const\",\"value\":null,\"value_type\":\"Null\"}],\"match\":[{\"stack\":[],\"value\":0}],\"name\":\"y\",\"type\":\"conditional\"},{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6FA3\",\"tlb\":\"#6FA3\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Pushes a <em>Null</em> under the second stack entry from the top, but only if the topmost <em>Integer</em> <code>y</code> is zero. May be used for stack alignment after quiet primitives such as <code>LDUXQ</code>.</p>\\n\",\"fift\":\"NULLROTRIFNOT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"6FA3\",\"stack\":\"x y - x y or null x y\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_null_swap_if\",\"line\":41,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"NULLROTRIFNOT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"else\":[],\"match\":[{\"stack\":[{\"type\":\"const\",\"value\":null,\"value_type\":\"Null\"}],\"value\":0}],\"name\":\"y\",\"type\":\"conditional\"},{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6FA4\",\"tlb\":\"#6FA4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Pushes two nulls under the topmost <em>Integer</em> <code>x</code>, but only if <code>x!=0</code>.\\nEquivalent to <code>NULLSWAPIF</code> <code>NULLSWAPIF</code>.</p>\\n\",\"fift\":\"NULLSWAPIF2\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"6FA4\",\"stack\":\"x - x or null null x\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_null_swap_if_many\",\"line\":56,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"NULLSWAPIF2\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"else\":[{\"type\":\"const\",\"value\":null,\"value_type\":\"Null\"},{\"type\":\"const\",\"value\":null,\"value_type\":\"Null\"}],\"match\":[{\"stack\":[],\"value\":0}],\"name\":\"x\",\"type\":\"conditional\"},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6FA5\",\"tlb\":\"#6FA5\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Pushes two nulls under the topmost <em>Integer</em> <code>x</code>, but only if <code>x=0</code>.\\nEquivalent to <code>NULLSWAPIFNOT</code> <code>NULLSWAPIFNOT</code>.</p>\\n\",\"fift\":\"NULLSWAPIFNOT2\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"6FA5\",\"stack\":\"x - x or null null x\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_null_swap_if_many\",\"line\":56,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"NULLSWAPIFNOT2\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"else\":[],\"match\":[{\"stack\":[{\"type\":\"const\",\"value\":null,\"value_type\":\"Null\"},{\"type\":\"const\",\"value\":null,\"value_type\":\"Null\"}],\"value\":0}],\"name\":\"x\",\"type\":\"conditional\"},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6FA6\",\"tlb\":\"#6FA6\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Pushes two nulls under the second stack entry from the top, but only if the topmost <em>Integer</em> <code>y</code> is non-zero.\\nEquivalent to <code>NULLROTRIF</code> <code>NULLROTRIF</code>.</p>\\n\",\"fift\":\"NULLROTRIF2\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"6FA6\",\"stack\":\"x y - x y or null null x y\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_null_swap_if_many\",\"line\":56,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"NULLROTRIF2\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"else\":[{\"type\":\"const\",\"value\":null,\"value_type\":\"Null\"},{\"type\":\"const\",\"value\":null,\"value_type\":\"Null\"}],\"match\":[{\"stack\":[],\"value\":0}],\"name\":\"y\",\"type\":\"conditional\"},{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"6FA7\",\"tlb\":\"#6FA7\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Pushes two nulls under the second stack entry from the top, but only if the topmost <em>Integer</em> <code>y</code> is zero.\\nEquivalent to <code>NULLROTRIFNOT</code> <code>NULLROTRIFNOT</code>.</p>\\n\",\"fift\":\"NULLROTRIFNOT2\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"6FA7\",\"stack\":\"x y - x y or null null x y\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_null_swap_if_many\",\"line\":56,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"NULLROTRIFNOT2\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"else\":[],\"match\":[{\"stack\":[{\"type\":\"const\",\"value\":null,\"value_type\":\"Null\"},{\"type\":\"const\",\"value\":null,\"value_type\":\"Null\"}],\"value\":0}],\"name\":\"y\",\"type\":\"conditional\"},{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":3,\"min_value\":0,\"name\":\"i\",\"size\":2,\"type\":\"uint\"},{\"display_hints\":[],\"max_value\":3,\"min_value\":0,\"name\":\"j\",\"size\":2,\"type\":\"uint\"}],\"prefix\":\"6FB\",\"tlb\":\"#6FB i:uint2 j:uint2\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Recovers <code>x=(t_{i+1})_{j+1}</code> for <code>0 &lt;= i,j &lt;= 3</code>.\\nEquivalent to <code>[i] INDEX</code> <code>[j] INDEX</code>.</p>\\n\",\"fift\":\"[i] [j] INDEX2\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"6FBij\",\"stack\":\"t - x\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_tuple_index2\",\"line\":320,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"INDEX2\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":3,\"min_value\":0,\"name\":\"i\",\"size\":2,\"type\":\"uint\"},{\"display_hints\":[],\"max_value\":3,\"min_value\":0,\"name\":\"j\",\"size\":2,\"type\":\"uint\"},{\"display_hints\":[],\"max_value\":3,\"min_value\":0,\"name\":\"k\",\"size\":2,\"type\":\"uint\"}],\"prefix\":\"6FE_\",\"tlb\":\"#6FE_ i:uint2 j:uint2 k:uint2\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"tuple\",\"description\":\"<p>Recovers <code>x=t_{i+1}_{j+1}_{k+1}</code>.\\n<code>0 &lt;= i,j,k &lt;= 3</code>\\nEquivalent to <code>[i] [j] INDEX2</code> <code>[k] INDEX</code>.</p>\\n\",\"fift\":\"[i] [j] [k] INDEX3\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"6FE_ijk\",\"stack\":\"t - x\"},\"implementation\":[{\"file\":\"tupleops.cpp\",\"function_name\":\"exec_tuple_index3\",\"line\":340,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tupleops.cpp\"}],\"mnemonic\":\"INDEX3\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"pushint4\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"7\",\"tlb\":\"#7 i:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"const_int\",\"description\":\"<p>Pushes integer <code>x</code> into the stack. <code>-5 &lt;= x &lt;= 10</code>.\\nHere <code>i</code> equals four lower-order bits of <code>x</code> (<code>i=x mod 16</code>).</p>\\n\",\"fift\":\"[x] PUSHINT\\n[x] INT\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"7i\",\"stack\":\"- x\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_push_tinyint4\",\"line\":31,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"PUSHINT_4\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":127,\"min_value\":-128,\"name\":\"x\",\"size\":8,\"type\":\"int\"}],\"prefix\":\"80\",\"tlb\":\"#80 xx:int8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"const_int\",\"description\":\"<p>Pushes integer <code>xx</code>. <code>-128 &lt;= xx &lt;= 127</code>.</p>\\n\",\"fift\":\"[xx] PUSHINT\\n[xx] INT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"80xx\",\"stack\":\"- xx\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_push_tinyint8\",\"line\":46,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"PUSHINT_8\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":32767,\"min_value\":-32768,\"name\":\"x\",\"size\":16,\"type\":\"int\"}],\"prefix\":\"81\",\"tlb\":\"#81 xxxx:int16\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"const_int\",\"description\":\"<p>Pushes integer <code>xxxx</code>. <code>-2^15 &lt;= xx &lt; 2^15</code>.</p>\\n\",\"fift\":\"[xxxx] PUSHINT\\n[xxxx] INT\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"81xxxx\",\"stack\":\"- xxxx\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_push_smallint\",\"line\":61,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"PUSHINT_16\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"name\":\"x\",\"type\":\"pushint_long\"}],\"operands_range_check\":{\"from\":0,\"length\":5,\"to\":30},\"prefix\":\"82\",\"tlb\":\"#82 l:(## 5) xxx:(int (8 * l + 19))\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"const_int\",\"description\":\"<p>Pushes integer <code>xxx</code>.\\n<em>Details:</em> 5-bit <code>0 &lt;= l &lt;= 30</code> determines the length <code>n=8l+19</code> of signed big-endian integer <code>xxx</code>.\\nThe total length of this instruction is <code>l+4</code> bytes or <code>n+13=8l+32</code> bits.</p>\\n\",\"fift\":\"[xxx] PUSHINT\\n[xxx] INT\",\"fift_examples\":[],\"gas\":\"23\",\"opcode\":\"82lxxx\",\"stack\":\"- xxx\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_push_int\",\"line\":76,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"PUSHINT_LONG\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":254,\"min_value\":0,\"name\":\"x\",\"size\":8,\"type\":\"uint\"}],\"operands_range_check\":{\"from\":0,\"length\":8,\"to\":254},\"prefix\":\"83\",\"tlb\":\"#83 xx:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"const_int\",\"description\":\"<p>(Quietly) pushes <code>2^(xx+1)</code> for <code>0 &lt;= xx &lt;= 255</code>.\\n<code>2^256</code> is a <code>NaN</code>.</p>\\n\",\"fift\":\"[xx+1] PUSHPOW2\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"83xx\",\"stack\":\"- 2^(xx+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_push_pow2\",\"line\":110,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"PUSHPOW2\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"83FF\",\"tlb\":\"#83FF\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"const_int\",\"description\":\"<p>Pushes a <code>NaN</code>.</p>\\n\",\"fift\":\"PUSHNAN\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"83FF\",\"stack\":\"- NaN\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_push_nan\",\"line\":120,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"PUSHNAN\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"type\":\"const\",\"value\":null,\"value_type\":\"Integer\"}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"x\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"84\",\"tlb\":\"#84 xx:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"const_int\",\"description\":\"<p>Pushes <code>2^(xx+1)-1</code> for <code>0 &lt;= xx &lt;= 255</code>.</p>\\n\",\"fift\":\"[xx+1] PUSHPOW2DEC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"84xx\",\"stack\":\"- 2^(xx+1)-1\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_push_pow2dec\",\"line\":129,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"PUSHPOW2DEC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"x\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"85\",\"tlb\":\"#85 xx:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"const_int\",\"description\":\"<p>Pushes <code>-2^(xx+1)</code> for <code>0 &lt;= xx &lt;= 255</code>.</p>\\n\",\"fift\":\"[xx+1] PUSHNEGPOW2\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"85xx\",\"stack\":\"- -2^(xx+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_push_negpow2\",\"line\":139,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"PUSHNEGPOW2\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"name\":\"c\",\"type\":\"ref\"}],\"prefix\":\"88\",\"tlb\":\"#88 c:^Cell\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"const_data\",\"description\":\"<p>Pushes the reference <code>ref</code> into the stack.\\n<em>Details:</em> Pushes the first reference of <code>cc.code</code> into the stack as a <em>Cell</em> (and removes this reference from the current continuation).</p>\\n\",\"fift\":\"[ref] PUSHREF\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"88\",\"stack\":\"- c\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_push_ref\",\"line\":32,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PUSHREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"name\":\"c\",\"type\":\"ref\"}],\"prefix\":\"89\",\"tlb\":\"#89 c:^Cell\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"const_data\",\"description\":\"<p>Similar to <code>PUSHREF</code>, but converts the cell into a <em>Slice</em>.</p>\\n\",\"fift\":\"[ref] PUSHREFSLICE\",\"fift_examples\":[],\"gas\":\"118/43\",\"opcode\":\"89\",\"stack\":\"- s\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_push_slice\",\"line\":117,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PUSHREFSLICE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"continuation\"}],\"name\":\"c\",\"type\":\"ref\"}],\"prefix\":\"8A\",\"tlb\":\"#8A c:^Cell\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"const_data\",\"description\":\"<p>Similar to <code>PUSHREFSLICE</code>, but makes a simple ordinary <em>Continuation</em> out of the cell.</p>\\n\",\"fift\":\"[ref] PUSHREFCONT\",\"fift_examples\":[],\"gas\":\"118/43\",\"opcode\":\"8A\",\"stack\":\"- cont\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_push_cont\",\"line\":165,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PUSHREFCONT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]}}},{\"bytecode\":{\"operands\":[{\"bits_length_var_size\":4,\"bits_padding\":4,\"completion_tag\":true,\"display_hints\":[],\"max_bits\":123,\"max_refs\":0,\"min_bits\":0,\"min_refs\":0,\"name\":\"s\",\"type\":\"subslice\"}],\"prefix\":\"8B\",\"tlb\":\"#8B x:(## 4) sss:((8 * x + 4) * Bit)\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"const_data\",\"description\":\"<p>Pushes the slice <code>slice</code> into the stack.\\n<em>Details:</em> Pushes the (prefix) subslice of <code>cc.code</code> consisting of its first <code>8x+4</code> bits and no references (i.e., essentially a bitstring), where <code>0 &lt;= x &lt;= 15</code>.\\nA completion tag is assumed, meaning that all trailing zeroes and the last binary one (if present) are removed from this bitstring.\\nIf the original bitstring consists only of zeroes, an empty slice will be pushed.</p>\\n\",\"fift\":\"[slice] PUSHSLICE\\n[slice] SLICE\",\"fift_examples\":[],\"gas\":\"22\",\"opcode\":\"8Bxsss\",\"stack\":\"- s\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_push_slice\",\"line\":117,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PUSHSLICE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[{\"bits_length_var_size\":5,\"bits_padding\":1,\"completion_tag\":true,\"display_hints\":[],\"max_bits\":248,\"max_refs\":4,\"min_bits\":0,\"min_refs\":1,\"name\":\"slice\",\"refs_add\":1,\"refs_length_var_size\":2,\"type\":\"subslice\"}],\"prefix\":\"8C\",\"tlb\":\"#8C r:(## 2) xx:(## 5) c:((r + 1) * ^Cell) ssss:((8 * xx + 1) * Bit)\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"const_data\",\"description\":\"<p>Pushes the slice <code>slice</code> into the stack.\\n<em>Details:</em> Pushes the (prefix) subslice of <code>cc.code</code> consisting of its first <code>1 &lt;= r+1 &lt;= 4</code> references and up to first <code>8xx+1</code> bits of data, with <code>0 &lt;= xx &lt;= 31</code>.\\nA completion tag is also assumed.</p>\\n\",\"fift\":\"[slice] PUSHSLICE\\n[slice] SLICE\",\"fift_examples\":[],\"gas\":\"25\",\"opcode\":\"8Crxxssss\",\"stack\":\"- s\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_push_slice_r\",\"line\":129,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PUSHSLICE_REFS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[{\"bits_length_var_size\":7,\"bits_padding\":6,\"completion_tag\":true,\"display_hints\":[],\"max_bits\":1021,\"max_refs\":4,\"min_bits\":0,\"min_refs\":0,\"name\":\"slice\",\"refs_add\":0,\"refs_length_var_size\":3,\"type\":\"subslice\"}],\"operands_range_check\":{\"from\":0,\"length\":3,\"to\":4},\"prefix\":\"8D\",\"tlb\":\"#8D r:(#<= 4) xx:(## 7) c:(r * ^Cell) ssss:((8 * xx + 6) * Bit)\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"const_data\",\"description\":\"<p>Pushes the slice <code>slice</code> into the stack.\\n<em>Details:</em> Pushes the subslice of <code>cc.code</code> consisting of <code>0 &lt;= r &lt;= 4</code> references and up to <code>8xx+6</code> bits of data, with <code>0 &lt;= xx &lt;= 127</code>.\\nA completion tag is assumed.</p>\\n\",\"fift\":\"[slice] PUSHSLICE\\n[slice] SLICE\",\"fift_examples\":[{\"description\":\"Examples of `PUSHSLICE`. `x{}` is an empty slice. `x{...}` is a hexadecimal literal. `b{...}` is a binary literal. More on slice literals [here](https://github.com/Piterden/TON-docs/blob/master/Fift.%20A%20Brief%20Introduction.md#user-content-51-slice-literals). Note that the assembler can replace `PUSHSLICE` with `PUSHREFSLICE` in certain situations (e.g. if there's not enough space in the current continuation).\",\"fift\":\"x{} PUSHSLICE x{ABCD1234} PUSHSLICE b{01101} PUSHSLICE\"},{\"description\":\"Examples of `PUSHREF` and `PUSHREFSLICE`. More on building cells in fift [here](https://github.com/Piterden/TON-docs/blob/master/Fift.%20A%20Brief%20Introduction.md#user-content-52-builder-primitives).\",\"fift\":\"<b x{AB12} s, b> PUSHREF <b x{AB12} s, b> PUSHREFSLICE\"}],\"gas\":\"28\",\"opcode\":\"8Drxxsssss\",\"stack\":\"- s\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_push_slice\",\"line\":117,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PUSHSLICE_LONG\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[{\"bits_length_var_size\":7,\"bits_padding\":0,\"completion_tag\":false,\"display_hints\":[{\"type\":\"continuation\"}],\"max_bits\":1016,\"max_refs\":3,\"min_bits\":0,\"min_refs\":0,\"name\":\"s\",\"refs_add\":0,\"refs_length_var_size\":2,\"type\":\"subslice\"}],\"prefix\":\"8F_\",\"tlb\":\"#8F_ r:(## 2) xx:(## 7) c:(r * ^Cell) ssss:((8 * xx) * Bit)\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"const_data\",\"description\":\"<p>Pushes a continuation made from <code>builder</code>.\\n<em>Details:</em> Pushes the simple ordinary continuation <code>cccc</code> made from the first <code>0 &lt;= r &lt;= 3</code> references and the first <code>0 &lt;= xx &lt;= 127</code> bytes of <code>cc.code</code>.</p>\\n\",\"fift\":\"[builder] PUSHCONT\\n[builder] CONT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"8F_rxxcccc\",\"stack\":\"- c\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_push_cont\",\"line\":165,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PUSHCONT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]}}},{\"bytecode\":{\"operands\":[{\"bits_length_var_size\":4,\"bits_padding\":0,\"completion_tag\":false,\"display_hints\":[{\"type\":\"continuation\"}],\"max_bits\":120,\"max_refs\":0,\"min_bits\":0,\"min_refs\":0,\"name\":\"s\",\"type\":\"subslice\"}],\"prefix\":\"9\",\"tlb\":\"#9 x:(## 4) ssss:((8 * x) * Bit)\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"const_data\",\"description\":\"<p>Pushes a continuation made from <code>builder</code>.\\n<em>Details:</em> Pushes an <code>x</code>-byte continuation for <code>0 &lt;= x &lt;= 15</code>.</p>\\n\",\"fift\":\"[builder] PUSHCONT\\n[builder] CONT\",\"fift_examples\":[{\"description\":\"Pushes a continuation with code `code`. Note that the assembler can replace `PUSHCONT` with `PUSHREFCONT` in certain situations (e.g. if there's not enough space in the current continuation).\",\"fift\":\"<{ code }> PUSHCONT <{ code }> CONT CONT:<{ code }>\"}],\"gas\":\"18\",\"opcode\":\"9xccc\",\"stack\":\"- c\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_push_cont\",\"line\":165,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PUSHCONT_SHORT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A0\",\"tlb\":\"#A0\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_basic\",\"description\":\"\",\"fift\":\"ADD\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"A0\",\"stack\":\"x y - x+y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_add\",\"line\":162,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"ADD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A1\",\"tlb\":\"#A1\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_basic\",\"description\":\"\",\"fift\":\"SUB\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"A1\",\"stack\":\"x y - x-y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_sub\",\"line\":171,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"SUB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A2\",\"tlb\":\"#A2\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_basic\",\"description\":\"<p>Equivalent to <code>SWAP</code> <code>SUB</code>.</p>\\n\",\"fift\":\"SUBR\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"A2\",\"stack\":\"x y - y-x\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_subr\",\"line\":180,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"SUBR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A3\",\"tlb\":\"#A3\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_basic\",\"description\":\"<p>Equivalent to <code>-1 MULCONST</code> or to <code>ZERO SUBR</code>.\\nNotice that it triggers an integer overflow exception if <code>x=-2^256</code>.</p>\\n\",\"fift\":\"NEGATE\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"A3\",\"stack\":\"x - -x\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_negate\",\"line\":189,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"NEGATE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A4\",\"tlb\":\"#A4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_basic\",\"description\":\"<p>Equivalent to <code>1 ADDCONST</code>.</p>\\n\",\"fift\":\"INC\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"A4\",\"stack\":\"x - x+1\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_inc\",\"line\":197,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"INC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A5\",\"tlb\":\"#A5\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_basic\",\"description\":\"<p>Equivalent to <code>-1 ADDCONST</code>.</p>\\n\",\"fift\":\"DEC\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"A5\",\"stack\":\"x - x-1\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_dec\",\"line\":205,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"DEC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":127,\"min_value\":-128,\"name\":\"c\",\"size\":8,\"type\":\"int\"}],\"prefix\":\"A6\",\"tlb\":\"#A6 cc:int8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_basic\",\"description\":\"<p><code>-128 &lt;= cc &lt;= 127</code>.</p>\\n\",\"fift\":\"[cc] ADDCONST\\n[cc] ADDINT\\n[-cc] SUBCONST\\n[-cc] SUBINT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A6cc\",\"stack\":\"x - x+cc\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_add_tinyint8\",\"line\":213,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"ADDCONST\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":127,\"min_value\":-128,\"name\":\"c\",\"size\":8,\"type\":\"int\"}],\"prefix\":\"A7\",\"tlb\":\"#A7 cc:int8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_basic\",\"description\":\"<p><code>-128 &lt;= cc &lt;= 127</code>.</p>\\n\",\"fift\":\"[cc] MULCONST\\n[cc] MULINT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A7cc\",\"stack\":\"x - x*cc\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mul_tinyint8\",\"line\":222,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULCONST\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A8\",\"tlb\":\"#A8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_basic\",\"description\":\"\",\"fift\":\"MUL\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"A8\",\"stack\":\"x y - x*y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mul\",\"line\":231,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MUL\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A900\",\"tlb\":\"#A900\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"ADDDIVMOD\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A900\",\"stack\":\"x w z - q=floor((x+w)/z) r=(x+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"ADDDIVMOD\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A901\",\"tlb\":\"#A901\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"ADDDIVMODR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A901\",\"stack\":\"x w z - q=round((x+w)/z) r=(x+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"ADDDIVMODR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A902\",\"tlb\":\"#A902\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"ADDDIVMODC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A902\",\"stack\":\"x w y - q=ceil((x+w)/z) r=(x+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"ADDDIVMODC\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A904\",\"tlb\":\"#A904\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"<p><code>q=floor(x/y)</code>, <code>r=x-y*q</code></p>\\n\",\"fift\":\"DIV\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A904\",\"stack\":\"x y - q\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"DIV\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A905\",\"tlb\":\"#A905\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"<p><code>q'=round(x/y)</code>, <code>r'=x-y*q'</code></p>\\n\",\"fift\":\"DIVR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A905\",\"stack\":\"x y - q'\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"DIVR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A906\",\"tlb\":\"#A906\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"<p><code>q''=ceil(x/y)</code>, <code>r''=x-y*q''</code></p>\\n\",\"fift\":\"DIVC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A906\",\"stack\":\"x y - q''\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"DIVC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A908\",\"tlb\":\"#A908\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MOD\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A908\",\"stack\":\"x y - r\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MOD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A909\",\"tlb\":\"#A909\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MODR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A909\",\"stack\":\"x y - r\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MODR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A90A\",\"tlb\":\"#A90A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MODC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A90A\",\"stack\":\"x y - r\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MODC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A90C\",\"tlb\":\"#A90C\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"DIVMOD\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A90C\",\"stack\":\"x y - q r\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"DIVMOD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A90D\",\"tlb\":\"#A90D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"DIVMODR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A90D\",\"stack\":\"x y - q' r'\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"DIVMODR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A90E\",\"tlb\":\"#A90E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"DIVMODC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A90E\",\"stack\":\"x y - q'' r''\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"DIVMODC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A920\",\"tlb\":\"#A920\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"ADDRSHIFTMOD\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A920\",\"stack\":\"x w z - q=floor((x+w)/2^z) r=(x+w)-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"ADDRSHIFTMOD_VAR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A921\",\"tlb\":\"#A921\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"ADDRSHIFTMODR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A921\",\"stack\":\"x w z - q=round((x+w)/2^z) r=(x+w)-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"ADDRSHIFTMODR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A922\",\"tlb\":\"#A922\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"ADDRSHIFTMODC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A922\",\"stack\":\"x w z - q=ceil((x+w)/2^z) r=(x+w)-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"ADDRSHIFTMODC\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A925\",\"tlb\":\"#A925\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"RSHIFTR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A925\",\"stack\":\"x y - round(x/2^y)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"RSHIFTR_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A926\",\"tlb\":\"#A926\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"RSHIFTC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A926\",\"stack\":\"x y - ceil(x/2^y)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"RSHIFTC_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A928\",\"tlb\":\"#A928\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MODPOW2\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A928\",\"stack\":\"x y - x mod 2^y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MODPOW2_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A929\",\"tlb\":\"#A929\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MODPOW2R\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A929\",\"stack\":\"x y - x mod 2^y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MODPOW2R_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A92A\",\"tlb\":\"#A92A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MODPOW2C\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A92A\",\"stack\":\"x y - x mod 2^y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MODPOW2C_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A92C\",\"tlb\":\"#A92C\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"RSHIFTMOD\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A92C\",\"stack\":\"x y - q=floor(x/2^y) r=x-q*2^y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"RSHIFTMOD_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A92D\",\"tlb\":\"#A92D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"RSHIFTMODR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A92D\",\"stack\":\"x y - q=round(x/2^y) r=x-q*2^y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"RSHIFTMODR_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A92E\",\"tlb\":\"#A92E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"RSHIFTMODC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A92E\",\"stack\":\"x y - q=ceil(x/2^y) r=x-q*2^y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"RSHIFTMODC_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A930\",\"tlb\":\"#A930 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] ADDRSHIFT#MOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A930tt\",\"stack\":\"x w - q=floor((x+w)/2^(tt+1)) r=(x+w)-q*2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"ADDRSHIFTMOD\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A931\",\"tlb\":\"#A931 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] ADDRSHIFTR#MOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A931tt\",\"stack\":\"x w - q=round((x+w)/2^(tt+1)) r=(x+w)-q*2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"ADDRSHIFTRMOD\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A932\",\"tlb\":\"#A932 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] ADDRSHIFTC#MOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A932tt\",\"stack\":\"x w - q=round((x+w)/2^(tt+1)) r=(x+w)-q*2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"ADDRSHIFTCMOD\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A935\",\"tlb\":\"#A935 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] RSHIFTR#\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A935tt\",\"stack\":\"x - round(x/2^(tt+1))\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"RSHIFTR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A936\",\"tlb\":\"#A936 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] RSHIFTC#\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A936tt\",\"stack\":\"x - ceil(x/2^(tt+1))\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"RSHIFTC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A938\",\"tlb\":\"#A938 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] MODPOW2#\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A938tt\",\"stack\":\"x - x mod 2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MODPOW2\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A939\",\"tlb\":\"#A939 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] MODPOW2R#\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A939tt\",\"stack\":\"x - x mod 2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MODPOW2R\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A93A\",\"tlb\":\"#A93A tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] MODPOW2C#\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A93Att\",\"stack\":\"x - x mod 2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MODPOW2C\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A93C\",\"tlb\":\"#A93C tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] RSHIFT#MOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A93Ctt\",\"stack\":\"x - q=floor(x/2^(tt+1)) r=x-q*2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"RSHIFTMOD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A93D\",\"tlb\":\"#A93D tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] RSHIFTR#MOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A93Dtt\",\"stack\":\"x - q=round(x/2^(tt+1)) r=x-q*2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"RSHIFTRMOD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A93E\",\"tlb\":\"#A93E tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] RSHIFTC#MOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A93Ett\",\"stack\":\"x - q=ceil(x/2^(tt+1)) r=x-q*2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"RSHIFTCMOD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A980\",\"tlb\":\"#A980\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MULADDDIVMOD\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A980\",\"stack\":\"x y w z - q=floor((xy+w)/z) r=(xy+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULADDDIVMOD\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A981\",\"tlb\":\"#A981\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MULADDDIVMODR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A981\",\"stack\":\"x y w z - q=round((xy+w)/z) r=(xy+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULADDDIVMODR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A982\",\"tlb\":\"#A982\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MULADDDIVMODC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A982\",\"stack\":\"x y w z - q=ceil((xy+w)/z) r=(xy+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULADDDIVMODC\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A984\",\"tlb\":\"#A984\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"<p><code>q=floor(x*y/z)</code></p>\\n\",\"fift\":\"MULDIV\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A984\",\"stack\":\"x y z - q\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULDIV\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A985\",\"tlb\":\"#A985\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"<p><code>q'=round(x*y/z)</code></p>\\n\",\"fift\":\"MULDIVR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A985\",\"stack\":\"x y z - q'\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULDIVR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A986\",\"tlb\":\"#A986\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"<p><code>q'=ceil(x*y/z)</code></p>\\n\",\"fift\":\"MULDIVC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A986\",\"stack\":\"x y z - q'\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULDIVC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A988\",\"tlb\":\"#A988\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MULMOD\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A988\",\"stack\":\"x y z - x*y mod z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULMOD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A989\",\"tlb\":\"#A989\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MULMODR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A989\",\"stack\":\"x y z - x*y mod z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULMODR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A98A\",\"tlb\":\"#A98A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MULMODC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A98A\",\"stack\":\"x y z - x*y mod z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULMODC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A98C\",\"tlb\":\"#A98C\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"<p><code>q=floor(x*y/z)</code>, <code>r=x*y-z*q</code></p>\\n\",\"fift\":\"MULDIVMOD\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A98C\",\"stack\":\"x y z - q r\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULDIVMOD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A98D\",\"tlb\":\"#A98D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"<p><code>q=round(x*y/z)</code>, <code>r=x*y-z*q</code></p>\\n\",\"fift\":\"MULDIVMODR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A98D\",\"stack\":\"x y z - q r\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULDIVMODR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A98E\",\"tlb\":\"#A98E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"<p><code>q=ceil(x*y/z)</code>, <code>r=x*y-z*q</code></p>\\n\",\"fift\":\"MULDIVMODC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A98E\",\"stack\":\"x y z - q r\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULDIVMODC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9A0\",\"tlb\":\"#A9A0\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MULADDRSHIFTMOD\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9A0\",\"stack\":\"x y w z - q=floor((xy+w)/2^z) r=(xy+w)-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULADDRSHIFTMOD_VAR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9A1\",\"tlb\":\"#A9A1\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MULADDRSHIFTRMOD\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9A1\",\"stack\":\"x y w z - q=round((xy+w)/2^z) r=(xy+w)-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULADDRSHIFTRMOD_VAR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9A2\",\"tlb\":\"#A9A2\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MULADDRSHIFTCMOD\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9A2\",\"stack\":\"x y w z - q=ceil((xy+w)/2^z) r=(xy+w)-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULADDRSHIFTCMOD_VAR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9A4\",\"tlb\":\"#A9A4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"<p><code>0 &lt;= z &lt;= 256</code></p>\\n\",\"fift\":\"MULRSHIFT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9A4\",\"stack\":\"x y z - floor(x*y/2^z)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULRSHIFT_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9A5\",\"tlb\":\"#A9A5\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"<p><code>0 &lt;= z &lt;= 256</code></p>\\n\",\"fift\":\"MULRSHIFTR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9A5\",\"stack\":\"x y z - round(x*y/2^z)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULRSHIFTR_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9A6\",\"tlb\":\"#A9A6\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"<p><code>0 &lt;= z &lt;= 256</code></p>\\n\",\"fift\":\"MULRSHIFTC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9A6\",\"stack\":\"x y z - ceil(x*y/2^z)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULRSHIFTC_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9A8\",\"tlb\":\"#A9A8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MULMODPOW2_VAR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9A8\",\"stack\":\"x y z - x*y mod 2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULMODPOW2_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9A9\",\"tlb\":\"#A9A9\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MULMODPOW2R_VAR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9A9\",\"stack\":\"x y z - x*y mod 2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULMODPOW2R_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9AA\",\"tlb\":\"#A9AA\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MULMODPOW2C_VAR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9AA\",\"stack\":\"x y z - x*y mod 2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULMODPOW2C_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9AC\",\"tlb\":\"#A9AC\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MULRSHIFTMOD_VAR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9AC\",\"stack\":\"x y z - q=floor(x*y/2^z) r=xy-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULRSHIFTMOD_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9AD\",\"tlb\":\"#A9AD\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MULRSHIFTRMOD_VAR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9AD\",\"stack\":\"x y z - q=round(x*y/2^z) r=xy-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULRSHIFTRMOD_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9AE\",\"tlb\":\"#A9AE\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MULRSHIFTCMOD_VAR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9AE\",\"stack\":\"x y z - q=ceil(x*y/2^z) r=xy-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULRSHIFTCMOD_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9B0\",\"tlb\":\"#A9B0 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] MULADDRSHIFT#MOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9B0tt\",\"stack\":\"x y w - q=floor((xy+w)/2^z) r=(xy+w)-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULADDRSHIFTMOD\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9B1\",\"tlb\":\"#A9B1 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] MULADDRSHIFTR#MOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9B1tt\",\"stack\":\"x y w - q=round((xy+w)/2^z) r=(xy+w)-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULADDRSHIFTRMOD\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9B2\",\"tlb\":\"#A9B2 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] MULADDRSHIFTC#MOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9B2tt\",\"stack\":\"x y w - q=ceil((xy+w)/2^z) r=(xy+w)-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULADDRSHIFTCMOD\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9B4\",\"tlb\":\"#A9B4 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] MULRSHIFT#\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9B4tt\",\"stack\":\"x y - floor(x*y/2^(tt+1))\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULRSHIFT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9B5\",\"tlb\":\"#A9B5 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] MULRSHIFTR#\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9B5tt\",\"stack\":\"x y - round(x*y/2^(tt+1))\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULRSHIFTR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9B6\",\"tlb\":\"#A9B6 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] MULRSHIFTC#\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9B6tt\",\"stack\":\"x y - ceil(x*y/2^(tt+1))\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULRSHIFTC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9B8\",\"tlb\":\"#A9B8 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] MULMODPOW2#\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9B8tt\",\"stack\":\"x y - x*y mod 2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULMODPOW2\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9B9\",\"tlb\":\"#A9B9 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] MULMODPOW2R#\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9B9tt\",\"stack\":\"x y - x*y mod 2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULMODPOW2R\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9BA\",\"tlb\":\"#A9BA tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] MULMODPOW2C#\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9BAtt\",\"stack\":\"x y - x*y mod 2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULMODPOW2C\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9BC\",\"tlb\":\"#A9BC\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MULRSHIFT#MOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9BC\",\"stack\":\"x y - q=floor(x*y/2^(tt+1)) r=xy-q*2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULRSHIFTMOD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9BD\",\"tlb\":\"#A9BD\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MULRSHIFTR#MOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9BD\",\"stack\":\"x y - q=round(x*y/2^(tt+1)) r=xy-q*2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULRSHIFTRMOD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9BE\",\"tlb\":\"#A9BE\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"MULRSHIFTC#MOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9BE\",\"stack\":\"x y - q=ceil(x*y/2^(tt+1)) r=xy-q*2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MULRSHIFTCMOD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9C0\",\"tlb\":\"#A9C0\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"LSHIFTADDDIVMOD\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9C0\",\"stack\":\"x w z y - q=floor((x*2^y+w)/z) r=(x*2^y+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTADDDIVMOD_VAR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9C1\",\"tlb\":\"#A9C1\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"LSHIFTADDDIVMODR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9C1\",\"stack\":\"x w z y - q=round((x*2^y+w)/z) r=(x*2^y+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTADDDIVMODR_VAR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9C2\",\"tlb\":\"#A9C2\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"LSHIFTADDDIVMODC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9C2\",\"stack\":\"x w z y - q=round((x*2^y+w)/z) r=(x*2^y+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTADDDIVMODC_VAR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9C4\",\"tlb\":\"#A9C4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"<p><code>0 &lt;= z &lt;= 256</code></p>\\n\",\"fift\":\"LSHIFTDIV\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9C4\",\"stack\":\"x y z - floor(2^z*x/y)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTDIV_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9C5\",\"tlb\":\"#A9C5\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"<p><code>0 &lt;= z &lt;= 256</code></p>\\n\",\"fift\":\"LSHIFTDIVR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9C5\",\"stack\":\"x y z - round(2^z*x/y)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTDIVR_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9C6\",\"tlb\":\"#A9C6\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"<p><code>0 &lt;= z &lt;= 256</code></p>\\n\",\"fift\":\"LSHIFTDIVC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9C6\",\"stack\":\"x y z - ceil(2^z*x/y)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTDIVC_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9C8\",\"tlb\":\"#A9C8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"LSHIFTMOD\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9C8\",\"stack\":\"x y z - 2^z*x mod y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTMOD_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9C9\",\"tlb\":\"#A9C9\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"LSHIFTMODR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9C9\",\"stack\":\"x y z - 2^z*x mod y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTMODR_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9CA\",\"tlb\":\"#A9CA\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"LSHIFTMODC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9CA\",\"stack\":\"x y z - 2^z*x mod y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTMODC_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9CC\",\"tlb\":\"#A9CC\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"LSHIFTDIVMOD\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9CC\",\"stack\":\"x y z - q=floor(2^z*x/y) r=2^z*x-q*y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTDIVMOD_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9CD\",\"tlb\":\"#A9CD\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"LSHIFTDIVMODR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9CD\",\"stack\":\"x y z - q=round(2^z*x/y) r=2^z*x-q*y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTDIVMODR_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"A9CE\",\"tlb\":\"#A9CE\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"LSHIFTDIVMODC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"A9CE\",\"stack\":\"x y z - q=ceil(2^z*x/y) r=2^z*x-q*y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTDIVMODC_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9D0\",\"tlb\":\"#A9D0 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] LSHIFT#ADDDIVMOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9D0tt\",\"stack\":\"x w z - q=floor((x*2^y+w)/z) r=(x*2^y+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTADDDIVMOD\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9D1\",\"tlb\":\"#A9D1 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] LSHIFT#ADDDIVMODR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9D1tt\",\"stack\":\"x w z - q=round((x*2^y+w)/z) r=(x*2^y+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTADDDIVMODR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9D2\",\"tlb\":\"#A9D2 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] LSHIFT#ADDDIVMODC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9D2tt\",\"stack\":\"x w z - q=ceil((x*2^y+w)/z) r=(x*2^y+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTADDDIVMODC\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9D4\",\"tlb\":\"#A9D4 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] LSHIFT#DIV\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9D4tt\",\"stack\":\"x y - floor(2^(tt+1)*x/y)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTDIV\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9D5\",\"tlb\":\"#A9D5 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] LSHIFT#DIVR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9D5tt\",\"stack\":\"x y - round(2^(tt+1)*x/y)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTDIVR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9D6\",\"tlb\":\"#A9D6 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] LSHIFT#DIVC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9D6tt\",\"stack\":\"x y - ceil(2^(tt+1)*x/y)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTDIVC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9D8\",\"tlb\":\"#A9D8 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] LSHIFT#MOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9D8tt\",\"stack\":\"x y - 2^(tt+1)*x mod y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTMOD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9D9\",\"tlb\":\"#A9D9 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] LSHIFT#MODR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9D9tt\",\"stack\":\"x y - 2^(tt+1)*x mod y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTMODR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9DA\",\"tlb\":\"#A9DA tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] LSHIFT#MODC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9DAtt\",\"stack\":\"x y - 2^(tt+1)*x mod y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTMODC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9DC\",\"tlb\":\"#A9DC tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] LSHIFT#DIVMOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9DCtt\",\"stack\":\"x y - q=floor(2^(tt+1)*x/y) r=2^(tt+1)*x-q*y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTDIVMOD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9DD\",\"tlb\":\"#A9DD tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] LSHIFT#DIVMODR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9DDtt\",\"stack\":\"x y - q=round(2^(tt+1)*x/y) r=2^(tt+1)*x-q*y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTDIVMODR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"A9DE\",\"tlb\":\"#A9DE tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_div\",\"description\":\"\",\"fift\":\"[tt+1] LSHIFT#DIVMODC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"A9DEtt\",\"stack\":\"x y - q=ceil(2^(tt+1)*x/y) r=2^(tt+1)*x-q*y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFTDIVMODC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"AA\",\"tlb\":\"#AA cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_logical\",\"description\":\"<p><code>0 &lt;= cc &lt;= 255</code></p>\\n\",\"fift\":\"[cc+1] LSHIFT#\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"AAcc\",\"stack\":\"x - x*2^(cc+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_lshift\",\"line\":740,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"AB\",\"tlb\":\"#AB cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_logical\",\"description\":\"<p><code>0 &lt;= cc &lt;= 255</code></p>\\n\",\"fift\":\"[cc+1] RSHIFT#\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"ABcc\",\"stack\":\"x - floor(x/2^(cc+1))\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_rshift\",\"line\":749,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"RSHIFT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"AC\",\"tlb\":\"#AC\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_logical\",\"description\":\"<p><code>0 &lt;= y &lt;= 1023</code></p>\\n\",\"fift\":\"LSHIFT\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"AC\",\"stack\":\"x y - x*2^y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_lshift_tinyint8\",\"line\":722,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LSHIFT_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"AD\",\"tlb\":\"#AD\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_logical\",\"description\":\"<p><code>0 &lt;= y &lt;= 1023</code></p>\\n\",\"fift\":\"RSHIFT\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"AD\",\"stack\":\"x y - floor(x/2^y)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_rshift_tinyint8\",\"line\":731,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"RSHIFT_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"AE\",\"tlb\":\"#AE\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_logical\",\"description\":\"<p><code>0 &lt;= y &lt;= 1023</code>\\nEquivalent to <code>ONE</code> <code>SWAP</code> <code>LSHIFT</code>.</p>\\n\",\"fift\":\"POW2\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"AE\",\"stack\":\"y - 2^y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_pow2\",\"line\":758,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"POW2\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B0\",\"tlb\":\"#B0\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_logical\",\"description\":\"<p>Bitwise and of two signed integers <code>x</code> and <code>y</code>, sign-extended to infinity.</p>\\n\",\"fift\":\"AND\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"B0\",\"stack\":\"x y - x&y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_and\",\"line\":769,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"AND\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B1\",\"tlb\":\"#B1\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_logical\",\"description\":\"<p>Bitwise or of two integers.</p>\\n\",\"fift\":\"OR\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"B1\",\"stack\":\"x y - x|y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_or\",\"line\":778,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"OR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B2\",\"tlb\":\"#B2\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_logical\",\"description\":\"<p>Bitwise xor of two integers.</p>\\n\",\"fift\":\"XOR\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"B2\",\"stack\":\"x y - x xor y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_xor\",\"line\":787,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"XOR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B3\",\"tlb\":\"#B3\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_logical\",\"description\":\"<p>Bitwise not of an integer.</p>\\n\",\"fift\":\"NOT\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"B3\",\"stack\":\"x - ~x\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_not\",\"line\":796,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"NOT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B4\",\"tlb\":\"#B4 cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_logical\",\"description\":\"<p>Checks whether <code>x</code> is a <code>cc+1</code>-bit signed integer for <code>0 &lt;= cc &lt;= 255</code> (i.e., whether <code>-2^cc &lt;= x &lt; 2^cc</code>).\\nIf not, either triggers an integer overflow exception, or replaces <code>x</code> with a <code>NaN</code> (quiet version).</p>\\n\",\"fift\":\"[cc+1] FITS\",\"fift_examples\":[],\"gas\":\"26/76\",\"opcode\":\"B4cc\",\"stack\":\"x - x\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_fits_tinyint8\",\"line\":804,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"FITS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B5\",\"tlb\":\"#B5 cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_logical\",\"description\":\"<p>Checks whether <code>x</code> is a <code>cc+1</code>-bit unsigned integer for <code>0 &lt;= cc &lt;= 255</code> (i.e., whether <code>0 &lt;= x &lt; 2^(cc+1)</code>).</p>\\n\",\"fift\":\"[cc+1] UFITS\",\"fift_examples\":[],\"gas\":\"26/76\",\"opcode\":\"B5cc\",\"stack\":\"x - x\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_ufits_tinyint8\",\"line\":817,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"UFITS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B600\",\"tlb\":\"#B600\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_logical\",\"description\":\"<p>Checks whether <code>x</code> is a <code>c</code>-bit signed integer for <code>0 &lt;= c &lt;= 1023</code>.</p>\\n\",\"fift\":\"FITSX\",\"fift_examples\":[],\"gas\":\"26/76\",\"opcode\":\"B600\",\"stack\":\"x c - x\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_fits\",\"line\":830,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"FITSX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B601\",\"tlb\":\"#B601\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_logical\",\"description\":\"<p>Checks whether <code>x</code> is a <code>c</code>-bit unsigned integer for <code>0 &lt;= c &lt;= 1023</code>.</p>\\n\",\"fift\":\"UFITSX\",\"fift_examples\":[],\"gas\":\"26/76\",\"opcode\":\"B601\",\"stack\":\"x c - x\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_ufits\",\"line\":843,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"UFITSX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B602\",\"tlb\":\"#B602\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_logical\",\"description\":\"<p>Computes smallest <code>c &gt;= 0</code> such that <code>x</code> fits into a <code>c</code>-bit signed integer (<code>-2^(c-1) &lt;= c &lt; 2^(c-1)</code>).</p>\\n\",\"fift\":\"BITSIZE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"B602\",\"stack\":\"x - c\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_bitsize\",\"line\":856,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"BITSIZE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B603\",\"tlb\":\"#B603\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_logical\",\"description\":\"<p>Computes smallest <code>c &gt;= 0</code> such that <code>x</code> fits into a <code>c</code>-bit unsigned integer (<code>0 &lt;= x &lt; 2^c</code>), or throws a range check exception.</p>\\n\",\"fift\":\"UBITSIZE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"B603\",\"stack\":\"x - c\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_bitsize\",\"line\":856,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"UBITSIZE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B608\",\"tlb\":\"#B608\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_logical\",\"description\":\"<p>Computes the minimum of two integers <code>x</code> and <code>y</code>.</p>\\n\",\"fift\":\"MIN\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"B608\",\"stack\":\"x y - x or y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_minmax\",\"line\":914,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MIN\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B609\",\"tlb\":\"#B609\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_logical\",\"description\":\"<p>Computes the maximum of two integers <code>x</code> and <code>y</code>.</p>\\n\",\"fift\":\"MAX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"B609\",\"stack\":\"x y - x or y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_minmax\",\"line\":914,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MAX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B60A\",\"tlb\":\"#B60A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_logical\",\"description\":\"<p>Sorts two integers. Quiet version of this operation returns two <code>NaN</code>s if any of the arguments are <code>NaN</code>s.</p>\\n\",\"fift\":\"MINMAX\\nINTSORT2\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"B60A\",\"stack\":\"x y - x y or y x\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_minmax\",\"line\":914,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"MINMAX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"r1\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B60B\",\"tlb\":\"#B60B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_logical\",\"description\":\"<p>Computes the absolute value of an integer <code>x</code>.</p>\\n\",\"fift\":\"ABS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"B60B\",\"stack\":\"x - |x|\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_abs\",\"line\":936,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"ABS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A0\",\"tlb\":\"#B7A0\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QADD\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"B7A0\",\"stack\":\"x y - x+y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_add\",\"line\":162,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QADD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A1\",\"tlb\":\"#B7A1\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QSUB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"B7A1\",\"stack\":\"x y - x-y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_sub\",\"line\":171,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QSUB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A2\",\"tlb\":\"#B7A2\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QSUBR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"B7A2\",\"stack\":\"x y - y-x\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_subr\",\"line\":180,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QSUBR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A3\",\"tlb\":\"#B7A3\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QNEGATE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"B7A3\",\"stack\":\"x - -x\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_negate\",\"line\":189,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QNEGATE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A4\",\"tlb\":\"#B7A4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QINC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"B7A4\",\"stack\":\"x - x+1\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_inc\",\"line\":197,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QINC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A5\",\"tlb\":\"#B7A5\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QDEC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"B7A5\",\"stack\":\"x - x-1\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_dec\",\"line\":205,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QDEC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A8\",\"tlb\":\"#B7A8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMUL\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"B7A8\",\"stack\":\"x y - x*y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mul\",\"line\":231,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMUL\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A900\",\"tlb\":\"#B7A900\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QADDDIVMOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A900\",\"stack\":\"x w z - q=floor((x+w)/z) r=(x+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QADDDIVMOD\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A901\",\"tlb\":\"#B7A901\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QADDDIVMODR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A901\",\"stack\":\"x w z - q=round((x+w)/z) r=(x+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QADDDIVMODR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A902\",\"tlb\":\"#B7A902\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QADDDIVMODC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A902\",\"stack\":\"x w y - q=ceil((x+w)/z) r=(x+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QADDDIVMODC\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A904\",\"tlb\":\"#B7A904\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"<p>Division returns <code>NaN</code> if <code>y=0</code>.</p>\\n\",\"fift\":\"QDIV\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A904\",\"stack\":\"x y - q\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QDIV\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A905\",\"tlb\":\"#B7A905\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QDIVR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A905\",\"stack\":\"x y - q'\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QDIVR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A906\",\"tlb\":\"#B7A906\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QDIVC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A906\",\"stack\":\"x y - q''\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QDIVC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A908\",\"tlb\":\"#B7A908\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A908\",\"stack\":\"x y - r\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMOD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A909\",\"tlb\":\"#B7A909\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMODR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A909\",\"stack\":\"x y - r\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMODR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A90A\",\"tlb\":\"#B7A90A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMODC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A90A\",\"stack\":\"x y - r\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMODC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A90C\",\"tlb\":\"#B7A90C\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QDIVMOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A90C\",\"stack\":\"x y - q r\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QDIVMOD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A90D\",\"tlb\":\"#B7A90D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QDIVMODR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A90D\",\"stack\":\"x y - q' r'\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QDIVMODR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A90E\",\"tlb\":\"#B7A90E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QDIVMODC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A90E\",\"stack\":\"x y - q'' r''\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_divmod\",\"line\":266,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QDIVMODC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A920\",\"tlb\":\"#B7A920\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QADDRSHIFTMOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A920\",\"stack\":\"x w z - q=floor((x+w)/2^z) r=(x+w)-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QADDRSHIFTMOD\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A921\",\"tlb\":\"#B7A921\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QADDRSHIFTMODR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A921\",\"stack\":\"x w z - q=round((x+w)/2^z) r=(x+w)-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QADDRSHIFTMODR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A922\",\"tlb\":\"#B7A922\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QADDRSHIFTMODC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A922\",\"stack\":\"x w z - q=ceil((x+w)/2^z) r=(x+w)-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QADDRSHIFTMODC\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A925\",\"tlb\":\"#B7A925\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QRSHIFTR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A925\",\"stack\":\"x y - round(x/2^y)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QRSHIFTR_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A926\",\"tlb\":\"#B7A926\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QRSHIFTC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A926\",\"stack\":\"x y - ceil(x/2^y)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QRSHIFTC_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A928\",\"tlb\":\"#B7A928\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMODPOW2\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A928\",\"stack\":\"x y - x mod 2^y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMODPOW2_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A929\",\"tlb\":\"#B7A929\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMODPOW2R\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A929\",\"stack\":\"x y - x mod 2^y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMODPOW2R_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A92A\",\"tlb\":\"#B7A92A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMODPOW2C\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A92A\",\"stack\":\"x y - x mod 2^y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMODPOW2C_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A92C\",\"tlb\":\"#B7A92C\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QRSHIFTMOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A92C\",\"stack\":\"x y - q=floor(x/2^y) r=x-q*2^y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QRSHIFTMOD_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A92D\",\"tlb\":\"#B7A92D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QRSHIFTMODR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A92D\",\"stack\":\"x y - q=round(x/2^y) r=x-q*2^y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QRSHIFTMODR_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A92E\",\"tlb\":\"#B7A92E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QRSHIFTMODC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A92E\",\"stack\":\"x y - q=ceil(x/2^y) r=x-q*2^y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QRSHIFTMODC_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A930\",\"tlb\":\"#B7A930 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QADDRSHIFT#MOD\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A930tt\",\"stack\":\"x w - q=floor((x+w)/2^(tt+1)) r=(x+w)-q*2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QADDRSHIFTMOD\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A931\",\"tlb\":\"#B7A931 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QADDRSHIFTR#MOD\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A931tt\",\"stack\":\"x w - q=round((x+w)/2^(tt+1)) r=(x+w)-q*2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QADDRSHIFTRMOD\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A932\",\"tlb\":\"#B7A932 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QADDRSHIFTC#MOD\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A932tt\",\"stack\":\"x w - q=round((x+w)/2^(tt+1)) r=(x+w)-q*2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QADDRSHIFTCMOD\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A935\",\"tlb\":\"#B7A935 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QRSHIFTR#\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A935tt\",\"stack\":\"x - round(x/2^(tt+1))\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QRSHIFTR\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A936\",\"tlb\":\"#B7A936 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QRSHIFTC#\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A936tt\",\"stack\":\"x - ceil(x/2^(tt+1))\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QRSHIFTC\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A938\",\"tlb\":\"#B7A938 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QMODPOW2#\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A938tt\",\"stack\":\"x - x mod 2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMODPOW2\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A939\",\"tlb\":\"#B7A939 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QMODPOW2R#\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A939tt\",\"stack\":\"x - x mod 2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMODPOW2R\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A93A\",\"tlb\":\"#B7A93A tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QMODPOW2C#\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A93Att\",\"stack\":\"x - x mod 2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMODPOW2C\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A93C\",\"tlb\":\"#B7A93C tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QRSHIFT#MOD\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A93Ctt\",\"stack\":\"x - q=floor(x/2^(tt+1)) r=x-q*2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QRSHIFTMOD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A93D\",\"tlb\":\"#B7A93D tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QRSHIFTR#MOD\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A93Dtt\",\"stack\":\"x - q=round(x/2^(tt+1)) r=x-q*2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QRSHIFTRMOD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A93E\",\"tlb\":\"#B7A93E tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QRSHIFTC#MOD\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A93Ett\",\"stack\":\"x - q=ceil(x/2^(tt+1)) r=x-q*2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QRSHIFTCMOD\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A980\",\"tlb\":\"#B7A980\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMULADDDIVMOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A980\",\"stack\":\"x y w z - q=floor((xy+w)/z) r=(xy+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULADDDIVMOD\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A981\",\"tlb\":\"#B7A981\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMULADDDIVMODR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A981\",\"stack\":\"x y w z - q=round((xy+w)/z) r=(xy+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULADDDIVMODR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A982\",\"tlb\":\"#B7A982\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMULADDDIVMODC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A982\",\"stack\":\"x y w z - q=ceil((xy+w)/z) r=(xy+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULADDDIVMODC\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A984\",\"tlb\":\"#B7A984\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"<p><code>q=floor(x*y/z)</code></p>\\n\",\"fift\":\"QMULDIV\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A984\",\"stack\":\"x y z - q\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULDIV\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A985\",\"tlb\":\"#B7A985\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMULDIVR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A985\",\"stack\":\"x y z - q'\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULDIVR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A986\",\"tlb\":\"#B7A986\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"<p><code>q'=ceil(x*y/z)</code></p>\\n\",\"fift\":\"QMULDIVC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A986\",\"stack\":\"x y z - q'\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULDIVC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A988\",\"tlb\":\"#B7A988\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMULMOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A988\",\"stack\":\"x y z - x*y mod z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULMOD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A989\",\"tlb\":\"#B7A989\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMULMODR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A989\",\"stack\":\"x y z - x*y mod z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULMODR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A98A\",\"tlb\":\"#B7A98A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMULMODC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A98A\",\"stack\":\"x y z - x*y mod z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULMODC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A98C\",\"tlb\":\"#B7A98C\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMULDIVMOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A98C\",\"stack\":\"x y z - q r\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULDIVMOD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A98D\",\"tlb\":\"#B7A98D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"<p><code>q=round(x*y/z)</code>, <code>r=x*y-z*q</code></p>\\n\",\"fift\":\"QMULDIVMODR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A98D\",\"stack\":\"x y z - q r\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULDIVMODR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A98E\",\"tlb\":\"#B7A98E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"<p><code>q=ceil(x*y/z)</code>, <code>r=x*y-z*q</code></p>\\n\",\"fift\":\"QMULDIVMODC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A98E\",\"stack\":\"x y z - q r\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_muldivmod\",\"line\":434,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULDIVMODC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9A0\",\"tlb\":\"#B7A9A0\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMULADDRSHIFTMOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9A0\",\"stack\":\"x y w z - q=floor((xy+w)/2^z) r=(xy+w)-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULADDRSHIFTMOD_VAR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9A1\",\"tlb\":\"#B7A9A1\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMULADDRSHIFTRMOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9A1\",\"stack\":\"x y w z - q=round((xy+w)/2^z) r=(xy+w)-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULADDRSHIFTRMOD_VAR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9A2\",\"tlb\":\"#B7A9A2\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMULADDRSHIFTCMOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9A2\",\"stack\":\"x y w z - q=ceil((xy+w)/2^z) r=(xy+w)-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULADDRSHIFTCMOD_VAR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"q\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9A4\",\"tlb\":\"#B7A9A4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"<p><code>0 &lt;= z &lt;= 256</code></p>\\n\",\"fift\":\"QMULRSHIFT\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9A4\",\"stack\":\"x y z - floor(x*y/2^z)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULRSHIFT_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9A5\",\"tlb\":\"#B7A9A5\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"<p><code>0 &lt;= z &lt;= 256</code></p>\\n\",\"fift\":\"QMULRSHIFTR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9A5\",\"stack\":\"x y z - round(x*y/2^z)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULRSHIFTR_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9A6\",\"tlb\":\"#B7A9A6\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"<p><code>0 &lt;= z &lt;= 256</code></p>\\n\",\"fift\":\"QMULRSHIFTC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9A6\",\"stack\":\"x y z - ceil(x*y/2^z)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULRSHIFTC_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9A8\",\"tlb\":\"#B7A9A8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMULMODPOW2_VAR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9A8\",\"stack\":\"x y z - x*y mod 2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULMODPOW2_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9A9\",\"tlb\":\"#B7A9A9\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMULMODPOW2R_VAR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9A9\",\"stack\":\"x y z - x*y mod 2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULMODPOW2R_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9AA\",\"tlb\":\"#B7A9AA\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMULMODPOW2C_VAR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9AA\",\"stack\":\"x y z - x*y mod 2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULMODPOW2C_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9AC\",\"tlb\":\"#B7A9AC\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMULRSHIFTMOD_VAR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9AC\",\"stack\":\"x y z - q=floor(x*y/2^z) r=xy-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULRSHIFTMOD_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9AD\",\"tlb\":\"#B7A9AD\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMULRSHIFTRMOD_VAR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9AD\",\"stack\":\"x y z - q=round(x*y/2^z) r=xy-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULRSHIFTRMOD_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9AE\",\"tlb\":\"#B7A9AE\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMULRSHIFTCMOD_VAR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9AE\",\"stack\":\"x y z - q=ceil(x*y/2^z) r=xy-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULRSHIFTCMOD_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9B0\",\"tlb\":\"#B7A9B0 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QMULADDRSHIFT#MOD\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9B0tt\",\"stack\":\"x y w - q=floor((xy+w)/2^z) r=(xy+w)-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULADDRSHIFTMOD\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9B1\",\"tlb\":\"#B7A9B1 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QMULADDRSHIFTR#MOD\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9B1tt\",\"stack\":\"x y w - q=round((xy+w)/2^z) r=(xy+w)-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULADDRSHIFTRMOD\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9B2\",\"tlb\":\"#B7A9B2 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QMULADDRSHIFTC#MOD\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9B2tt\",\"stack\":\"x y w - q=ceil((xy+w)/2^z) r=(xy+w)-q*2^z\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shrmod\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULADDRSHIFTCMOD\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9B4\",\"tlb\":\"#B7A9B4 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QMULRSHIFT#\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9B4tt\",\"stack\":\"x y - floor(x*y/2^(tt+1))\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULRSHIFT\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9B5\",\"tlb\":\"#B7A9B5 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QMULRSHIFTR#\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9B5tt\",\"stack\":\"x y - round(x*y/2^(tt+1))\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULRSHIFTR\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9B6\",\"tlb\":\"#B7A9B6 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QMULRSHIFTC#\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9B6tt\",\"stack\":\"x y - ceil(x*y/2^(tt+1))\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULRSHIFTC\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9B8\",\"tlb\":\"#B7A9B8 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QMULMODPOW2#\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9B8tt\",\"stack\":\"x y - x*y mod 2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULMODPOW2\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9B9\",\"tlb\":\"#B7A9B9 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QMULMODPOW2R#\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9B9tt\",\"stack\":\"x y - x*y mod 2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULMODPOW2R\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9BA\",\"tlb\":\"#B7A9BA tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QMULMODPOW2C#\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9BAtt\",\"stack\":\"x y - x*y mod 2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULMODPOW2C\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9BC\",\"tlb\":\"#B7A9BC\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMULRSHIFT#MOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9BC\",\"stack\":\"x y - q=floor(x*y/2^(tt+1)) r=xy-q*2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULRSHIFTMOD\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9BD\",\"tlb\":\"#B7A9BD\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMULRSHIFTR#MOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9BD\",\"stack\":\"x y - q=round(x*y/2^(tt+1)) r=xy-q*2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULRSHIFTRMOD\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9BE\",\"tlb\":\"#B7A9BE\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QMULRSHIFTC#MOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9BE\",\"stack\":\"x y - q=ceil(x*y/2^(tt+1)) r=xy-q*2^(tt+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_mulshrmod\",\"line\":497,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QMULRSHIFTCMOD\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9C0\",\"tlb\":\"#B7A9C0\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QLSHIFTADDDIVMOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9C0\",\"stack\":\"x w z y - q=floor((x*2^y+w)/z) r=(x*2^y+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTADDDIVMOD_VAR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9C1\",\"tlb\":\"#B7A9C1\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QLSHIFTADDDIVMODR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9C1\",\"stack\":\"x w z y - q=round((x*2^y+w)/z) r=(x*2^y+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTADDDIVMODR_VAR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9C2\",\"tlb\":\"#B7A9C2\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QLSHIFTADDDIVMODC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9C2\",\"stack\":\"x w z y - q=round((x*2^y+w)/z) r=(x*2^y+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTADDDIVMODC_VAR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9C4\",\"tlb\":\"#B7A9C4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"<p><code>0 &lt;= z &lt;= 256</code></p>\\n\",\"fift\":\"QLSHIFTDIV\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9C4\",\"stack\":\"x y z - floor(2^z*x/y)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTDIV_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9C5\",\"tlb\":\"#B7A9C5\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"<p><code>0 &lt;= z &lt;= 256</code></p>\\n\",\"fift\":\"QLSHIFTDIVR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9C5\",\"stack\":\"x y z - round(2^z*x/y)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTDIVR_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9C6\",\"tlb\":\"#B7A9C6\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"<p><code>0 &lt;= z &lt;= 256</code></p>\\n\",\"fift\":\"QLSHIFTDIVC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9C6\",\"stack\":\"x y z - ceil(2^z*x/y)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTDIVC_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9C8\",\"tlb\":\"#B7A9C8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QLSHIFTMOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9C8\",\"stack\":\"x y z - 2^z*x mod y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTMOD_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9C9\",\"tlb\":\"#B7A9C9\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QLSHIFTMODR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9C9\",\"stack\":\"x y z - 2^z*x mod y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTMODR_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9CA\",\"tlb\":\"#B7A9CA\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QLSHIFTMODC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9CA\",\"stack\":\"x y z - 2^z*x mod y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTMODC_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9CC\",\"tlb\":\"#B7A9CC\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QLSHIFTDIVMOD\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9CC\",\"stack\":\"x y z - q=floor(2^z*x/y) r=2^z*x-q*y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTDIVMOD_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9CD\",\"tlb\":\"#B7A9CD\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QLSHIFTDIVMODR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9CD\",\"stack\":\"x y z - q=round(2^z*x/y) r=2^z*x-q*y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTDIVMODR_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7A9CE\",\"tlb\":\"#B7A9CE\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QLSHIFTDIVMODC\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7A9CE\",\"stack\":\"x y z - q=ceil(2^z*x/y) r=2^z*x-q*y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTDIVMODC_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9D0\",\"tlb\":\"#B7A9D0 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QLSHIFT#ADDDIVMOD\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9D0tt\",\"stack\":\"x w z - q=floor((x*2^(tt+1)+w)/z) r=(x*2^(tt+1)+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTADDDIVMOD\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9D1\",\"tlb\":\"#B7A9D1 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QLSHIFT#ADDDIVMODR\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9D1tt\",\"stack\":\"x w z - q=round((x*2^(tt+1)+w)/z) r=(x*2^(tt+1)+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTADDDIVMODR\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9D2\",\"tlb\":\"#B7A9D2 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QLSHIFT#ADDDIVMODC\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9D2tt\",\"stack\":\"x w z - q=ceil((x*2^(tt+1)+w)/z) r=(x*2^(tt+1)+w)-zq\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTADDDIVMODC\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"w\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9D4\",\"tlb\":\"#B7A9D4 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QLSHIFT#DIV\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9D4tt\",\"stack\":\"x y - floor(2^(tt+1)*x/y)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTDIV\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9D5\",\"tlb\":\"#B7A9D5 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QLSHIFT#DIVR\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9D5tt\",\"stack\":\"x y - round(2^(tt+1)*x/y)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTDIVR\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9D6\",\"tlb\":\"#B7A9D6 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QLSHIFT#DIVC\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9D6tt\",\"stack\":\"x y - ceil(2^(tt+1)*x/y)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTDIVC\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9D8\",\"tlb\":\"#B7A9D8 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QLSHIFT#MOD\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9D8tt\",\"stack\":\"x y - 2^(tt+1)*x mod y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTMOD\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9D9\",\"tlb\":\"#B7A9D9 tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QLSHIFT#MODR\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9D9tt\",\"stack\":\"x y - 2^(tt+1)*x mod y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTMODR\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9DA\",\"tlb\":\"#B7A9DA tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QLSHIFT#MODC\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9DAtt\",\"stack\":\"x y - 2^(tt+1)*x mod y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTMODC\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9DC\",\"tlb\":\"#B7A9DC tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QLSHIFT#DIVMOD\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9DCtt\",\"stack\":\"x y - q=floor(2^(tt+1)*x/y) r=2^(tt+1)*x-q*y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTDIVMOD\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9DD\",\"tlb\":\"#B7A9DD tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QLSHIFT#DIVMODR\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9DDtt\",\"stack\":\"x y - q=round(2^(tt+1)*x/y) r=2^(tt+1)*x-q*y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTDIVMODR\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"t\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7A9DE\",\"tlb\":\"#B7A9DE tt:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"[tt+1] QLSHIFT#DIVMODC\",\"fift_examples\":[],\"gas\":\"42\",\"opcode\":\"B7A9DEtt\",\"stack\":\"x y - q=ceil(2^(tt+1)*x/y) r=2^(tt+1)*x-q*y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_shldivmod\",\"line\":595,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFTDIVMODC\",\"since_version\":9999,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7AA\",\"tlb\":\"#B7AA cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"<p><code>0 &lt;= cc &lt;= 255</code></p>\\n\",\"fift\":\"[cc+1] QLSHIFT#\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7AAcc\",\"stack\":\"x - x*2^(cc+1)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_lshift\",\"line\":740,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7AB\",\"tlb\":\"#B7AB cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"<p><code>0 &lt;= cc &lt;= 255</code></p>\\n\",\"fift\":\"[cc+1] QRSHIFT#\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7ABcc\",\"stack\":\"x - floor(x/2^(cc+1))\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_rshift\",\"line\":749,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QRSHIFT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7AC\",\"tlb\":\"#B7AC\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QLSHIFT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"B7AC\",\"stack\":\"x y - x*2^y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_lshift\",\"line\":740,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QLSHIFT_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7AD\",\"tlb\":\"#B7AD\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QRSHIFT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"B7AD\",\"stack\":\"x y - floor(x/2^y)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_rshift\",\"line\":749,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QRSHIFT_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7AE\",\"tlb\":\"#B7AE\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QPOW2\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"B7AE\",\"stack\":\"y - 2^y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_pow2\",\"line\":758,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QPOW2\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7B0\",\"tlb\":\"#B7B0\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QAND\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"B7B0\",\"stack\":\"x y - x&y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_and\",\"line\":769,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QAND\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7B1\",\"tlb\":\"#B7B1\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QOR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"B7B1\",\"stack\":\"x y - x|y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_or\",\"line\":778,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QOR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7B2\",\"tlb\":\"#B7B2\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QXOR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"B7B2\",\"stack\":\"x y - x xor y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_xor\",\"line\":787,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QXOR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7B3\",\"tlb\":\"#B7B3\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"\",\"fift\":\"QNOT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"B7B3\",\"stack\":\"x - ~x\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_not\",\"line\":796,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QNOT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7B4\",\"tlb\":\"#B7B4 cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"<p>Replaces <code>x</code> with a <code>NaN</code> if x is not a <code>cc+1</code>-bit signed integer, leaves it intact otherwise.</p>\\n\",\"fift\":\"[cc+1] QFITS\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7B4cc\",\"stack\":\"x - x\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_fits\",\"line\":830,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QFITS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"B7B5\",\"tlb\":\"#B7B5 cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"<p>Replaces <code>x</code> with a <code>NaN</code> if x is not a <code>cc+1</code>-bit unsigned integer, leaves it intact otherwise.</p>\\n\",\"fift\":\"[cc+1] QUFITS\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7B5cc\",\"stack\":\"x - x\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_fits\",\"line\":830,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QUFITS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7B600\",\"tlb\":\"#B7B600\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"<p>Replaces <code>x</code> with a <code>NaN</code> if x is not a c-bit signed integer, leaves it intact otherwise.</p>\\n\",\"fift\":\"QFITSX\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7B600\",\"stack\":\"x c - x\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_fits\",\"line\":830,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QFITSX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7B601\",\"tlb\":\"#B7B601\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"arithm_quiet\",\"description\":\"<p>Replaces <code>x</code> with a <code>NaN</code> if x is not a c-bit unsigned integer, leaves it intact otherwise.</p>\\n\",\"fift\":\"QUFITSX\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"B7B601\",\"stack\":\"x c - x\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_ufits\",\"line\":843,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"QUFITSX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B8\",\"tlb\":\"#B8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_int\",\"description\":\"<p>Computes the sign of an integer <code>x</code>:\\n<code>-1</code> if <code>x&lt;0</code>, <code>0</code> if <code>x=0</code>, <code>1</code> if <code>x&gt;0</code>.</p>\\n\",\"fift\":\"SGN\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"B8\",\"stack\":\"x - sgn(x)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_sgn\",\"line\":961,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"SGN\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B9\",\"tlb\":\"#B9\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_int\",\"description\":\"<p>Returns <code>-1</code> if <code>x&lt;y</code>, <code>0</code> otherwise.</p>\\n\",\"fift\":\"LESS\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"B9\",\"stack\":\"x y - x<y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_cmp\",\"line\":975,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LESS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"BA\",\"tlb\":\"#BA\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_int\",\"description\":\"<p>Returns <code>-1</code> if <code>x=y</code>, <code>0</code> otherwise.</p>\\n\",\"fift\":\"EQUAL\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"BA\",\"stack\":\"x y - x=y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_cmp\",\"line\":975,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"EQUAL\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"BB\",\"tlb\":\"#BB\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_int\",\"description\":\"\",\"fift\":\"LEQ\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"BB\",\"stack\":\"x y - x<=y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_cmp\",\"line\":975,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LEQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"BC\",\"tlb\":\"#BC\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_int\",\"description\":\"\",\"fift\":\"GREATER\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"BC\",\"stack\":\"x y - x>y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_cmp\",\"line\":975,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"GREATER\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"BD\",\"tlb\":\"#BD\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_int\",\"description\":\"<p>Equivalent to <code>EQUAL</code> <code>NOT</code>.</p>\\n\",\"fift\":\"NEQ\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"BD\",\"stack\":\"x y - x!=y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_cmp\",\"line\":975,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"NEQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"BE\",\"tlb\":\"#BE\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_int\",\"description\":\"<p>Equivalent to <code>LESS</code> <code>NOT</code>.</p>\\n\",\"fift\":\"GEQ\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"BE\",\"stack\":\"x y - x>=y\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_cmp\",\"line\":975,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"GEQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"BF\",\"tlb\":\"#BF\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_int\",\"description\":\"<p>Computes the sign of <code>x-y</code>:\\n<code>-1</code> if <code>x&lt;y</code>, <code>0</code> if <code>x=y</code>, <code>1</code> if <code>x&gt;y</code>.\\nNo integer overflow can occur here unless <code>x</code> or <code>y</code> is a <code>NaN</code>.</p>\\n\",\"fift\":\"CMP\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"BF\",\"stack\":\"x y - sgn(x-y)\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_cmp\",\"line\":975,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"CMP\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":127,\"min_value\":-128,\"name\":\"y\",\"size\":8,\"type\":\"int\"}],\"prefix\":\"C0\",\"tlb\":\"#C0 yy:int8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_int\",\"description\":\"<p>Returns <code>-1</code> if <code>x=yy</code>, <code>0</code> otherwise.\\n<code>-2^7 &lt;= yy &lt; 2^7</code>.</p>\\n\",\"fift\":\"[yy] EQINT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C0yy\",\"stack\":\"x - x=yy\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_cmp_int\",\"line\":992,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"EQINT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":127,\"min_value\":-128,\"name\":\"y\",\"size\":8,\"type\":\"int\"}],\"prefix\":\"C1\",\"tlb\":\"#C1 yy:int8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_int\",\"description\":\"<p>Returns <code>-1</code> if <code>x&lt;yy</code>, <code>0</code> otherwise.\\n<code>-2^7 &lt;= yy &lt; 2^7</code>.</p>\\n\",\"fift\":\"[yy] LESSINT\\n[yy-1] LEQINT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C1yy\",\"stack\":\"x - x<yy\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_cmp_int\",\"line\":992,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"LESSINT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":127,\"min_value\":-128,\"name\":\"y\",\"size\":8,\"type\":\"int\"}],\"prefix\":\"C2\",\"tlb\":\"#C2 yy:int8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_int\",\"description\":\"<p>Returns <code>-1</code> if <code>x&gt;yy</code>, <code>0</code> otherwise.\\n<code>-2^7 &lt;= yy &lt; 2^7</code>.</p>\\n\",\"fift\":\"[yy] GTINT\\n[yy+1] GEQINT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C2yy\",\"stack\":\"x - x>yy\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_cmp_int\",\"line\":992,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"GTINT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":127,\"min_value\":-128,\"name\":\"y\",\"size\":8,\"type\":\"int\"}],\"prefix\":\"C3\",\"tlb\":\"#C3 yy:int8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_int\",\"description\":\"<p>Returns <code>-1</code> if <code>x!=yy</code>, <code>0</code> otherwise.\\n<code>-2^7 &lt;= yy &lt; 2^7</code>.</p>\\n\",\"fift\":\"[yy] NEQINT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C3yy\",\"stack\":\"x - x!=yy\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_cmp_int\",\"line\":992,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"NEQINT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C4\",\"tlb\":\"#C4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_int\",\"description\":\"<p>Checks whether <code>x</code> is a <code>NaN</code>.</p>\\n\",\"fift\":\"ISNAN\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"C4\",\"stack\":\"x - x=NaN\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_is_nan\",\"line\":1007,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"ISNAN\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C5\",\"tlb\":\"#C5\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_int\",\"description\":\"<p>Throws an arithmetic overflow exception if <code>x</code> is a <code>NaN</code>.</p>\\n\",\"fift\":\"CHKNAN\",\"fift_examples\":[],\"gas\":\"18/68\",\"opcode\":\"C5\",\"stack\":\"x - x\"},\"implementation\":[{\"file\":\"arithops.cpp\",\"function_name\":\"exec_chk_nan\",\"line\":1016,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/arithops.cpp\"}],\"mnemonic\":\"CHKNAN\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C700\",\"tlb\":\"#C700\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_other\",\"description\":\"<p>Checks whether a <em>Slice</em> <code>s</code> is empty (i.e., contains no bits of data and no cell references).</p>\\n\",\"fift\":\"SEMPTY\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C700\",\"stack\":\"s - ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_un_cs_cmp\",\"line\":251,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SEMPTY\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C701\",\"tlb\":\"#C701\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_other\",\"description\":\"<p>Checks whether <em>Slice</em> <code>s</code> has no bits of data.</p>\\n\",\"fift\":\"SDEMPTY\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C701\",\"stack\":\"s - ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_un_cs_cmp\",\"line\":251,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDEMPTY\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C702\",\"tlb\":\"#C702\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_other\",\"description\":\"<p>Checks whether <em>Slice</em> <code>s</code> has no references.</p>\\n\",\"fift\":\"SREMPTY\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C702\",\"stack\":\"s - ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_un_cs_cmp\",\"line\":251,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SREMPTY\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C703\",\"tlb\":\"#C703\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_other\",\"description\":\"<p>Checks whether the first bit of <em>Slice</em> <code>s</code> is a one.</p>\\n\",\"fift\":\"SDFIRST\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C703\",\"stack\":\"s - ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_un_cs_cmp\",\"line\":251,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDFIRST\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C704\",\"tlb\":\"#C704\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_other\",\"description\":\"<p>Compares the data of <code>s</code> lexicographically with the data of <code>s'</code>, returning <code>-1</code>, 0, or 1 depending on the result.</p>\\n\",\"fift\":\"SDLEXCMP\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C704\",\"stack\":\"s s' - x\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_ibin_cs_cmp\",\"line\":277,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDLEXCMP\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C705\",\"tlb\":\"#C705\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_other\",\"description\":\"<p>Checks whether the data parts of <code>s</code> and <code>s'</code> coincide, equivalent to <code>SDLEXCMP</code> <code>ISZERO</code>.</p>\\n\",\"fift\":\"SDEQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C705\",\"stack\":\"s s' - ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_bin_cs_cmp\",\"line\":267,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDEQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C708\",\"tlb\":\"#C708\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_other\",\"description\":\"<p>Checks whether <code>s</code> is a prefix of <code>s'</code>.</p>\\n\",\"fift\":\"SDPFX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C708\",\"stack\":\"s s' - ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_bin_cs_cmp\",\"line\":267,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDPFX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C709\",\"tlb\":\"#C709\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_other\",\"description\":\"<p>Checks whether <code>s'</code> is a prefix of <code>s</code>, equivalent to <code>SWAP</code> <code>SDPFX</code>.</p>\\n\",\"fift\":\"SDPFXREV\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C709\",\"stack\":\"s s' - ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_bin_cs_cmp\",\"line\":267,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDPFXREV\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C70A\",\"tlb\":\"#C70A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_other\",\"description\":\"<p>Checks whether <code>s</code> is a proper prefix of <code>s'</code> (i.e., a prefix distinct from <code>s'</code>).</p>\\n\",\"fift\":\"SDPPFX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C70A\",\"stack\":\"s s' - ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_bin_cs_cmp\",\"line\":267,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDPPFX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C70B\",\"tlb\":\"#C70B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_other\",\"description\":\"<p>Checks whether <code>s'</code> is a proper prefix of <code>s</code>.</p>\\n\",\"fift\":\"SDPPFXREV\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C70B\",\"stack\":\"s s' - ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_bin_cs_cmp\",\"line\":267,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDPPFXREV\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C70C\",\"tlb\":\"#C70C\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_other\",\"description\":\"<p>Checks whether <code>s</code> is a suffix of <code>s'</code>.</p>\\n\",\"fift\":\"SDSFX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C70C\",\"stack\":\"s s' - ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_bin_cs_cmp\",\"line\":267,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDSFX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C70D\",\"tlb\":\"#C70D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_other\",\"description\":\"<p>Checks whether <code>s'</code> is a suffix of <code>s</code>.</p>\\n\",\"fift\":\"SDSFXREV\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C70D\",\"stack\":\"s s' - ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_bin_cs_cmp\",\"line\":267,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDSFXREV\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C70E\",\"tlb\":\"#C70E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_other\",\"description\":\"<p>Checks whether <code>s</code> is a proper suffix of <code>s'</code>.</p>\\n\",\"fift\":\"SDPSFX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C70E\",\"stack\":\"s s' - ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_bin_cs_cmp\",\"line\":267,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDPSFX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C70F\",\"tlb\":\"#C70F\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_other\",\"description\":\"<p>Checks whether <code>s'</code> is a proper suffix of <code>s</code>.</p>\\n\",\"fift\":\"SDPSFXREV\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C70F\",\"stack\":\"s s' - ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_bin_cs_cmp\",\"line\":267,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDPSFXREV\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C710\",\"tlb\":\"#C710\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_other\",\"description\":\"<p>Returns the number of leading zeroes in <code>s</code>.</p>\\n\",\"fift\":\"SDCNTLEAD0\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C710\",\"stack\":\"s - n\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_iun_cs_cmp\",\"line\":259,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDCNTLEAD0\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C711\",\"tlb\":\"#C711\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_other\",\"description\":\"<p>Returns the number of leading ones in <code>s</code>.</p>\\n\",\"fift\":\"SDCNTLEAD1\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C711\",\"stack\":\"s - n\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_iun_cs_cmp\",\"line\":259,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDCNTLEAD1\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C712\",\"tlb\":\"#C712\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_other\",\"description\":\"<p>Returns the number of trailing zeroes in <code>s</code>.</p>\\n\",\"fift\":\"SDCNTTRAIL0\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C712\",\"stack\":\"s - n\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_iun_cs_cmp\",\"line\":259,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDCNTTRAIL0\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C713\",\"tlb\":\"#C713\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"compare_other\",\"description\":\"<p>Returns the number of trailing ones in <code>s</code>.</p>\\n\",\"fift\":\"SDCNTTRAIL1\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"C713\",\"stack\":\"s - n\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_iun_cs_cmp\",\"line\":259,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDCNTTRAIL1\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C8\",\"tlb\":\"#C8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Creates a new empty <em>Builder</em>.</p>\\n\",\"fift\":\"NEWC\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"C8\",\"stack\":\"- b\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_new_builder\",\"line\":334,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"NEWC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"C9\",\"tlb\":\"#C9\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Converts a <em>Builder</em> into an ordinary <em>Cell</em>.</p>\\n\",\"fift\":\"ENDC\",\"fift_examples\":[],\"gas\":\"518\",\"opcode\":\"C9\",\"stack\":\"b - c\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_builder_to_cell\",\"line\":341,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"ENDC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"CA\",\"tlb\":\"#CA cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Stores a signed <code>cc+1</code>-bit integer <code>x</code> into <em>Builder</em> <code>b</code> for <code>0 &lt;= cc &lt;= 255</code>, throws a range check exception if <code>x</code> does not fit into <code>cc+1</code> bits.</p>\\n\",\"fift\":\"[cc+1] STI\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CAcc\",\"stack\":\"x b - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_fixed\",\"line\":622,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STI\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"CB\",\"tlb\":\"#CB cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Stores an unsigned <code>cc+1</code>-bit integer <code>x</code> into <em>Builder</em> <code>b</code>. In all other respects it is similar to <code>STI</code>.</p>\\n\",\"fift\":\"[cc+1] STU\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CBcc\",\"stack\":\"x b - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_fixed\",\"line\":622,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STU\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CC\",\"tlb\":\"#CC\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Stores a reference to <em>Cell</em> <code>c</code> into <em>Builder</em> <code>b</code>.</p>\\n\",\"fift\":\"STREF\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"CC\",\"stack\":\"c b - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_ref\",\"line\":415,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CD\",\"tlb\":\"#CD\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Equivalent to <code>ENDC</code> <code>SWAP</code> <code>STREF</code>.</p>\\n\",\"fift\":\"STBREFR\\nENDCST\",\"fift_examples\":[],\"gas\":\"518\",\"opcode\":\"CD\",\"stack\":\"b b'' - b\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_builder_as_ref_rev\",\"line\":484,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STBREFR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"child\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CE\",\"tlb\":\"#CE\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Stores <em>Slice</em> <code>s</code> into <em>Builder</em> <code>b</code>.</p>\\n\",\"fift\":\"STSLICE\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"CE\",\"stack\":\"s b - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_slice\",\"line\":507,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STSLICE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF00\",\"tlb\":\"#CF00\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Stores a signed <code>l</code>-bit integer <code>x</code> into <code>b</code> for <code>0 &lt;= l &lt;= 257</code>.</p>\\n\",\"fift\":\"STIX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF00\",\"stack\":\"x b l - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_var\",\"line\":599,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STIX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF01\",\"tlb\":\"#CF01\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Stores an unsigned <code>l</code>-bit integer <code>x</code> into <code>b</code> for <code>0 &lt;= l &lt;= 256</code>.</p>\\n\",\"fift\":\"STUX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF01\",\"stack\":\"x b l - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_var\",\"line\":599,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STUX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF02\",\"tlb\":\"#CF02\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Similar to <code>STIX</code>, but with arguments in a different order.</p>\\n\",\"fift\":\"STIXR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF02\",\"stack\":\"b x l - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_var\",\"line\":599,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STIXR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF03\",\"tlb\":\"#CF03\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Similar to <code>STUX</code>, but with arguments in a different order.</p>\\n\",\"fift\":\"STUXR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF03\",\"stack\":\"b x l - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_var\",\"line\":599,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STUXR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF04\",\"tlb\":\"#CF04\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>A quiet version of <code>STIX</code>. If there is no space in <code>b</code>, sets <code>b'=b</code> and <code>f=-1</code>.\\nIf <code>x</code> does not fit into <code>l</code> bits, sets <code>b'=b</code> and <code>f=1</code>.\\nIf the operation succeeds, <code>b'</code> is the new <em>Builder</em> and <code>f=0</code>.\\nHowever, <code>0 &lt;= l &lt;= 257</code>, with a range check exception if this is not so.</p>\\n\",\"fift\":\"STIXQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF04\",\"stack\":\"x b l - x b f or b' 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_var\",\"line\":599,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STIXQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":-1},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF05\",\"tlb\":\"#CF05\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>A quiet version of <code>STUX</code>.</p>\\n\",\"fift\":\"STUXQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF05\",\"stack\":\"x b l - x b f or b' 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_var\",\"line\":599,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STUXQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":-1},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF06\",\"tlb\":\"#CF06\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>A quiet version of <code>STIXR</code>.</p>\\n\",\"fift\":\"STIXRQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF06\",\"stack\":\"b x l - b x f or b' 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_var\",\"line\":599,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STIXRQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":0},{\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1},{\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF07\",\"tlb\":\"#CF07\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>A quiet version of <code>STUXR</code>.</p>\\n\",\"fift\":\"STUXRQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF07\",\"stack\":\"b x l - b x f or b' 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_var\",\"line\":599,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STUXRQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":0},{\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1},{\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"CF08\",\"tlb\":\"#CF08 cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>A longer version of <code>[cc+1] STI</code>.</p>\\n\",\"fift\":\"[cc+1] STI_l\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"CF08cc\",\"stack\":\"x b - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_fixed\",\"line\":622,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STI_ALT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"CF09\",\"tlb\":\"#CF09 cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>A longer version of <code>[cc+1] STU</code>.</p>\\n\",\"fift\":\"[cc+1] STU_l\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"CF09cc\",\"stack\":\"x b - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_fixed\",\"line\":622,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STU_ALT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"CF0A\",\"tlb\":\"#CF0A cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Equivalent to <code>SWAP</code> <code>[cc+1] STI</code>.</p>\\n\",\"fift\":\"[cc+1] STIR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"CF0Acc\",\"stack\":\"b x - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_fixed\",\"line\":622,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STIR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"CF0B\",\"tlb\":\"#CF0B cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Equivalent to <code>SWAP</code> <code>[cc+1] STU</code>.</p>\\n\",\"fift\":\"[cc+1] STUR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"CF0Bcc\",\"stack\":\"b x - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_fixed\",\"line\":622,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STUR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"CF0C\",\"tlb\":\"#CF0C cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>A quiet version of <code>STI</code>.</p>\\n\",\"fift\":\"[cc+1] STIQ\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"CF0Ccc\",\"stack\":\"x b - x b f or b' 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_fixed\",\"line\":622,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STIQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":-1},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"CF0D\",\"tlb\":\"#CF0D cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>A quiet version of <code>STU</code>.</p>\\n\",\"fift\":\"[cc+1] STUQ\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"CF0Dcc\",\"stack\":\"x b - x b f or b' 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_fixed\",\"line\":622,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STUQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":-1},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"CF0E\",\"tlb\":\"#CF0E cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>A quiet version of <code>STIR</code>.</p>\\n\",\"fift\":\"[cc+1] STIRQ\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"CF0Ecc\",\"stack\":\"b x - b x f or b' 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_fixed\",\"line\":622,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STIRQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":0},{\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1},{\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"CF0F\",\"tlb\":\"#CF0F cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>A quiet version of <code>STUR</code>.</p>\\n\",\"fift\":\"[cc+1] STURQ\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"CF0Fcc\",\"stack\":\"b x - b x f or b' 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_fixed\",\"line\":622,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STURQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":0},{\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1},{\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF10\",\"tlb\":\"#CF10\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>A longer version of <code>STREF</code>.</p>\\n\",\"fift\":\"STREF_l\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF10\",\"stack\":\"c b - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_ref_rev\",\"line\":438,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STREF_ALT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF11\",\"tlb\":\"#CF11\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Equivalent to <code>SWAP</code> <code>STBREFR</code>.</p>\\n\",\"fift\":\"STBREF\",\"fift_examples\":[],\"gas\":\"526\",\"opcode\":\"CF11\",\"stack\":\"b' b - b''\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_builder_as_ref\",\"line\":461,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STBREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"child\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF12\",\"tlb\":\"#CF12\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>A longer version of <code>STSLICE</code>.</p>\\n\",\"fift\":\"STSLICE_l\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF12\",\"stack\":\"s b - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_slice\",\"line\":507,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STSLICE_ALT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF13\",\"tlb\":\"#CF13\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Appends all data from <em>Builder</em> <code>b'</code> to <em>Builder</em> <code>b</code>.</p>\\n\",\"fift\":\"STB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF13\",\"stack\":\"b' b - b''\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_builder\",\"line\":553,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b3\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF14\",\"tlb\":\"#CF14\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Equivalent to <code>SWAP</code> <code>STREF</code>.</p>\\n\",\"fift\":\"STREFR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF14\",\"stack\":\"b c - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_ref_rev\",\"line\":438,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STREFR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF15\",\"tlb\":\"#CF15\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>A longer encoding of <code>STBREFR</code>.</p>\\n\",\"fift\":\"STBREFR_l\",\"fift_examples\":[],\"gas\":\"526\",\"opcode\":\"CF15\",\"stack\":\"b b' - b''\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_builder_as_ref_rev\",\"line\":484,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STBREFR_ALT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b3\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF16\",\"tlb\":\"#CF16\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Equivalent to <code>SWAP</code> <code>STSLICE</code>.</p>\\n\",\"fift\":\"STSLICER\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF16\",\"stack\":\"b s - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_slice_rev\",\"line\":530,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STSLICER\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF17\",\"tlb\":\"#CF17\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Concatenates two builders.\\nEquivalent to <code>SWAP</code> <code>STB</code>.</p>\\n\",\"fift\":\"STBR\\nBCONCAT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF17\",\"stack\":\"b b' - b''\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_builder_rev\",\"line\":576,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STBR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b3\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF18\",\"tlb\":\"#CF18\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Quiet version of <code>STREF</code>.</p>\\n\",\"fift\":\"STREFQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF18\",\"stack\":\"c b - c b -1 or b' 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_ref\",\"line\":415,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STREFQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":0},{\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF19\",\"tlb\":\"#CF19\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Quiet version of <code>STBREF</code>.</p>\\n\",\"fift\":\"STBREFQ\",\"fift_examples\":[],\"gas\":\"526\",\"opcode\":\"CF19\",\"stack\":\"b' b - b' b -1 or b'' 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_builder_as_ref\",\"line\":461,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STBREFQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"b3\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":0},{\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF1A\",\"tlb\":\"#CF1A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Quiet version of <code>STSLICE</code>.</p>\\n\",\"fift\":\"STSLICEQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF1A\",\"stack\":\"s b - s b -1 or b' 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_slice\",\"line\":507,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STSLICEQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":0},{\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF1B\",\"tlb\":\"#CF1B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Quiet version of <code>STB</code>.</p>\\n\",\"fift\":\"STBQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF1B\",\"stack\":\"b' b - b' b -1 or b'' 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_builder\",\"line\":553,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STBQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"b3\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":0},{\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF1C\",\"tlb\":\"#CF1C\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Quiet version of <code>STREFR</code>.</p>\\n\",\"fift\":\"STREFRQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF1C\",\"stack\":\"b c - b c -1 or b' 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_ref_rev\",\"line\":438,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STREFRQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":0},{\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF1D\",\"tlb\":\"#CF1D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Quiet version of <code>STBREFR</code>.</p>\\n\",\"fift\":\"STBREFRQ\",\"fift_examples\":[],\"gas\":\"526\",\"opcode\":\"CF1D\",\"stack\":\"b b' - b b' -1 or b'' 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_builder_as_ref_rev\",\"line\":484,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STBREFRQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"b3\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":0},{\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF1E\",\"tlb\":\"#CF1E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Quiet version of <code>STSLICER</code>.</p>\\n\",\"fift\":\"STSLICERQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF1E\",\"stack\":\"b s - b s -1 or b'' 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_slice_rev\",\"line\":530,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STSLICERQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"b3\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":0},{\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF1F\",\"tlb\":\"#CF1F\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Quiet version of <code>STBR</code>.</p>\\n\",\"fift\":\"STBRQ\\nBCONCATQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF1F\",\"stack\":\"b b' - b b' -1 or b'' 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_builder_rev\",\"line\":576,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STBRQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"b3\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":0},{\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"name\":\"c\",\"type\":\"ref\"}],\"prefix\":\"CF20\",\"tlb\":\"#CF20 c:^Cell\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Equivalent to <code>PUSHREF</code> <code>STREFR</code>.</p>\\n\",\"fift\":\"[ref] STREFCONST\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF20\",\"stack\":\"b - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_const_ref\",\"line\":647,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STREFCONST\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"name\":\"c1\",\"type\":\"ref\"},{\"display_hints\":[],\"name\":\"c2\",\"type\":\"ref\"}],\"prefix\":\"CF21\",\"tlb\":\"#CF21 c1:^Cell c2:^Cell\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Equivalent to <code>STREFCONST</code> <code>STREFCONST</code>.</p>\\n\",\"fift\":\"[ref] [ref] STREF2CONST\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF21\",\"stack\":\"b - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_const_ref\",\"line\":647,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STREF2CONST\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF23\",\"tlb\":\"#CF23\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>If <code>x!=0</code>, creates a <em>special</em> or <em>exotic</em> cell from <em>Builder</em> <code>b</code>.\\nThe type of the exotic cell must be stored in the first 8 bits of <code>b</code>.\\nIf <code>x=0</code>, it is equivalent to <code>ENDC</code>. Otherwise some validity checks on the data and references of <code>b</code> are performed before creating the exotic cell.</p>\\n\",\"fift\":\"ENDXC\",\"fift_examples\":[],\"gas\":\"526\",\"opcode\":\"CF23\",\"stack\":\"b x - c\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_builder_to_special_cell\",\"line\":349,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"ENDXC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF28\",\"tlb\":\"#CF28\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Stores a little-endian signed 32-bit integer.</p>\\n\",\"fift\":\"STILE4\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF28\",\"stack\":\"x b - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_fixed\",\"line\":622,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STILE4\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF29\",\"tlb\":\"#CF29\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Stores a little-endian unsigned 32-bit integer.</p>\\n\",\"fift\":\"STULE4\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF29\",\"stack\":\"x b - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_fixed\",\"line\":622,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STULE4\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF2A\",\"tlb\":\"#CF2A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Stores a little-endian signed 64-bit integer.</p>\\n\",\"fift\":\"STILE8\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF2A\",\"stack\":\"x b - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_fixed\",\"line\":622,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STILE8\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF2B\",\"tlb\":\"#CF2B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Stores a little-endian unsigned 64-bit integer.</p>\\n\",\"fift\":\"STULE8\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF2B\",\"stack\":\"x b - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_int_fixed\",\"line\":622,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STULE8\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF30\",\"tlb\":\"#CF30\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Returns the depth of <em>Builder</em> <code>b</code>. If no cell references are stored in <code>b</code>, then <code>x=0</code>; otherwise <code>x</code> is one plus the maximum of depths of cells referred to from <code>b</code>.</p>\\n\",\"fift\":\"BDEPTH\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF30\",\"stack\":\"b - x\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_int_builder_func\",\"line\":704,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"BDEPTH\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF31\",\"tlb\":\"#CF31\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Returns the number of data bits already stored in <em>Builder</em> <code>b</code>.</p>\\n\",\"fift\":\"BBITS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF31\",\"stack\":\"b - x\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_int_builder_func\",\"line\":704,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"BBITS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF32\",\"tlb\":\"#CF32\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Returns the number of cell references already stored in <code>b</code>.</p>\\n\",\"fift\":\"BREFS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF32\",\"stack\":\"b - y\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_int_builder_func\",\"line\":704,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"BREFS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF33\",\"tlb\":\"#CF33\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Returns the numbers of both data bits and cell references in <code>b</code>.</p>\\n\",\"fift\":\"BBITREFS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF33\",\"stack\":\"b - x y\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_2int_builder_func\",\"line\":712,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"BBITREFS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF35\",\"tlb\":\"#CF35\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Returns the number of data bits that can still be stored in <code>b</code>.</p>\\n\",\"fift\":\"BREMBITS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF35\",\"stack\":\"b - x'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_int_builder_func\",\"line\":704,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"BREMBITS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF36\",\"tlb\":\"#CF36\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Returns the number of references that can still be stored in <code>b</code>.</p>\\n\",\"fift\":\"BREMREFS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF36\",\"stack\":\"b - y'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_int_builder_func\",\"line\":704,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"BREMREFS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"y2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF37\",\"tlb\":\"#CF37\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Returns the numbers of both data bits and references that can still be stored in <code>b</code>.</p>\\n\",\"fift\":\"BREMBITREFS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF37\",\"stack\":\"b - x' y'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_2int_builder_func\",\"line\":712,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"BREMBITREFS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"CF38\",\"tlb\":\"#CF38 cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Checks whether <code>cc+1</code> bits can be stored into <code>b</code>, where <code>0 &lt;= cc &lt;= 255</code>.</p>\\n\",\"fift\":\"[cc+1] BCHKBITS#\",\"fift_examples\":[],\"gas\":\"34/84\",\"opcode\":\"CF38cc\",\"stack\":\"b -\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_builder_chk_bits_refs\",\"line\":737,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"BCHKBITS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF39\",\"tlb\":\"#CF39\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Checks whether <code>x</code> bits can be stored into <code>b</code>, <code>0 &lt;= x &lt;= 1023</code>. If there is no space for <code>x</code> more bits in <code>b</code>, or if <code>x</code> is not within the range <code>0...1023</code>, throws an exception.</p>\\n\",\"fift\":\"BCHKBITS\",\"fift_examples\":[],\"gas\":\"26/76\",\"opcode\":\"CF39\",\"stack\":\"b x - \"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_builder_chk_bits_refs\",\"line\":737,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"BCHKBITS_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF3A\",\"tlb\":\"#CF3A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Checks whether <code>y</code> references can be stored into <code>b</code>, <code>0 &lt;= y &lt;= 7</code>.</p>\\n\",\"fift\":\"BCHKREFS\",\"fift_examples\":[],\"gas\":\"26/76\",\"opcode\":\"CF3A\",\"stack\":\"b y - \"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_builder_chk_bits_refs\",\"line\":737,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"BCHKREFS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF3B\",\"tlb\":\"#CF3B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Checks whether <code>x</code> bits and <code>y</code> references can be stored into <code>b</code>, <code>0 &lt;= x &lt;= 1023</code>, <code>0 &lt;= y &lt;= 7</code>.</p>\\n\",\"fift\":\"BCHKBITREFS\",\"fift_examples\":[],\"gas\":\"26/76\",\"opcode\":\"CF3B\",\"stack\":\"b x y - \"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_builder_chk_bits_refs\",\"line\":737,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"BCHKBITREFS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"CF3C\",\"tlb\":\"#CF3C cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Checks whether <code>cc+1</code> bits can be stored into <code>b</code>, where <code>0 &lt;= cc &lt;= 255</code>.</p>\\n\",\"fift\":\"[cc+1] BCHKBITSQ#\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"CF3Ccc\",\"stack\":\"b - ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_builder_chk_bits_refs\",\"line\":737,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"BCHKBITSQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF3D\",\"tlb\":\"#CF3D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Checks whether <code>x</code> bits can be stored into <code>b</code>, <code>0 &lt;= x &lt;= 1023</code>.</p>\\n\",\"fift\":\"BCHKBITSQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF3D\",\"stack\":\"b x - ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_builder_chk_bits_refs\",\"line\":737,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"BCHKBITSQ_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF3E\",\"tlb\":\"#CF3E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Checks whether <code>y</code> references can be stored into <code>b</code>, <code>0 &lt;= y &lt;= 7</code>.</p>\\n\",\"fift\":\"BCHKREFSQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF3E\",\"stack\":\"b y - ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_builder_chk_bits_refs\",\"line\":737,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"BCHKREFSQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF3F\",\"tlb\":\"#CF3F\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Checks whether <code>x</code> bits and <code>y</code> references can be stored into <code>b</code>, <code>0 &lt;= x &lt;= 1023</code>, <code>0 &lt;= y &lt;= 7</code>.</p>\\n\",\"fift\":\"BCHKBITREFSQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF3F\",\"stack\":\"b x y - ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_builder_chk_bits_refs\",\"line\":737,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"BCHKBITREFSQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF40\",\"tlb\":\"#CF40\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Stores <code>n</code> binary zeroes into <em>Builder</em> <code>b</code>.</p>\\n\",\"fift\":\"STZEROES\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF40\",\"stack\":\"b n - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_same\",\"line\":752,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STZEROES\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF41\",\"tlb\":\"#CF41\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Stores <code>n</code> binary ones into <em>Builder</em> <code>b</code>.</p>\\n\",\"fift\":\"STONES\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF41\",\"stack\":\"b n - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_same\",\"line\":752,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STONES\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF42\",\"tlb\":\"#CF42\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Stores <code>n</code> binary <code>x</code>es (<code>0 &lt;= x &lt;= 1</code>) into <em>Builder</em> <code>b</code>.</p>\\n\",\"fift\":\"STSAME\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF42\",\"stack\":\"b n x - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_same\",\"line\":752,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STSAME\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"CF50\",\"tlb\":\"#CF50\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Same as <code>ENDC CTOS</code>, but without gas cost for cell creation and loading.</p>\\n\",\"fift\":\"BTOS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"CF50\",\"stack\":\"b - s\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_builder_to_slice\",\"line\":767,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/f58297f1b668c7b49e8b30b65062951ca7c18acc/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"BTOS\",\"since_version\":12,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[{\"bits_length_var_size\":3,\"bits_padding\":2,\"completion_tag\":true,\"display_hints\":[],\"max_bits\":57,\"max_refs\":3,\"min_bits\":0,\"min_refs\":0,\"name\":\"s\",\"refs_add\":0,\"refs_length_var_size\":2,\"type\":\"subslice\"}],\"prefix\":\"CFC_\",\"tlb\":\"#CFC_ x:(## 2) y:(## 3) c:(x * ^Cell) sss:((8 * y + 2) * Bit)\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_build\",\"description\":\"<p>Stores a constant subslice <code>sss</code>.\\n<em>Details:</em> <code>sss</code> consists of <code>0 &lt;= x &lt;= 3</code> references and up to <code>8y+2</code> data bits, with <code>0 &lt;= y &lt;= 7</code>. Completion bit is assumed.\\nNote that the assembler can replace <code>STSLICECONST</code> with <code>PUSHSLICE</code> <code>STSLICER</code> if the slice is too big.</p>\\n\",\"fift\":\"[slice] STSLICECONST\",\"fift_examples\":[],\"gas\":\"24\",\"opcode\":\"CFC_xysss\",\"stack\":\"b - b'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_store_const_slice\",\"line\":776,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"STSLICECONST\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D0\",\"tlb\":\"#D0\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Converts a <em>Cell</em> into a <em>Slice</em>. Notice that <code>c</code> must be either an ordinary cell, or an exotic cell which is automatically <em>loaded</em> to yield an ordinary cell <code>c'</code>, converted into a <em>Slice</em> afterwards.</p>\\n\",\"fift\":\"CTOS\",\"fift_examples\":[],\"gas\":\"118/43\",\"opcode\":\"D0\",\"stack\":\"c - s\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_cell_to_slice\",\"line\":883,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"CTOS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D1\",\"tlb\":\"#D1\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Removes a <em>Slice</em> <code>s</code> from the stack, and throws an exception if it is not empty.</p>\\n\",\"fift\":\"ENDS\",\"fift_examples\":[],\"gas\":\"18/68\",\"opcode\":\"D1\",\"stack\":\"s - \"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_chk_empty\",\"line\":946,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"ENDS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"D2\",\"tlb\":\"#D2 cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Loads (i.e., parses) a signed <code>cc+1</code>-bit integer <code>x</code> from <em>Slice</em> <code>s</code>, and returns the remainder of <code>s</code> as <code>s'</code>.</p>\\n\",\"fift\":\"[cc+1] LDI\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D2cc\",\"stack\":\"s - x s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_int_fixed\",\"line\":981,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDI\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"D3\",\"tlb\":\"#D3 cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Loads an unsigned <code>cc+1</code>-bit integer <code>x</code> from <em>Slice</em> <code>s</code>.</p>\\n\",\"fift\":\"[cc+1] LDU\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D3cc\",\"stack\":\"s - x s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_int_fixed\",\"line\":981,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDU\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D4\",\"tlb\":\"#D4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Loads a cell reference <code>c</code> from <code>s</code>.</p>\\n\",\"fift\":\"LDREF\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"D4\",\"stack\":\"s - c s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_ref\",\"line\":1013,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D5\",\"tlb\":\"#D5\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Equivalent to <code>LDREF</code> <code>SWAP</code> <code>CTOS</code>.</p>\\n\",\"fift\":\"LDREFRTOS\",\"fift_examples\":[],\"gas\":\"118/43\",\"opcode\":\"D5\",\"stack\":\"s - s' s''\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_ref_rev_to_slice\",\"line\":1036,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDREFRTOS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"D6\",\"tlb\":\"#D6 cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Cuts the next <code>cc+1</code> bits of <code>s</code> into a separate <em>Slice</em> <code>s''</code>.</p>\\n\",\"fift\":\"[cc+1] LDSLICE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D6cc\",\"stack\":\"s - s'' s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_slice\",\"line\":1137,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDSLICE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D700\",\"tlb\":\"#D700\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Loads a signed <code>l</code>-bit (<code>0 &lt;= l &lt;= 257</code>) integer <code>x</code> from <em>Slice</em> <code>s</code>, and returns the remainder of <code>s</code> as <code>s'</code>.</p>\\n\",\"fift\":\"LDIX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D700\",\"stack\":\"s l - x s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_int_var\",\"line\":1090,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDIX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D701\",\"tlb\":\"#D701\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Loads an unsigned <code>l</code>-bit integer <code>x</code> from (the first <code>l</code> bits of) <code>s</code>, with <code>0 &lt;= l &lt;= 256</code>.</p>\\n\",\"fift\":\"LDUX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D701\",\"stack\":\"s l - x s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_int_var\",\"line\":1090,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDUX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D702\",\"tlb\":\"#D702\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Preloads a signed <code>l</code>-bit integer from <em>Slice</em> <code>s</code>, for <code>0 &lt;= l &lt;= 257</code>.</p>\\n\",\"fift\":\"PLDIX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D702\",\"stack\":\"s l - x\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_preload_ref_fixed\",\"line\":988,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDIX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D703\",\"tlb\":\"#D703\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Preloads an unsigned <code>l</code>-bit integer from <code>s</code>, for <code>0 &lt;= l &lt;= 256</code>.</p>\\n\",\"fift\":\"PLDUX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D703\",\"stack\":\"s l - x\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_preload_ref_fixed\",\"line\":988,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDUX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D704\",\"tlb\":\"#D704\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Quiet version of <code>LDIX</code>: loads a signed <code>l</code>-bit integer from <code>s</code> similarly to <code>LDIX</code>, but returns a success flag, equal to <code>-1</code> on success or to <code>0</code> on failure (if <code>s</code> does not have <code>l</code> bits), instead of throwing a cell underflow exception.</p>\\n\",\"fift\":\"LDIXQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D704\",\"stack\":\"s l - x s' -1 or s 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_int_var\",\"line\":1090,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDIXQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D705\",\"tlb\":\"#D705\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Quiet version of <code>LDUX</code>.</p>\\n\",\"fift\":\"LDUXQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D705\",\"stack\":\"s l - x s' -1 or s 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_int_var\",\"line\":1090,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDUXQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D706\",\"tlb\":\"#D706\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Quiet version of <code>PLDIX</code>.</p>\\n\",\"fift\":\"PLDIXQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D706\",\"stack\":\"s l - x -1 or 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_preload_ref_fixed\",\"line\":988,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDIXQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D707\",\"tlb\":\"#D707\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Quiet version of <code>PLDUX</code>.</p>\\n\",\"fift\":\"PLDUXQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D707\",\"stack\":\"s l - x -1 or 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_preload_ref_fixed\",\"line\":988,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDUXQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"D708\",\"tlb\":\"#D708 cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>A longer encoding for <code>LDI</code>.</p>\\n\",\"fift\":\"[cc+1] LDI_l\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"D708cc\",\"stack\":\"s - x s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_int_fixed\",\"line\":981,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDI_ALT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"D709\",\"tlb\":\"#D709 cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>A longer encoding for <code>LDU</code>.</p>\\n\",\"fift\":\"[cc+1] LDU_l\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"D709cc\",\"stack\":\"s - x s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_int_fixed\",\"line\":981,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDU_ALT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"D70A\",\"tlb\":\"#D70A cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Preloads a signed <code>cc+1</code>-bit integer from <em>Slice</em> <code>s</code>.</p>\\n\",\"fift\":\"[cc+1] PLDI\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"D70Acc\",\"stack\":\"s - x\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_preload_ref_fixed\",\"line\":988,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDI\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"D70B\",\"tlb\":\"#D70B cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Preloads an unsigned <code>cc+1</code>-bit integer from <code>s</code>.</p>\\n\",\"fift\":\"[cc+1] PLDU\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"D70Bcc\",\"stack\":\"s - x\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_preload_ref_fixed\",\"line\":988,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDU\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"D70C\",\"tlb\":\"#D70C cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>A quiet version of <code>LDI</code>.</p>\\n\",\"fift\":\"[cc+1] LDIQ\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"D70Ccc\",\"stack\":\"s - x s' -1 or s 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_int_fixed\",\"line\":981,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDIQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"D70D\",\"tlb\":\"#D70D cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>A quiet version of <code>LDU</code>.</p>\\n\",\"fift\":\"[cc+1] LDUQ\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"D70Dcc\",\"stack\":\"s - x s' -1 or s 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_int_fixed\",\"line\":981,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDUQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"D70E\",\"tlb\":\"#D70E cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>A quiet version of <code>PLDI</code>.</p>\\n\",\"fift\":\"[cc+1] PLDIQ\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"D70Ecc\",\"stack\":\"s - x -1 or 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_preload_ref_fixed\",\"line\":988,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDIQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"D70F\",\"tlb\":\"#D70F cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>A quiet version of <code>PLDU</code>.</p>\\n\",\"fift\":\"[cc+1] PLDUQ\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"D70Fcc\",\"stack\":\"s - x -1 or 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_preload_ref_fixed\",\"line\":988,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDUQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"plduz\"}],\"max_value\":7,\"min_value\":0,\"name\":\"c\",\"size\":3,\"type\":\"uint\"}],\"prefix\":\"D714_\",\"tlb\":\"#D714_ c:uint3\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Preloads the first <code>32(c+1)</code> bits of <em>Slice</em> <code>s</code> into an unsigned integer <code>x</code>, for <code>0 &lt;= c &lt;= 7</code>. If <code>s</code> is shorter than necessary, missing bits are assumed to be zero. This operation is intended to be used along with <code>IFBITJMP</code> and similar instructions.</p>\\n\",\"fift\":\"[32(c+1)] PLDUZ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D714_c\",\"stack\":\"s - s x\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_preload_ref_fixed\",\"line\":988,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDUZ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D718\",\"tlb\":\"#D718\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Loads the first <code>0 &lt;= l &lt;= 1023</code> bits from <em>Slice</em> <code>s</code> into a separate <em>Slice</em> <code>s''</code>, returning the remainder of <code>s</code> as <code>s'</code>.</p>\\n\",\"fift\":\"LDSLICEX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D718\",\"stack\":\"s l - s'' s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_slice\",\"line\":1137,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDSLICEX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D719\",\"tlb\":\"#D719\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns the first <code>0 &lt;= l &lt;= 1023</code> bits of <code>s</code> as <code>s''</code>.</p>\\n\",\"fift\":\"PLDSLICEX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D719\",\"stack\":\"s l - s''\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_slice\",\"line\":1137,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDSLICEX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D71A\",\"tlb\":\"#D71A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>A quiet version of <code>LDSLICEX</code>.</p>\\n\",\"fift\":\"LDSLICEXQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D71A\",\"stack\":\"s l - s'' s' -1 or s 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_slice\",\"line\":1137,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDSLICEXQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D71B\",\"tlb\":\"#D71B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>A quiet version of <code>LDSLICEXQ</code>.</p>\\n\",\"fift\":\"PLDSLICEXQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D71B\",\"stack\":\"s l - s' -1 or 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_slice\",\"line\":1137,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDSLICEXQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"D71C\",\"tlb\":\"#D71C cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>A longer encoding for <code>LDSLICE</code>.</p>\\n\",\"fift\":\"[cc+1] LDSLICE_l\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"D71Ccc\",\"stack\":\"s - s'' s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_slice\",\"line\":1137,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDSLICE_ALT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"D71D\",\"tlb\":\"#D71D cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns the first <code>0 &lt; cc+1 &lt;= 256</code> bits of <code>s</code> as <code>s''</code>.</p>\\n\",\"fift\":\"[cc+1] PLDSLICE\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"D71Dcc\",\"stack\":\"s - s''\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_slice\",\"line\":1137,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDSLICE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"D71E\",\"tlb\":\"#D71E cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>A quiet version of <code>LDSLICE</code>.</p>\\n\",\"fift\":\"[cc+1] LDSLICEQ\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"D71Ecc\",\"stack\":\"s - s'' s' -1 or s 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_slice\",\"line\":1137,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDSLICEQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":1}],\"max_value\":255,\"min_value\":0,\"name\":\"c\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"D71F\",\"tlb\":\"#D71F cc:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>A quiet version of <code>PLDSLICE</code>.</p>\\n\",\"fift\":\"[cc+1] PLDSLICEQ\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"D71Fcc\",\"stack\":\"s - s'' -1 or 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_slice\",\"line\":1137,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDSLICEQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D720\",\"tlb\":\"#D720\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns the first <code>0 &lt;= l &lt;= 1023</code> bits of <code>s</code>. It is equivalent to <code>PLDSLICEX</code>.</p>\\n\",\"fift\":\"SDCUTFIRST\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D720\",\"stack\":\"s l - s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_op_args\",\"line\":1167,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDCUTFIRST\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D721\",\"tlb\":\"#D721\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns all but the first <code>0 &lt;= l &lt;= 1023</code> bits of <code>s</code>. It is equivalent to <code>LDSLICEX</code> <code>NIP</code>.</p>\\n\",\"fift\":\"SDSKIPFIRST\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D721\",\"stack\":\"s l - s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_op_args\",\"line\":1167,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDSKIPFIRST\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D722\",\"tlb\":\"#D722\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns the last <code>0 &lt;= l &lt;= 1023</code> bits of <code>s</code>.</p>\\n\",\"fift\":\"SDCUTLAST\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D722\",\"stack\":\"s l - s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_op_args\",\"line\":1167,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDCUTLAST\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D723\",\"tlb\":\"#D723\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns all but the last <code>0 &lt;= l &lt;= 1023</code> bits of <code>s</code>.</p>\\n\",\"fift\":\"SDSKIPLAST\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D723\",\"stack\":\"s l - s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_op_args\",\"line\":1167,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDSKIPLAST\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D724\",\"tlb\":\"#D724\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns <code>0 &lt;= l' &lt;= 1023</code> bits of <code>s</code> starting from offset <code>0 &lt;= l &lt;= 1023</code>, thus extracting a bit substring out of the data of <code>s</code>.</p>\\n\",\"fift\":\"SDSUBSTR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D724\",\"stack\":\"s l l' - s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_op_args2\",\"line\":1181,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDSUBSTR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"l2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D726\",\"tlb\":\"#D726\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Checks whether <code>s</code> begins with (the data bits of) <code>s'</code>, and removes <code>s'</code> from <code>s</code> on success. On failure throws a cell deserialization exception. Primitive <code>SDPFXREV</code> can be considered a quiet version of <code>SDBEGINSX</code>.</p>\\n\",\"fift\":\"SDBEGINSX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D726\",\"stack\":\"s s' - s''\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_begins_with\",\"line\":1215,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDBEGINSX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D727\",\"tlb\":\"#D727\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>A quiet version of <code>SDBEGINSX</code>.</p>\\n\",\"fift\":\"SDBEGINSXQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D727\",\"stack\":\"s s' - s'' -1 or s 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_begins_with\",\"line\":1215,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDBEGINSXQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"bits_length_var_size\":7,\"bits_padding\":3,\"completion_tag\":true,\"display_hints\":[],\"max_bits\":1018,\"max_refs\":0,\"min_bits\":0,\"min_refs\":0,\"name\":\"s\",\"type\":\"subslice\"}],\"prefix\":\"D72A_\",\"tlb\":\"#D72A_ x:(## 7) sss:((8 * x + 3) * Bit)\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Checks whether <code>s</code> begins with constant bitstring <code>sss</code> of length <code>8x+3</code> (with continuation bit assumed), where <code>0 &lt;= x &lt;= 127</code>, and removes <code>sss</code> from <code>s</code> on success.</p>\\n\",\"fift\":\"[slice] SDBEGINS\",\"fift_examples\":[],\"gas\":\"31\",\"opcode\":\"D72A_xsss\",\"stack\":\"s - s''\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_begins_with_const\",\"line\":1222,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDBEGINS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[{\"bits_length_var_size\":7,\"bits_padding\":3,\"completion_tag\":true,\"display_hints\":[],\"max_bits\":1018,\"max_refs\":0,\"min_bits\":0,\"min_refs\":0,\"name\":\"s\",\"type\":\"subslice\"}],\"prefix\":\"D72E_\",\"tlb\":\"#D72E_ x:(## 7) sss:((8 * x + 3) * Bit)\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>A quiet version of <code>SDBEGINS</code>.</p>\\n\",\"fift\":\"[slice] SDBEGINSQ\",\"fift_examples\":[],\"gas\":\"31\",\"opcode\":\"D72E_xsss\",\"stack\":\"s - s'' -1 or s 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_begins_with_const\",\"line\":1222,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDBEGINSQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D730\",\"tlb\":\"#D730\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns the first <code>0 &lt;= l &lt;= 1023</code> bits and first <code>0 &lt;= r &lt;= 4</code> references of <code>s</code>.</p>\\n\",\"fift\":\"SCUTFIRST\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D730\",\"stack\":\"s l r - s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_op_args2\",\"line\":1181,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SCUTFIRST\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D731\",\"tlb\":\"#D731\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns all but the first <code>l</code> bits of <code>s</code> and <code>r</code> references of <code>s</code>.</p>\\n\",\"fift\":\"SSKIPFIRST\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D731\",\"stack\":\"s l r - s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_op_args2\",\"line\":1181,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SSKIPFIRST\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D732\",\"tlb\":\"#D732\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns the last <code>0 &lt;= l &lt;= 1023</code> data bits and last <code>0 &lt;= r &lt;= 4</code> references of <code>s</code>.</p>\\n\",\"fift\":\"SCUTLAST\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D732\",\"stack\":\"s l r - s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_op_args2\",\"line\":1181,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SCUTLAST\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D733\",\"tlb\":\"#D733\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns all but the last <code>l</code> bits of <code>s</code> and <code>r</code> references of <code>s</code>.</p>\\n\",\"fift\":\"SSKIPLAST\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D733\",\"stack\":\"s l r - s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_op_args2\",\"line\":1181,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SSKIPLAST\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D734\",\"tlb\":\"#D734\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns <code>0 &lt;= l' &lt;= 1023</code> bits and <code>0 &lt;= r' &lt;= 4</code> references from <em>Slice</em> <code>s</code>, after skipping the first <code>0 &lt;= l &lt;= 1023</code> bits and first <code>0 &lt;= r &lt;= 4</code> references.</p>\\n\",\"fift\":\"SUBSLICE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D734\",\"stack\":\"s l r l' r' - s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_subslice\",\"line\":1246,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SUBSLICE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"l2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D736\",\"tlb\":\"#D736\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Splits the first <code>0 &lt;= l &lt;= 1023</code> data bits and first <code>0 &lt;= r &lt;= 4</code> references from <code>s</code> into <code>s'</code>, returning the remainder of <code>s</code> as <code>s''</code>.</p>\\n\",\"fift\":\"SPLIT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D736\",\"stack\":\"s l r - s' s''\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_split\",\"line\":1260,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SPLIT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D737\",\"tlb\":\"#D737\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>A quiet version of <code>SPLIT</code>.</p>\\n\",\"fift\":\"SPLITQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D737\",\"stack\":\"s l r - s' s'' -1 or s 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_split\",\"line\":1260,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SPLITQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D739\",\"tlb\":\"#D739\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Transforms an ordinary or exotic cell into a <em>Slice</em>, as if it were an ordinary cell. A flag is returned indicating whether <code>c</code> is exotic. If that be the case, its type can later be deserialized from the first eight bits of <code>s</code>.</p>\\n\",\"fift\":\"XCTOS\",\"fift_examples\":[],\"gas\":\"126/51\",\"opcode\":\"D739\",\"stack\":\"c - s ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_cell_to_slice_maybe_special\",\"line\":891,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"XCTOS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"flag\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D73A\",\"tlb\":\"#D73A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Loads an exotic cell <code>c</code> and returns an ordinary cell <code>c'</code>. If <code>c</code> is already ordinary, does nothing. If <code>c</code> cannot be loaded, throws an exception.</p>\\n\",\"fift\":\"XLOAD\",\"fift_examples\":[],\"gas\":\"126/51\",\"opcode\":\"D73A\",\"stack\":\"c - c'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_special_cell\",\"line\":901,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"XLOAD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D73B\",\"tlb\":\"#D73B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Loads an exotic cell <code>c</code> and returns an ordinary cell <code>c'</code>. If <code>c</code> is already ordinary, does nothing. If <code>c</code> cannot be loaded, returns 0.</p>\\n\",\"fift\":\"XLOADQ\",\"fift_examples\":[],\"gas\":\"126/51\",\"opcode\":\"D73B\",\"stack\":\"c - c' -1 or c 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_special_cell\",\"line\":901,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"XLOADQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}],\"value\":0},{\"stack\":[{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D741\",\"tlb\":\"#D741\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Checks whether there are at least <code>l</code> data bits in <em>Slice</em> <code>s</code>. If this is not the case, throws a cell deserialisation (i.e., cell underflow) exception.</p>\\n\",\"fift\":\"SCHKBITS\",\"fift_examples\":[],\"gas\":\"26/76\",\"opcode\":\"D741\",\"stack\":\"s l - \"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_chk_op_args\",\"line\":1285,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SCHKBITS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D742\",\"tlb\":\"#D742\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Checks whether there are at least <code>r</code> references in <em>Slice</em> <code>s</code>.</p>\\n\",\"fift\":\"SCHKREFS\",\"fift_examples\":[],\"gas\":\"26/76\",\"opcode\":\"D742\",\"stack\":\"s r - \"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_chk_op_args\",\"line\":1285,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SCHKREFS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D743\",\"tlb\":\"#D743\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Checks whether there are at least <code>l</code> data bits and <code>r</code> references in <em>Slice</em> <code>s</code>.</p>\\n\",\"fift\":\"SCHKBITREFS\",\"fift_examples\":[],\"gas\":\"26/76\",\"opcode\":\"D743\",\"stack\":\"s l r - \"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_chk_op_args2\",\"line\":1301,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SCHKBITREFS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D745\",\"tlb\":\"#D745\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Checks whether there are at least <code>l</code> data bits in <em>Slice</em> <code>s</code>.</p>\\n\",\"fift\":\"SCHKBITSQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D745\",\"stack\":\"s l - ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_chk_op_args\",\"line\":1285,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SCHKBITSQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D746\",\"tlb\":\"#D746\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Checks whether there are at least <code>r</code> references in <em>Slice</em> <code>s</code>.</p>\\n\",\"fift\":\"SCHKREFSQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D746\",\"stack\":\"s r - ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_chk_op_args\",\"line\":1285,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SCHKREFSQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D747\",\"tlb\":\"#D747\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Checks whether there are at least <code>l</code> data bits and <code>r</code> references in <em>Slice</em> <code>s</code>.</p>\\n\",\"fift\":\"SCHKBITREFSQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D747\",\"stack\":\"s l r - ?\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_chk_op_args2\",\"line\":1301,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SCHKBITREFSQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D748\",\"tlb\":\"#D748\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns the <code>n</code>-th cell reference of <em>Slice</em> <code>s</code> for <code>0 &lt;= n &lt;= 3</code>.</p>\\n\",\"fift\":\"PLDREFVAR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D748\",\"stack\":\"s n - c\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_preload_ref\",\"line\":1000,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDREFVAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D749\",\"tlb\":\"#D749\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns the number of data bits in <em>Slice</em> <code>s</code>.</p>\\n\",\"fift\":\"SBITS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D749\",\"stack\":\"s - l\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_bits_refs\",\"line\":1318,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SBITS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D74A\",\"tlb\":\"#D74A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns the number of references in <em>Slice</em> <code>s</code>.</p>\\n\",\"fift\":\"SREFS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D74A\",\"stack\":\"s - r\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_bits_refs\",\"line\":1318,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SREFS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D74B\",\"tlb\":\"#D74B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns both the number of data bits and the number of references in <code>s</code>.</p>\\n\",\"fift\":\"SBITREFS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D74B\",\"stack\":\"s - l r\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_bits_refs\",\"line\":1318,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SBITREFS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":3,\"min_value\":0,\"name\":\"n\",\"size\":2,\"type\":\"uint\"}],\"prefix\":\"D74E_\",\"tlb\":\"#D74E_ n:uint2\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns the <code>n</code>-th cell reference of <em>Slice</em> <code>s</code>, where <code>0 &lt;= n &lt;= 3</code>.</p>\\n\",\"fift\":\"[n] PLDREFIDX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D74E_n\",\"stack\":\"s - c\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_preload_ref_fixed\",\"line\":988,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDREFIDX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D750\",\"tlb\":\"#D750\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Loads a little-endian signed 32-bit integer.</p>\\n\",\"fift\":\"LDILE4\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D750\",\"stack\":\"s - x s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_int_fixed\",\"line\":981,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDILE4\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D751\",\"tlb\":\"#D751\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Loads a little-endian unsigned 32-bit integer.</p>\\n\",\"fift\":\"LDULE4\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D751\",\"stack\":\"s - x s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_int_fixed\",\"line\":981,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDULE4\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D752\",\"tlb\":\"#D752\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Loads a little-endian signed 64-bit integer.</p>\\n\",\"fift\":\"LDILE8\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D752\",\"stack\":\"s - x s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_int_fixed\",\"line\":981,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDILE8\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D753\",\"tlb\":\"#D753\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Loads a little-endian unsigned 64-bit integer.</p>\\n\",\"fift\":\"LDULE8\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D753\",\"stack\":\"s - x s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_int_fixed\",\"line\":981,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDULE8\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D754\",\"tlb\":\"#D754\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Preloads a little-endian signed 32-bit integer.</p>\\n\",\"fift\":\"PLDILE4\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D754\",\"stack\":\"s - x\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_preload_ref_fixed\",\"line\":988,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDILE4\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D755\",\"tlb\":\"#D755\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Preloads a little-endian unsigned 32-bit integer.</p>\\n\",\"fift\":\"PLDULE4\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D755\",\"stack\":\"s - x\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_preload_ref_fixed\",\"line\":988,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDULE4\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D756\",\"tlb\":\"#D756\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Preloads a little-endian signed 64-bit integer.</p>\\n\",\"fift\":\"PLDILE8\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D756\",\"stack\":\"s - x\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_preload_ref_fixed\",\"line\":988,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDILE8\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D757\",\"tlb\":\"#D757\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Preloads a little-endian unsigned 64-bit integer.</p>\\n\",\"fift\":\"PLDULE8\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D757\",\"stack\":\"s - x\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_preload_ref_fixed\",\"line\":988,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDULE8\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D758\",\"tlb\":\"#D758\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Quietly loads a little-endian signed 32-bit integer.</p>\\n\",\"fift\":\"LDILE4Q\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D758\",\"stack\":\"s - x s' -1 or s 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_int_fixed\",\"line\":981,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDILE4Q\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D759\",\"tlb\":\"#D759\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Quietly loads a little-endian unsigned 32-bit integer.</p>\\n\",\"fift\":\"LDULE4Q\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D759\",\"stack\":\"s - x s' -1 or s 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_int_fixed\",\"line\":981,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDULE4Q\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D75A\",\"tlb\":\"#D75A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Quietly loads a little-endian signed 64-bit integer.</p>\\n\",\"fift\":\"LDILE8Q\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D75A\",\"stack\":\"s - x s' -1 or s 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_int_fixed\",\"line\":981,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDILE8Q\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D75B\",\"tlb\":\"#D75B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Quietly loads a little-endian unsigned 64-bit integer.</p>\\n\",\"fift\":\"LDULE8Q\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D75B\",\"stack\":\"s - x s' -1 or s 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_int_fixed\",\"line\":981,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDULE8Q\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D75C\",\"tlb\":\"#D75C\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Quietly preloads a little-endian signed 32-bit integer.</p>\\n\",\"fift\":\"PLDILE4Q\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D75C\",\"stack\":\"s - x -1 or 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_preload_ref_fixed\",\"line\":988,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDILE4Q\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D75D\",\"tlb\":\"#D75D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Quietly preloads a little-endian unsigned 32-bit integer.</p>\\n\",\"fift\":\"PLDULE4Q\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D75D\",\"stack\":\"s - x -1 or 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_preload_ref_fixed\",\"line\":988,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDULE4Q\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D75E\",\"tlb\":\"#D75E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Quietly preloads a little-endian signed 64-bit integer.</p>\\n\",\"fift\":\"PLDILE8Q\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D75E\",\"stack\":\"s - x -1 or 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_preload_ref_fixed\",\"line\":988,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDILE8Q\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D75F\",\"tlb\":\"#D75F\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Quietly preloads a little-endian unsigned 64-bit integer.</p>\\n\",\"fift\":\"PLDULE8Q\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D75F\",\"stack\":\"s - x -1 or 0\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_preload_ref_fixed\",\"line\":988,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"PLDULE8Q\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D760\",\"tlb\":\"#D760\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns the count <code>n</code> of leading zero bits in <code>s</code>, and removes these bits from <code>s</code>.</p>\\n\",\"fift\":\"LDZEROES\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D760\",\"stack\":\"s - n s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_same\",\"line\":1371,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDZEROES\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D761\",\"tlb\":\"#D761\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns the count <code>n</code> of leading one bits in <code>s</code>, and removes these bits from <code>s</code>.</p>\\n\",\"fift\":\"LDONES\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D761\",\"stack\":\"s - n s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_same\",\"line\":1371,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDONES\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D762\",\"tlb\":\"#D762\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns the count <code>n</code> of leading bits equal to <code>0 &lt;= x &lt;= 1</code> in <code>s</code>, and removes these bits from <code>s</code>.</p>\\n\",\"fift\":\"LDSAME\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D762\",\"stack\":\"s x - n s'\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_load_same\",\"line\":1371,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"LDSAME\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D764\",\"tlb\":\"#D764\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns the depth of <em>Slice</em> <code>s</code>. If <code>s</code> has no references, then <code>x=0</code>; otherwise <code>x</code> is one plus the maximum of depths of cells referred to from <code>s</code>.</p>\\n\",\"fift\":\"SDEPTH\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D764\",\"stack\":\"s - x\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_slice_depth\",\"line\":1396,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"SDEPTH\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D765\",\"tlb\":\"#D765\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns the depth of <em>Cell</em> <code>c</code>. If <code>c</code> has no references, then <code>x=0</code>; otherwise <code>x</code> is one plus the maximum of depths of cells referred to from <code>c</code>. If <code>c</code> is a <em>Null</em> instead of a <em>Cell</em>, returns zero.</p>\\n\",\"fift\":\"CDEPTH\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D765\",\"stack\":\"c - x\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_cell_depth\",\"line\":1388,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"CDEPTH\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D766\",\"tlb\":\"#D766\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns level of the cell.</p>\\n\",\"fift\":\"CLEVEL\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D766\",\"stack\":\"cell - level\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_cell_level\",\"line\":1404,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"CLEVEL\",\"since_version\":6,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"cell\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"level\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D767\",\"tlb\":\"#D767\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns level mask of the cell.</p>\\n\",\"fift\":\"CLEVELMASK\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D767\",\"stack\":\"cell - level_mask\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_cell_level_mask\",\"line\":1412,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"CLEVELMASK\",\"since_version\":6,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"cell\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"level_mask\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":3,\"min_value\":0,\"name\":\"n\",\"size\":2,\"type\":\"uint\"}],\"prefix\":\"D76A_\",\"tlb\":\"#D76A_ i:uint2\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns <code>i</code>th hash of the cell.</p>\\n\",\"fift\":\"[i] CHASHI\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D76A_\",\"stack\":\"cell - hash\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_cell_hash_i\",\"line\":1420,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"CHASHI\",\"since_version\":6,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"cell\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"hash\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":3,\"min_value\":0,\"name\":\"n\",\"size\":2,\"type\":\"uint\"}],\"prefix\":\"D76E_\",\"tlb\":\"#D76E_ i:uint2\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns <code>i</code>th depth of the cell.</p>\\n\",\"fift\":\"[i] CDEPTHI\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D76E_\",\"stack\":\"cell - depth\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_cell_depth_i\",\"line\":1438,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"CDEPTHI\",\"since_version\":6,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"cell\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"depth\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D770\",\"tlb\":\"#D770\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns <code>i</code>th hash of the cell.</p>\\n\",\"fift\":\"CHASHIX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D770\",\"stack\":\"cell i - hash\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_cell_hash_i\",\"line\":1420,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"CHASHIX\",\"since_version\":6,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"cell\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"hash\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D771\",\"tlb\":\"#D771\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cell_parse\",\"description\":\"<p>Returns <code>i</code>th depth of the cell.</p>\\n\",\"fift\":\"CDEPTHIX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"D771\",\"stack\":\"cell i - depth\"},\"implementation\":[{\"file\":\"cellops.cpp\",\"function_name\":\"exec_cell_depth_i\",\"line\":1438,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/cellops.cpp\"}],\"mnemonic\":\"CDEPTHIX\",\"since_version\":6,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"cell\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"depth\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D8\",\"tlb\":\"#D8\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p><em>Calls</em>, or <em>executes</em>, continuation <code>c</code>.</p>\\n\",\"fift\":\"EXECUTE\\nCALLX\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"D8\",\"stack\":\"c - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_execute\",\"line\":33,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"EXECUTE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"D9\",\"tlb\":\"#D9\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p><em>Jumps</em>, or transfers control, to continuation <code>c</code>.\\nThe remainder of the previous current continuation <code>cc</code> is discarded.</p>\\n\",\"fift\":\"JMPX\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"D9\",\"stack\":\"c - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_jmpx\",\"line\":53,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"JMPX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"p\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"r\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"DA\",\"tlb\":\"#DA p:uint4 r:uint4\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p><em>Calls</em> continuation <code>c</code> with <code>p</code> parameters and expecting <code>r</code> return values\\n<code>0 &lt;= p &lt;= 15</code>, <code>0 &lt;= r &lt;= 15</code></p>\\n\",\"fift\":\"[p] [r] CALLXARGS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"DApr\",\"stack\":\"c - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_callx_args\",\"line\":39,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"CALLXARGS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"arg\",\"type\":\"simple\"}],\"length_var\":\"p\",\"name\":\"args\",\"type\":\"array\"},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"p\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"DB0\",\"tlb\":\"#DB0 p:uint4\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p><em>Calls</em> continuation <code>c</code> with <code>0 &lt;= p &lt;= 15</code> parameters, expecting an arbitrary number of return values.</p>\\n\",\"fift\":\"[p] -1 CALLXARGS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"DB0p\",\"stack\":\"c - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_callx_args\",\"line\":39,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"CALLXARGS_VAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"arg\",\"type\":\"simple\"}],\"length_var\":\"p\",\"name\":\"args\",\"type\":\"array\"},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"p\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"DB1\",\"tlb\":\"#DB1 p:uint4\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p><em>Jumps</em> to continuation <code>c</code>, passing only the top <code>0 &lt;= p &lt;= 15</code> values from the current stack to it (the remainder of the current stack is discarded).</p>\\n\",\"fift\":\"[p] JMPXARGS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"DB1p\",\"stack\":\"c - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_jmpx_args\",\"line\":59,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"JMPXARGS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"arg\",\"type\":\"simple\"}],\"length_var\":\"p\",\"name\":\"args\",\"type\":\"array\"},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"r\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"DB2\",\"tlb\":\"#DB2 r:uint4\"},\"control_flow\":{\"branches\":[{\"index\":0,\"type\":\"register\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p><em>Returns</em> to <code>c0</code>, with <code>0 &lt;= r &lt;= 15</code> return values taken from the current stack.</p>\\n\",\"fift\":\"[r] RETARGS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"DB2r\",\"stack\":\"\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_ret_args\",\"line\":71,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"RETARGS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"arg\",\"type\":\"simple\"}],\"length_var\":\"p\",\"name\":\"args\",\"type\":\"array\"}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"DB30\",\"tlb\":\"#DB30\"},\"control_flow\":{\"branches\":[{\"index\":0,\"type\":\"register\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p><em>Returns</em> to the continuation at <code>c0</code>. The remainder of the current continuation <code>cc</code> is discarded.\\nApproximately equivalent to <code>c0 PUSHCTR</code> <code>JMPX</code>.</p>\\n\",\"fift\":\"RET\\nRETTRUE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"DB30\",\"stack\":\"\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_ret\",\"line\":66,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"RET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"DB31\",\"tlb\":\"#DB31\"},\"control_flow\":{\"branches\":[{\"index\":1,\"type\":\"register\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p><em>Returns</em> to the continuation at <code>c1</code>.\\nApproximately equivalent to <code>c1 PUSHCTR</code> <code>JMPX</code>.</p>\\n\",\"fift\":\"RETALT\\nRETFALSE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"DB31\",\"stack\":\"\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_ret_alt\",\"line\":77,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"RETALT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"DB32\",\"tlb\":\"#DB32\"},\"control_flow\":{\"branches\":[{\"index\":0,\"type\":\"register\"},{\"index\":1,\"type\":\"register\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p>Performs <code>RETTRUE</code> if integer <code>f!=0</code>, or <code>RETFALSE</code> if <code>f=0</code>.</p>\\n\",\"fift\":\"BRANCH\\nRETBOOL\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"DB32\",\"stack\":\"f - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_ret_bool\",\"line\":82,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"BRANCH\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"DB34\",\"tlb\":\"#DB34\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p><em>Call with current continuation</em>, transfers control to <code>c</code>, pushing the old value of <code>cc</code> into <code>c</code>'s stack (instead of discarding it or writing it into new <code>c0</code>).</p>\\n\",\"fift\":\"CALLCC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"DB34\",\"stack\":\"c - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_callcc\",\"line\":87,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"CALLCC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"DB35\",\"tlb\":\"#DB35\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p>Similar to <code>CALLCC</code>, but the remainder of the current continuation (the old value of <code>cc</code>) is converted into a <em>Slice</em> before pushing it into the stack of <code>c</code>.</p>\\n\",\"fift\":\"JMPXDATA\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"DB35\",\"stack\":\"c - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_jmpx_data\",\"line\":96,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"JMPXDATA\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"p\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"optional_nargs\"}],\"max_value\":15,\"min_value\":0,\"name\":\"r\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"DB36\",\"tlb\":\"#DB36 p:uint4 r:uint4\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p>Similar to <code>CALLXARGS</code>, but pushes the old value of <code>cc</code> (along with the top <code>0 &lt;= p &lt;= 15</code> values from the original stack) into the stack of newly-invoked continuation <code>c</code>, setting <code>cc.nargs</code> to <code>-1 &lt;= r &lt;= 14</code>.</p>\\n\",\"fift\":\"[p] [r] CALLCCARGS\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"DB36pr\",\"stack\":\"c - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_callcc_args\",\"line\":103,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"CALLCCARGS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"arg\",\"type\":\"simple\"}],\"length_var\":\"p\",\"name\":\"args\",\"type\":\"array\"},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"DB38\",\"tlb\":\"#DB38\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p>Similar to <code>CALLXARGS</code>, but takes <code>-1 &lt;= p,r &lt;= 254</code> from the stack. The next three operations also take <code>p</code> and <code>r</code> from the stack, both in the range <code>-1...254</code>.</p>\\n\",\"fift\":\"CALLXVARARGS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"DB38\",\"stack\":\"c p r - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_callx_varargs\",\"line\":114,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"CALLXVARARGS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"arg\",\"type\":\"simple\"}],\"length_var\":\"p\",\"name\":\"args\",\"type\":\"array\"},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]},{\"name\":\"p\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"DB39\",\"tlb\":\"#DB39\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p>Similar to <code>RETARGS</code>.</p>\\n\",\"fift\":\"RETVARARGS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"DB39\",\"stack\":\"p r - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_ret_varargs\",\"line\":123,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"RETVARARGS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"arg\",\"type\":\"simple\"}],\"length_var\":\"p\",\"name\":\"args\",\"type\":\"array\"},{\"name\":\"p\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"DB3A\",\"tlb\":\"#DB3A\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p>Similar to <code>JMPXARGS</code>.</p>\\n\",\"fift\":\"JMPXVARARGS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"DB3A\",\"stack\":\"c p r - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_jmpx_varargs\",\"line\":130,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"JMPXVARARGS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"arg\",\"type\":\"simple\"}],\"length_var\":\"p\",\"name\":\"args\",\"type\":\"array\"},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]},{\"name\":\"p\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"DB3B\",\"tlb\":\"#DB3B\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p>Similar to <code>CALLCCARGS</code>.</p>\\n\",\"fift\":\"CALLCCVARARGS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"DB3B\",\"stack\":\"c p r - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_callcc_varargs\",\"line\":139,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"CALLCCVARARGS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"arg\",\"type\":\"simple\"}],\"length_var\":\"p\",\"name\":\"args\",\"type\":\"array\"},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]},{\"name\":\"p\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"continuation\"}],\"name\":\"c\",\"type\":\"ref\"}],\"prefix\":\"DB3C\",\"tlb\":\"#DB3C c:^Cell\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p>Equivalent to <code>PUSHREFCONT</code> <code>CALLX</code>.</p>\\n\",\"fift\":\"[ref] CALLREF\",\"fift_examples\":[],\"gas\":\"126/51\",\"opcode\":\"DB3C\",\"stack\":\"\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_do_with_ref\",\"line\":152,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"CALLREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"continuation\"}],\"name\":\"c\",\"type\":\"ref\"}],\"prefix\":\"DB3D\",\"tlb\":\"#DB3D c:^Cell\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p>Equivalent to <code>PUSHREFCONT</code> <code>JMPX</code>.</p>\\n\",\"fift\":\"[ref] JMPREF\",\"fift_examples\":[],\"gas\":\"126/51\",\"opcode\":\"DB3D\",\"stack\":\"\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_if_bit_jmpref\",\"line\":459,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"JMPREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"continuation\"}],\"name\":\"c\",\"type\":\"ref\"}],\"prefix\":\"DB3E\",\"tlb\":\"#DB3E c:^Cell\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p>Equivalent to <code>PUSHREFCONT</code> <code>JMPXDATA</code>.</p>\\n\",\"fift\":\"[ref] JMPREFDATA\",\"fift_examples\":[],\"gas\":\"126/51\",\"opcode\":\"DB3E\",\"stack\":\"\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_ret_data\",\"line\":209,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"JMPREFDATA\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"DB3F\",\"tlb\":\"#DB3F\"},\"control_flow\":{\"branches\":[{\"index\":0,\"type\":\"register\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p>Equivalent to <code>c0 PUSHCTR</code> <code>JMPXDATA</code>. In this way, the remainder of the current continuation is converted into a <em>Slice</em> and returned to the caller.</p>\\n\",\"fift\":\"RETDATA\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"DB3F\",\"stack\":\"\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_ret_data\",\"line\":209,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"RETDATA\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":4095,\"min_value\":0,\"name\":\"flags\",\"size\":12,\"type\":\"uint\"}],\"prefix\":\"DB4\",\"tlb\":\"#DB4 flags:(## 12)\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p>Runs child VM with code <code>code</code> and stack <code>x_1...x_n</code>. Returns the resulting stack <code>x'_1...x'_m</code> and exitcode. Other arguments and return values are enabled by flags.</p>\\n<p>Flags operate similarly to <code>RUNVMX</code> in Fift:</p>\\n<ul>\\n<li><code>+1</code>: sets <code>c3</code> to code.</li>\\n<li><code>+2</code>: pushes an implicit <code>0</code> before executing the code.</li>\\n<li><code>+4</code>: takes persistent data <code>c4</code> from the stack and returns its final value.</li>\\n<li><code>+8</code>: takes the gas limit <code>g_l</code> from the stack and returns the consumed gas <code>g_c</code>.</li>\\n<li><code>+16</code>: takes <code>c7</code> (smart contract context) from the stack.</li>\\n<li><code>+32</code>: returns the final value of <code>c5</code> (actions).</li>\\n<li><code>+64</code>: pops the hard gas limit <code>g_m</code> enabled by <code>ACCEPT</code> from the stack.</li>\\n<li><code>+128</code>: enables \\\"isolated gas consumption\\\", meaning the child VM maintains a separate set of visited cells and a <code>chksgn</code> counter.</li>\\n<li><code>+256</code>: pops an integer <code>r</code> and ensures exactly <code>r</code> values are returned from the top of the stack:\\n<ul>\\n<li>If <code>RUNVM</code> call succeeds and <code>r</code> is set, it returns <code>r</code> elements. If <code>r</code> is not set, it returns all available elements.</li>\\n<li>If <code>RUNVM</code> is successful but lacks elements on the stack, meaning the stack depth is less than <code>r</code>, it is treated as an exception in the child VM. The <code>exit_code</code> is set to <code>-3</code>, and <code>exit_arg</code> is set to <code>0</code>, so <code>0</code> is returned as the only stack element.</li>\\n<li>If <code>RUNVM</code> fails with an exception, only one element is returned, <code>exit_arg</code>, which should not be confused with <code>exit_code</code>.</li>\\n<li>In the case of running out of gas, <code>exit_code</code> is set to <code>-14</code>, and <code>exit_arg</code> contains the amount of gas.</li>\\n</ul>\\n</li>\\n</ul>\\n<p>Gas cost:</p>\\n<ul>\\n<li>66 gas;</li>\\n<li>1 gas for each stack element passed to the child VM (the first 32 elements are free);</li>\\n<li>1 gas for each stack element returned from the child VM (the first 32 elements are free).</li>\\n</ul>\\n\",\"fift\":\"flags RUNVM\",\"fift_examples\":[],\"gas\":\"74\",\"opcode\":\"DB4fff\",\"stack\":\"x_1 ... x_n n code [r] [c4] [c7] [g_l] [g_m] - x'_1 ... x'_m exitcode [data'] [c4'] [c5] [g_c]\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_execute\",\"line\":33,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"RUNVM\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"DB50\",\"tlb\":\"#DB50\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_basic\",\"description\":\"<p>Runs child VM with code <code>code</code> and stack <code>x_1...x_n</code>. Returns the resulting stack <code>x'_1...x'_m</code> and exitcode. Other arguments and return values are enabled by flags.</p>\\n<p>Flags operate similarly to <code>RUNVMX</code> in Fift:</p>\\n<ul>\\n<li><code>+1</code>: sets <code>c3</code> to code.</li>\\n<li><code>+2</code>: pushes an implicit <code>0</code> before executing the code.</li>\\n<li><code>+4</code>: takes persistent data <code>c4</code> from the stack and returns its final value.</li>\\n<li><code>+8</code>: takes the gas limit <code>g_l</code> from the stack and returns the consumed gas <code>g_c</code>.</li>\\n<li><code>+16</code>: takes <code>c7</code> (smart contract context) from the stack.</li>\\n<li><code>+32</code>: returns the final value of <code>c5</code> (actions).</li>\\n<li><code>+64</code>: pops the hard gas limit <code>g_m</code> enabled by <code>ACCEPT</code> from the stack.</li>\\n<li><code>+128</code>: enables \\\"isolated gas consumption\\\", meaning the child VM maintains a separate set of visited cells and a <code>chksgn</code> counter.</li>\\n<li><code>+256</code>: pops an integer <code>r</code> and ensures exactly <code>r</code> values are returned from the top of the stack:\\n<ul>\\n<li>If <code>RUNVM</code> call succeeds and <code>r</code> is set, it returns <code>r</code> elements. If <code>r</code> is not set, it returns all available elements.</li>\\n<li>If <code>RUNVM</code> is successful but lacks elements on the stack, meaning the stack depth is less than <code>r</code>, it is treated as an exception in the child VM. The <code>exit_code</code> is set to <code>-3</code>, and <code>exit_arg</code> is set to <code>0</code>, so <code>0</code> is returned as the only stack element.</li>\\n<li>If <code>RUNVM</code> fails with an exception, only one element is returned, <code>exit_arg</code>, which should not be confused with <code>exit_code</code>.</li>\\n<li>In the case of running out of gas, <code>exit_code</code> is set to <code>-14</code>, and <code>exit_arg</code> contains the amount of gas.</li>\\n</ul>\\n</li>\\n</ul>\\n<p>Gas cost:</p>\\n<ul>\\n<li>66 gas;</li>\\n<li>1 gas for each stack element passed to the child VM (the first 32 elements are free);</li>\\n<li>1 gas for each stack element returned from the child VM (the first 32 elements are free).</li>\\n</ul>\\n\",\"fift\":\"RUNVMX\",\"fift_examples\":[],\"gas\":\"66\",\"opcode\":\"DB50\",\"stack\":\"x_1 ... x_n n code [r] [c4] [c7] [g_l] [g_m] flags - x'_1 ... x'_m exitcode [data'] [c4'] [c5] [g_c]\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_runvmx\",\"line\":277,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"RUNVMX\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"DC\",\"tlb\":\"#DC\"},\"control_flow\":{\"branches\":[{\"index\":0,\"type\":\"register\"}],\"nobranch\":true},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>Performs a <code>RET</code>, but only if integer <code>f</code> is non-zero. If <code>f</code> is a <code>NaN</code>, throws an integer overflow exception.</p>\\n\",\"fift\":\"IFRET\\nIFNOT:\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"DC\",\"stack\":\"f - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_ifret\",\"line\":369,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"IFRET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"DD\",\"tlb\":\"#DD\"},\"control_flow\":{\"branches\":[{\"index\":0,\"type\":\"register\"}],\"nobranch\":true},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>Performs a <code>RET</code>, but only if integer <code>f</code> is zero.</p>\\n\",\"fift\":\"IFNOTRET\\nIF:\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"DD\",\"stack\":\"f - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_ifnotret\",\"line\":377,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"IFNOTRET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"DE\",\"tlb\":\"#DE\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":true},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>Performs <code>EXECUTE</code> for <code>c</code> (i.e., <em>executes</em> <code>c</code>), but only if integer <code>f</code> is non-zero. Otherwise simply discards both values.</p>\\n\",\"fift\":\"IF\",\"fift_examples\":[{\"description\":\"Equivalent to `<{ code }> CONT` `IF`.\",\"fift\":\"IF:<{ code }> <{ code }>IF\"}],\"gas\":\"18\",\"opcode\":\"DE\",\"stack\":\"f c - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_if\",\"line\":325,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"IF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"DF\",\"tlb\":\"#DF\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":true},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>Executes continuation <code>c</code>, but only if integer <code>f</code> is zero. Otherwise simply discards both values.</p>\\n\",\"fift\":\"IFNOT\",\"fift_examples\":[{\"description\":\"Equivalent to `<{ code }> CONT` `IFNOT`.\",\"fift\":\"IFNOT:<{ code }> <{ code }>IFNOT\"}],\"gas\":\"18\",\"opcode\":\"DF\",\"stack\":\"f c - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_ifnot\",\"line\":336,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"IFNOT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E0\",\"tlb\":\"#E0\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":true},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>Jumps to <code>c</code> (similarly to <code>JMPX</code>), but only if <code>f</code> is non-zero.</p>\\n\",\"fift\":\"IFJMP\",\"fift_examples\":[{\"description\":\"Equivalent to `<{ code }> CONT` `IFJMP`.\",\"fift\":\"IFJMP:<{ code }>\"}],\"gas\":\"18\",\"opcode\":\"E0\",\"stack\":\"f c - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_if_jmp\",\"line\":347,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"IFJMP\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E1\",\"tlb\":\"#E1\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":true},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>Jumps to <code>c</code> (similarly to <code>JMPX</code>), but only if <code>f</code> is zero.</p>\\n\",\"fift\":\"IFNOTJMP\",\"fift_examples\":[{\"description\":\"Equivalent to `<{ code }> CONT` `IFNOTJMP`.\",\"fift\":\"IFNOTJMP:<{ code }>\"}],\"gas\":\"18\",\"opcode\":\"E1\",\"stack\":\"f c - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_ifnot_jmp\",\"line\":358,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"IFNOTJMP\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E2\",\"tlb\":\"#E2\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c\"},{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c2\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>If integer <code>f</code> is non-zero, executes <code>c</code>, otherwise executes <code>c'</code>. Equivalent to <code>CONDSELCHK</code> <code>EXECUTE</code>.</p>\\n\",\"fift\":\"IFELSE\",\"fift_examples\":[{\"description\":\"Equivalent to `<{ code1 }> CONT` `<{ code2 }> CONT` `IFELSE`.\",\"fift\":\"IF:<{ code1 }>ELSE<{ code2 }>\"}],\"gas\":\"18\",\"opcode\":\"E2\",\"stack\":\"f c c' - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_if_else\",\"line\":385,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"IFELSE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]},{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"continuation\"}],\"name\":\"c\",\"type\":\"ref\"}],\"prefix\":\"E300\",\"tlb\":\"#E300 c:^Cell\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":true},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>Equivalent to <code>PUSHREFCONT</code> <code>IF</code>, with the optimization that the cell reference is not actually loaded into a <em>Slice</em> and then converted into an ordinary <em>Continuation</em> if <code>f=0</code>.\\nGas consumption of this primitive depends on whether <code>f=0</code> and whether the reference was loaded before.\\nSimilar remarks apply other primitives that accept a continuation as a reference.</p>\\n\",\"fift\":\"[ref] IFREF\",\"fift_examples\":[],\"gas\":\"26/126/51\",\"opcode\":\"E300\",\"stack\":\"f - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_ifret\",\"line\":369,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"IFREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"continuation\"}],\"name\":\"c\",\"type\":\"ref\"}],\"prefix\":\"E301\",\"tlb\":\"#E301 c:^Cell\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":true},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>Equivalent to <code>PUSHREFCONT</code> <code>IFNOT</code>.</p>\\n\",\"fift\":\"[ref] IFNOTREF\",\"fift_examples\":[],\"gas\":\"26/126/51\",\"opcode\":\"E301\",\"stack\":\"f - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_ifnotret\",\"line\":377,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"IFNOTREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"continuation\"}],\"name\":\"c\",\"type\":\"ref\"}],\"prefix\":\"E302\",\"tlb\":\"#E302 c:^Cell\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":true},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>Equivalent to <code>PUSHREFCONT</code> <code>IFJMP</code>.</p>\\n\",\"fift\":\"[ref] IFJMPREF\",\"fift_examples\":[],\"gas\":\"26/126/51\",\"opcode\":\"E302\",\"stack\":\"f - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_if_bit_jmpref\",\"line\":459,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"IFJMPREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"continuation\"}],\"name\":\"c\",\"type\":\"ref\"}],\"prefix\":\"E303\",\"tlb\":\"#E303 c:^Cell\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":true},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>Equivalent to <code>PUSHREFCONT</code> <code>IFNOTJMP</code>.</p>\\n\",\"fift\":\"[ref] IFNOTJMPREF\",\"fift_examples\":[],\"gas\":\"26/126/51\",\"opcode\":\"E303\",\"stack\":\"f - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_condsel\",\"line\":398,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"IFNOTJMPREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E304\",\"tlb\":\"#E304\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>If integer <code>f</code> is non-zero, returns <code>x</code>, otherwise returns <code>y</code>. Notice that no type checks are performed on <code>x</code> and <code>y</code>; as such, it is more like a conditional stack operation. Roughly equivalent to <code>ROT</code> <code>ISZERO</code> <code>INC</code> <code>ROLLX</code> <code>NIP</code>.</p>\\n\",\"fift\":\"CONDSEL\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"E304\",\"stack\":\"f x y - x or y\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_condsel\",\"line\":398,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"CONDSEL\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"y\",\"type\":\"simple\"}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\"}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E305\",\"tlb\":\"#E305\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>Same as <code>CONDSEL</code>, but first checks whether <code>x</code> and <code>y</code> have the same type.</p>\\n\",\"fift\":\"CONDSELCHK\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"E305\",\"stack\":\"f x y - x or y\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_condsel_chk\",\"line\":408,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"CONDSELCHK\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"y\",\"type\":\"simple\"}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\"}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E308\",\"tlb\":\"#E308\"},\"control_flow\":{\"branches\":[{\"index\":1,\"type\":\"register\"}],\"nobranch\":true},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>Performs <code>RETALT</code> if integer <code>f!=0</code>.</p>\\n\",\"fift\":\"IFRETALT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"E308\",\"stack\":\"f -\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_ifretalt\",\"line\":421,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"IFRETALT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E309\",\"tlb\":\"#E309\"},\"control_flow\":{\"branches\":[{\"index\":1,\"type\":\"register\"}],\"nobranch\":true},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>Performs <code>RETALT</code> if integer <code>f=0</code>.</p>\\n\",\"fift\":\"IFNOTRETALT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"E309\",\"stack\":\"f -\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_ifnotretalt\",\"line\":429,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"IFNOTRETALT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"continuation\"}],\"name\":\"c\",\"type\":\"ref\"}],\"prefix\":\"E30D\",\"tlb\":\"#E30D c:^Cell\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c\"},{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c2\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>Equivalent to <code>PUSHREFCONT</code> <code>SWAP</code> <code>IFELSE</code>, with the optimization that the cell reference is not actually loaded into a <em>Slice</em> and then converted into an ordinary <em>Continuation</em> if <code>f=0</code>. Similar remarks apply to the next two primitives: cells are converted into continuations only when necessary.</p>\\n\",\"fift\":\"[ref] IFREFELSE\",\"fift_examples\":[],\"gas\":\"26/126/51\",\"opcode\":\"E30D\",\"stack\":\"f c -\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_ifref_elseref\",\"line\":193,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"IFREFELSE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"continuation\"}],\"name\":\"c\",\"type\":\"ref\"}],\"prefix\":\"E30E\",\"tlb\":\"#E30E c:^Cell\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c\"},{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c2\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>Equivalent to <code>PUSHREFCONT</code> <code>IFELSE</code>.</p>\\n\",\"fift\":\"[ref] IFELSEREF\",\"fift_examples\":[],\"gas\":\"26/126/51\",\"opcode\":\"E30E\",\"stack\":\"f c -\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_ifelse_ref\",\"line\":174,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"IFELSEREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"continuation\"}],\"name\":\"c1\",\"type\":\"ref\"},{\"display_hints\":[{\"type\":\"continuation\"}],\"name\":\"c2\",\"type\":\"ref\"}],\"prefix\":\"E30F\",\"tlb\":\"#E30F c1:^Cell c2:^Cell\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c1\"},{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c2\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>Equivalent to <code>PUSHREFCONT</code> <code>PUSHREFCONT</code> <code>IFELSE</code>.</p>\\n\",\"fift\":\"[ref] [ref] IFREFELSEREF\",\"fift_examples\":[],\"gas\":\"126/51\",\"opcode\":\"E30F\",\"stack\":\"f -\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_ifref_elseref\",\"line\":193,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"IFREFELSEREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":31,\"min_value\":0,\"name\":\"n\",\"size\":5,\"type\":\"uint\"}],\"prefix\":\"E39_\",\"tlb\":\"#E39_ n:uint5\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>Checks whether bit <code>0 &lt;= n &lt;= 31</code> is set in integer <code>x</code>, and if so, performs <code>JMPX</code> to continuation <code>c</code>. Value <code>x</code> is left in the stack.</p>\\n\",\"fift\":\"[n] IFBITJMP\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"E39_n\",\"stack\":\"x c - x\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_if_bit_jmp\",\"line\":437,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"IFBITJMP\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":31,\"min_value\":0,\"name\":\"n\",\"size\":5,\"type\":\"uint\"}],\"prefix\":\"E3B_\",\"tlb\":\"#E3B_ n:uint5\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>Jumps to <code>c</code> if bit <code>0 &lt;= n &lt;= 31</code> is not set in integer <code>x</code>.</p>\\n\",\"fift\":\"[n] IFNBITJMP\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"E3B_n\",\"stack\":\"x c - x\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_if_bit_jmp\",\"line\":437,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"IFNBITJMP\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":31,\"min_value\":0,\"name\":\"n\",\"size\":5,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"continuation\"}],\"name\":\"c\",\"type\":\"ref\"}],\"prefix\":\"E3D_\",\"tlb\":\"#E3D_ n:uint5 c:^Cell\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>Performs a <code>JMPREF</code> if bit <code>0 &lt;= n &lt;= 31</code> is set in integer <code>x</code>.</p>\\n\",\"fift\":\"[ref] [n] IFBITJMPREF\",\"fift_examples\":[],\"gas\":\"126/51\",\"opcode\":\"E3D_n\",\"stack\":\"x - x\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_if_bit_jmpref\",\"line\":459,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"IFBITJMPREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":31,\"min_value\":0,\"name\":\"n\",\"size\":5,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"continuation\"}],\"name\":\"c\",\"type\":\"ref\"}],\"prefix\":\"E3F_\",\"tlb\":\"#E3F_ n:uint5 c:^Cell\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_conditional\",\"description\":\"<p>Performs a <code>JMPREF</code> if bit <code>0 &lt;= n &lt;= 31</code> is not set in integer <code>x</code>.</p>\\n\",\"fift\":\"[ref] [n] IFNBITJMPREF\",\"fift_examples\":[],\"gas\":\"126/51\",\"opcode\":\"E3F_n\",\"stack\":\"x - x\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_if_bit_jmpref\",\"line\":459,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"IFNBITJMPREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E4\",\"tlb\":\"#E4\"},\"control_flow\":{\"branches\":[{\"args\":{\"after\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"},\"body\":{\"type\":\"variable\",\"var_name\":\"c\"},\"count\":\"n\"},\"name\":\"repeat\",\"type\":\"special\"}],\"nobranch\":true},\"doc\":{\"category\":\"cont_loops\",\"description\":\"<p>Executes continuation <code>c</code> <code>n</code> times, if integer <code>n</code> is non-negative. If <code>n&gt;=2^31</code> or <code>n&lt;-2^31</code>, generates a range check exception.\\nNotice that a <code>RET</code> inside the code of <code>c</code> works as a <code>continue</code>, not as a <code>break</code>. One should use either alternative (experimental) loops or alternative <code>RETALT</code> (along with a <code>SETEXITALT</code> before the loop) to <code>break</code> out of a loop.</p>\\n\",\"fift\":\"REPEAT\",\"fift_examples\":[{\"description\":\"Equivalent to `<{ code }> CONT` `REPEAT`.\",\"fift\":\"REPEAT:<{ code }> <{ code }>REPEAT\"}],\"gas\":\"18\",\"opcode\":\"E4\",\"stack\":\"n c - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_repeat\",\"line\":489,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"REPEAT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E5\",\"tlb\":\"#E5\"},\"control_flow\":{\"branches\":[{\"args\":{\"after\":{\"index\":0,\"type\":\"register\"},\"body\":{\"type\":\"cc\"},\"count\":\"n\"},\"name\":\"repeat\",\"type\":\"special\"}],\"nobranch\":true},\"doc\":{\"category\":\"cont_loops\",\"description\":\"<p>Similar to <code>REPEAT</code>, but it is applied to the current continuation <code>cc</code>.</p>\\n\",\"fift\":\"REPEATEND\\nREPEAT:\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"E5\",\"stack\":\"n - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_repeat_end\",\"line\":501,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"REPEATEND\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E6\",\"tlb\":\"#E6\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"args\":{\"after\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"},\"body\":{\"type\":\"variable\",\"var_name\":\"c\"}},\"name\":\"until\",\"type\":\"special\"}},\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_loops\",\"description\":\"<p>Executes continuation <code>c</code>, then pops an integer <code>x</code> from the resulting stack. If <code>x</code> is zero, performs another iteration of this loop. The actual implementation of this primitive involves an extraordinary continuation <code>ec_until</code> with its arguments set to the body of the loop (continuation <code>c</code>) and the original current continuation <code>cc</code>. This extraordinary continuation is then saved into the savelist of <code>c</code> as <code>c.c0</code> and the modified <code>c</code> is then executed. The other loop primitives are implemented similarly with the aid of suitable extraordinary continuations.</p>\\n\",\"fift\":\"UNTIL\",\"fift_examples\":[{\"description\":\"Equivalent to `<{ code }> CONT` `UNTIL`.\",\"fift\":\"UNTIL:<{ code }> <{ code }>UNTIL\"}],\"gas\":\"18\",\"opcode\":\"E6\",\"stack\":\"c - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_until\",\"line\":513,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"UNTIL\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E7\",\"tlb\":\"#E7\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"args\":{\"after\":{\"index\":0,\"type\":\"register\"},\"body\":{\"type\":\"cc\"}},\"name\":\"until\",\"type\":\"special\"}},\"type\":\"cc\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_loops\",\"description\":\"<p>Similar to <code>UNTIL</code>, but executes the current continuation <code>cc</code> in a loop. When the loop exit condition is satisfied, performs a <code>RET</code>.</p>\\n\",\"fift\":\"UNTILEND\\nUNTIL:\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"E7\",\"stack\":\"-\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_until_end\",\"line\":520,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"UNTILEND\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E8\",\"tlb\":\"#E8\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"args\":{\"after\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"},\"body\":{\"type\":\"variable\",\"var_name\":\"c\"},\"cond\":{\"type\":\"variable\",\"var_name\":\"c2\"}},\"name\":\"while\",\"type\":\"special\"}},\"type\":\"variable\",\"var_name\":\"c2\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_loops\",\"description\":\"<p>Executes <code>c'</code> and pops an integer <code>x</code> from the resulting stack. If <code>x</code> is zero, exists the loop and transfers control to the original <code>cc</code>. If <code>x</code> is non-zero, executes <code>c</code>, and then begins a new iteration.</p>\\n\",\"fift\":\"WHILE\",\"fift_examples\":[{\"description\":\"Equivalent to `<{ cond }> CONT` `<{ code }> CONT` `WHILE`.\",\"fift\":\"WHILE:<{ cond }>DO<{ code }>\"}],\"gas\":\"18\",\"opcode\":\"E8\",\"stack\":\"c' c - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_while\",\"line\":526,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"WHILE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E9\",\"tlb\":\"#E9\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"args\":{\"after\":{\"index\":0,\"type\":\"register\"},\"body\":{\"type\":\"cc\"},\"cond\":{\"type\":\"variable\",\"var_name\":\"c2\"}},\"name\":\"while\",\"type\":\"special\"}},\"type\":\"variable\",\"var_name\":\"c2\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_loops\",\"description\":\"<p>Similar to <code>WHILE</code>, but uses the current continuation <code>cc</code> as the loop body.</p>\\n\",\"fift\":\"WHILEEND\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"E9\",\"stack\":\"c' - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_while_end\",\"line\":535,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"WHILEEND\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"EA\",\"tlb\":\"#EA\"},\"control_flow\":{\"branches\":[{\"args\":{\"body\":{\"type\":\"variable\",\"var_name\":\"c\"}},\"name\":\"again\",\"type\":\"special\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_loops\",\"description\":\"<p>Similar to <code>REPEAT</code>, but executes <code>c</code> infinitely many times. A <code>RET</code> only begins a new iteration of the infinite loop, which can be exited only by an exception, or a <code>RETALT</code> (or an explicit <code>JMPX</code>).</p>\\n\",\"fift\":\"AGAIN\",\"fift_examples\":[{\"description\":\"Equivalent to `<{ code }> CONT` `AGAIN`.\",\"fift\":\"AGAIN:<{ code }> <{ code }>AGAIN\"}],\"gas\":\"18\",\"opcode\":\"EA\",\"stack\":\"c - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_again\",\"line\":542,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"AGAIN\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"EB\",\"tlb\":\"#EB\"},\"control_flow\":{\"branches\":[{\"args\":{\"body\":{\"type\":\"cc\"}},\"name\":\"again\",\"type\":\"special\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_loops\",\"description\":\"<p>Similar to <code>AGAIN</code>, but performed with respect to the current continuation <code>cc</code>.</p>\\n\",\"fift\":\"AGAINEND\\nAGAIN:\",\"fift_examples\":[],\"gas\":\"18\",\"opcode\":\"EB\",\"stack\":\"-\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_again_end\",\"line\":550,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"AGAINEND\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E314\",\"tlb\":\"#E314\"},\"control_flow\":{\"branches\":[{\"args\":{\"after\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"},\"c1\":{\"index\":1,\"type\":\"register\"}},\"type\":\"cc\"},\"body\":{\"save\":{\"c1\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"},\"c1\":{\"index\":1,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c\"},\"count\":\"n\"},\"name\":\"repeat\",\"type\":\"special\"}],\"nobranch\":true},\"doc\":{\"category\":\"cont_loops\",\"description\":\"<p>Similar to <code>REPEAT</code>, but also sets <code>c1</code> to the original <code>cc</code> after saving the old value of <code>c1</code> into the savelist of the original <code>cc</code>. In this way <code>RETALT</code> could be used to break out of the loop body.</p>\\n\",\"fift\":\"REPEATBRK\",\"fift_examples\":[{\"description\":\"Equivalent to `<{ code }> CONT` `REPEATBRK`.\",\"fift\":\"REPEATBRK:<{ code }> <{ code }>REPEATBRK\"}],\"gas\":\"26\",\"opcode\":\"E314\",\"stack\":\"n c -\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_repeat\",\"line\":489,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"REPEATBRK\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E315\",\"tlb\":\"#E315\"},\"control_flow\":{\"branches\":[{\"args\":{\"after\":{\"index\":0,\"type\":\"register\"},\"body\":{\"save\":{\"c1\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"},\"count\":\"n\"},\"name\":\"repeat\",\"type\":\"special\"}],\"nobranch\":true},\"doc\":{\"category\":\"cont_loops\",\"description\":\"<p>Similar to <code>REPEATEND</code>, but also sets <code>c1</code> to the original <code>c0</code> after saving the old value of <code>c1</code> into the savelist of the original <code>c0</code>. Equivalent to <code>SAMEALTSAVE</code> <code>REPEATEND</code>.</p>\\n\",\"fift\":\"REPEATENDBRK\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"E315\",\"stack\":\"n -\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_repeat_end\",\"line\":501,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"REPEATENDBRK\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E316\",\"tlb\":\"#E316\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"args\":{\"after\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"},\"c1\":{\"index\":1,\"type\":\"register\"}},\"type\":\"cc\"},\"body\":{\"save\":{\"c1\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"},\"c1\":{\"index\":1,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c\"}},\"name\":\"until\",\"type\":\"special\"},\"c1\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"},\"c1\":{\"index\":1,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_loops\",\"description\":\"<p>Similar to <code>UNTIL</code>, but also modifies <code>c1</code> in the same way as <code>REPEATBRK</code>.</p>\\n\",\"fift\":\"UNTILBRK\",\"fift_examples\":[{\"description\":\"Equivalent to `<{ code }> CONT` `UNTILBRK`.\",\"fift\":\"UNTILBRK:<{ code }>\"}],\"gas\":\"26\",\"opcode\":\"E316\",\"stack\":\"c -\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_until\",\"line\":513,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"UNTILBRK\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E317\",\"tlb\":\"#E317\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"args\":{\"after\":{\"index\":0,\"type\":\"register\"},\"body\":{\"save\":{\"c1\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"name\":\"until\",\"type\":\"special\"},\"c1\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_loops\",\"description\":\"<p>Equivalent to <code>SAMEALTSAVE</code> <code>UNTILEND</code>.</p>\\n\",\"fift\":\"UNTILENDBRK\\nUNTILBRK:\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"E317\",\"stack\":\"-\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_until_end\",\"line\":520,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"UNTILENDBRK\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E318\",\"tlb\":\"#E318\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"args\":{\"after\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"},\"c1\":{\"index\":1,\"type\":\"register\"}},\"type\":\"cc\"},\"body\":{\"type\":\"variable\",\"var_name\":\"c\"},\"cond\":{\"type\":\"variable\",\"var_name\":\"c2\"}},\"name\":\"while\",\"type\":\"special\"}},\"type\":\"variable\",\"var_name\":\"c2\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_loops\",\"description\":\"<p>Similar to <code>WHILE</code>, but also modifies <code>c1</code> in the same way as <code>REPEATBRK</code>.</p>\\n\",\"fift\":\"WHILEBRK\",\"fift_examples\":[{\"description\":\"Equivalent to `<{ cond }> CONT` `<{ code }> CONT` `WHILEBRK`.\",\"fift\":\"WHILEBRK:<{ cond }>DO<{ code }>\"}],\"gas\":\"26\",\"opcode\":\"E318\",\"stack\":\"c' c -\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_while\",\"line\":526,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"WHILEBRK\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E319\",\"tlb\":\"#E319\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_loops\",\"description\":\"<p>Equivalent to <code>SAMEALTSAVE</code> <code>WHILEEND</code>.</p>\\n\",\"fift\":\"WHILEENDBRK\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"E319\",\"stack\":\"c -\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_while_end\",\"line\":535,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"WHILEENDBRK\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E31A\",\"tlb\":\"#E31A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_loops\",\"description\":\"<p>Similar to <code>AGAIN</code>, but also modifies <code>c1</code> in the same way as <code>REPEATBRK</code>.</p>\\n\",\"fift\":\"AGAINBRK\",\"fift_examples\":[{\"description\":\"Equivalent to `<{ code }> CONT` `AGAINBRK`.\",\"fift\":\"AGAINBRK:<{ code }>\"}],\"gas\":\"26\",\"opcode\":\"E31A\",\"stack\":\"c -\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_again\",\"line\":542,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"AGAINBRK\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"E31B\",\"tlb\":\"#E31B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_loops\",\"description\":\"<p>Equivalent to <code>SAMEALTSAVE</code> <code>AGAINEND</code>.</p>\\n\",\"fift\":\"AGAINENDBRK\\nAGAINBRK:\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"E31B\",\"stack\":\"-\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_again_end\",\"line\":550,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"AGAINENDBRK\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"r\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"optional_nargs\"}],\"max_value\":15,\"min_value\":0,\"name\":\"n\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"EC\",\"tlb\":\"#EC r:uint4 n:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_stack\",\"description\":\"<p>Pushes <code>0 &lt;= r &lt;= 15</code> values <code>x_1...x_r</code> into the stack of (a copy of) the continuation <code>c</code>, starting with <code>x_1</code>. When <code>n</code> is 15 (-1 in Fift notation), does nothing with <code>c.nargs</code>. For <code>0 &lt;= n &lt;= 14</code>, sets <code>c.nargs</code> to the final size of the stack of <code>c'</code> plus <code>n</code>. In other words, transforms <code>c</code> into a <em>closure</em> or a <em>partially applied function</em>, with <code>0 &lt;= n &lt;= 14</code> arguments missing.</p>\\n\",\"fift\":\"[r] [n] SETCONTARGS\",\"fift_examples\":[],\"gas\":\"26+s''\",\"opcode\":\"ECrn\",\"stack\":\"x_1 x_2...x_r c - c'\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_setcontargs\",\"line\":665,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"SETCONTARGS_N\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"x\",\"type\":\"simple\"}],\"length_var\":\"r\",\"name\":\"args\",\"type\":\"array\"},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"p\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"ED0\",\"tlb\":\"#ED0 p:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_stack\",\"description\":\"<p>Leaves only the top <code>0 &lt;= p &lt;= 15</code> values in the current stack (somewhat similarly to <code>ONLYTOPX</code>), with all the unused bottom values not discarded, but saved into continuation <code>c0</code> in the same way as <code>SETCONTARGS</code> does.</p>\\n\",\"fift\":\"[p] RETURNARGS\",\"fift_examples\":[],\"gas\":\"26+s''\",\"opcode\":\"ED0p\",\"stack\":\"-\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_return_args\",\"line\":722,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"RETURNARGS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"ED10\",\"tlb\":\"#ED10\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_stack\",\"description\":\"<p>Similar to <code>RETURNARGS</code>, but with Integer <code>0 &lt;= p &lt;= 255</code> taken from the stack.</p>\\n\",\"fift\":\"RETURNVARARGS\",\"fift_examples\":[],\"gas\":\"26+s''\",\"opcode\":\"ED10\",\"stack\":\"p -\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_return_varargs\",\"line\":728,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"RETURNVARARGS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"ED11\",\"tlb\":\"#ED11\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_stack\",\"description\":\"<p>Similar to <code>SETCONTARGS</code>, but with <code>0 &lt;= r &lt;= 255</code> and <code>-1 &lt;= n &lt;= 255</code> taken from the stack.</p>\\n\",\"fift\":\"SETCONTVARARGS\",\"fift_examples\":[],\"gas\":\"26+s''\",\"opcode\":\"ED11\",\"stack\":\"x_1 x_2...x_r c r n - c'\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_setcont_varargs\",\"line\":678,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"SETCONTVARARGS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"x\",\"type\":\"simple\"}],\"length_var\":\"r\",\"name\":\"args\",\"type\":\"array\"},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"ED12\",\"tlb\":\"#ED12\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_stack\",\"description\":\"<p><code>-1 &lt;= n &lt;= 255</code>\\nIf <code>n=-1</code>, this operation does nothing (<code>c'=c</code>).\\nOtherwise its action is similar to <code>[n] SETNUMARGS</code>, but with <code>n</code> taken from the stack.</p>\\n\",\"fift\":\"SETNUMVARARGS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"ED12\",\"stack\":\"c n - c'\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_setnum_varargs\",\"line\":687,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"SETNUMVARARGS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"ED1E\",\"tlb\":\"#ED1E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_create\",\"description\":\"<p>Transforms a <em>Slice</em> <code>s</code> into a simple ordinary continuation <code>c</code>, with <code>c.code=s</code> and an empty stack and savelist.</p>\\n\",\"fift\":\"BLESS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"ED1E\",\"stack\":\"s - c\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_bless\",\"line\":733,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"BLESS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"ED1F\",\"tlb\":\"#ED1F\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_create\",\"description\":\"<p>Equivalent to <code>ROT</code> <code>BLESS</code> <code>ROTREV</code> <code>SETCONTVARARGS</code>.</p>\\n\",\"fift\":\"BLESSVARARGS\",\"fift_examples\":[],\"gas\":\"26+s''\",\"opcode\":\"ED1F\",\"stack\":\"x_1...x_r s r n - c\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_bless_varargs\",\"line\":750,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"BLESSVARARGS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"x\",\"type\":\"simple\"}],\"length_var\":\"r\",\"name\":\"args\",\"type\":\"array\"},{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"r\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[{\"type\":\"optional_nargs\"}],\"max_value\":15,\"min_value\":0,\"name\":\"n\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"EE\",\"tlb\":\"#EE r:uint4 n:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_create\",\"description\":\"<p><code>0 &lt;= r &lt;= 15</code>, <code>-1 &lt;= n &lt;= 14</code>\\nEquivalent to <code>BLESS</code> <code>[r] [n] SETCONTARGS</code>.\\nThe value of <code>n</code> is represented inside the instruction by the 4-bit integer <code>n mod 16</code>.</p>\\n\",\"fift\":\"[r] [n] BLESSARGS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"EErn\",\"stack\":\"x_1...x_r s - c\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_bless_args\",\"line\":759,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"BLESSARGS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"x\",\"type\":\"simple\"}],\"length_var\":\"r\",\"name\":\"args\",\"type\":\"array\"},{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"register\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"ED4\",\"tlb\":\"#ED4 i:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Pushes the current value of control register <code>c(i)</code>. If the control register is not supported in the current codepage, or if it does not have a value, an exception is triggered.</p>\\n\",\"fift\":\"c[i] PUSHCTR\\nc[i] PUSH\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"ED4i\",\"stack\":\"- x\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_push_ctr\",\"line\":765,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"PUSHCTR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"type\":\"variable\",\"var_name\":\"i\"}],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"register\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"ED5\",\"tlb\":\"#ED5 i:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Pops a value <code>x</code> from the stack and stores it into control register <code>c(i)</code>, if supported in the current codepage. Notice that if a control register accepts only values of a specific type, a type-checking exception may occur.</p>\\n\",\"fift\":\"c[i] POPCTR\\nc[i] POP\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"ED5i\",\"stack\":\"x - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_pop_ctr\",\"line\":794,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"POPCTR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"}]},\"outputs\":{\"registers\":[{\"type\":\"variable\",\"var_name\":\"i\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"register\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"ED6\",\"tlb\":\"#ED6 i:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Stores <code>x</code> into the savelist of continuation <code>c</code> as <code>c(i)</code>, and returns the resulting continuation <code>c'</code>. Almost all operations with continuations may be expressed in terms of <code>SETCONTCTR</code>, <code>POPCTR</code>, and <code>PUSHCTR</code>.</p>\\n\",\"fift\":\"c[i] SETCONT\\nc[i] SETCONTCTR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"ED6i\",\"stack\":\"x c - c'\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_setcont_ctr\",\"line\":807,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"SETCONTCTR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"register\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"ED7\",\"tlb\":\"#ED7 i:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Equivalent to <code>c0 PUSHCTR</code> <code>c[i] SETCONTCTR</code> <code>c0 POPCTR</code>.</p>\\n\",\"fift\":\"c[i] SETRETCTR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"ED7i\",\"stack\":\"x - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_setret_ctr\",\"line\":818,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"SETRETCTR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":0,\"type\":\"constant\"}],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"}]},\"outputs\":{\"registers\":[{\"index\":0,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"register\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"ED8\",\"tlb\":\"#ED8 i:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Equivalent to <code>c1 PUSHCTR</code> <code>c[i] SETCONTCTR</code> <code>c1 POPCTR</code>.</p>\\n\",\"fift\":\"c[i] SETALTCTR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"ED8i\",\"stack\":\"x - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_setalt_ctr\",\"line\":827,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"SETALTCTR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":1,\"type\":\"constant\"}],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"}]},\"outputs\":{\"registers\":[{\"index\":1,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"register\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"ED9\",\"tlb\":\"#ED9 i:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Similar to <code>c[i] POPCTR</code>, but also saves the old value of <code>c[i]</code> into continuation <code>c0</code>.\\nEquivalent (up to exceptions) to <code>c[i] SAVECTR</code> <code>c[i] POPCTR</code>.</p>\\n\",\"fift\":\"c[i] POPSAVE\\nc[i] POPCTRSAVE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"ED9i\",\"stack\":\"x -\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_popsave_ctr\",\"line\":836,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"POPSAVE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"type\":\"variable\",\"var_name\":\"i\"},{\"index\":0,\"type\":\"constant\"}],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"}]},\"outputs\":{\"registers\":[{\"index\":0,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"register\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"EDA\",\"tlb\":\"#EDA i:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Saves the current value of <code>c(i)</code> into the savelist of continuation <code>c0</code>. If an entry for <code>c[i]</code> is already present in the savelist of <code>c0</code>, nothing is done. Equivalent to <code>c[i] PUSHCTR</code> <code>c[i] SETRETCTR</code>.</p>\\n\",\"fift\":\"c[i] SAVE\\nc[i] SAVECTR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"EDAi\",\"stack\":\"\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_savealt_ctr\",\"line\":873,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"SAVE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"type\":\"variable\",\"var_name\":\"i\"},{\"index\":0,\"type\":\"constant\"}],\"stack\":[]},\"outputs\":{\"registers\":[{\"index\":0,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"register\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"EDB\",\"tlb\":\"#EDB i:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Similar to <code>c[i] SAVE</code>, but saves the current value of <code>c[i]</code> into the savelist of <code>c1</code>, not <code>c0</code>.</p>\\n\",\"fift\":\"c[i] SAVEALT\\nc[i] SAVEALTCTR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"EDBi\",\"stack\":\"\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_samealt\",\"line\":862,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"SAVEALT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"type\":\"variable\",\"var_name\":\"i\"},{\"index\":1,\"type\":\"constant\"}],\"stack\":[]},\"outputs\":{\"registers\":[{\"index\":1,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"register\"}],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"EDC\",\"tlb\":\"#EDC i:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Equivalent to <code>c[i] SAVE</code> <code>c[i] SAVEALT</code>.</p>\\n\",\"fift\":\"c[i] SAVEBOTH\\nc[i] SAVEBOTHCTR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"EDCi\",\"stack\":\"\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_saveboth_ctr\",\"line\":882,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"SAVEBOTH\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"type\":\"variable\",\"var_name\":\"i\"},{\"index\":0,\"type\":\"constant\"},{\"index\":1,\"type\":\"constant\"}],\"stack\":[]},\"outputs\":{\"registers\":[{\"index\":0,\"type\":\"constant\"},{\"index\":1,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"EDE0\",\"tlb\":\"#EDE0\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Similar to <code>c[i] PUSHCTR</code>, but with <code>i</code>, <code>0 &lt;= i &lt;= 255</code>, taken from the stack.\\nNotice that this primitive is one of the few ''exotic'' primitives, which are not polymorphic like stack manipulation primitives, and at the same time do not have well-defined types of parameters and return values, because the type of <code>x</code> depends on <code>i</code>.</p>\\n\",\"fift\":\"PUSHCTRX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"EDE0\",\"stack\":\"i - x\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_push_ctr_var\",\"line\":894,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"PUSHCTRX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"type\":\"variable\",\"var_name\":\"i\"}],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"EDE1\",\"tlb\":\"#EDE1\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Similar to <code>c[i] POPCTR</code>, but with <code>0 &lt;= i &lt;= 255</code> from the stack.</p>\\n\",\"fift\":\"POPCTRX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"EDE1\",\"stack\":\"x i - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_pop_ctr_var\",\"line\":904,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"POPCTRX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[{\"type\":\"variable\",\"var_name\":\"i\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"EDE2\",\"tlb\":\"#EDE2\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Similar to <code>c[i] SETCONTCTR</code>, but with <code>0 &lt;= i &lt;= 255</code> from the stack.</p>\\n\",\"fift\":\"SETCONTCTRX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"EDE2\",\"stack\":\"x c i - c'\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_setcont_ctr_var\",\"line\":914,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"SETCONTCTRX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":255,\"min_value\":0,\"name\":\"mask\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"EDE3\",\"tlb\":\"#EDE3 mask:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Takes continuation, performs the equivalent of <code>c[i] PUSHCTR SWAP c[i] SETCONTCNR</code> for each <code>i</code> that is set in <code>mask</code> (mask is in <code>0..255</code>).</p>\\n\",\"fift\":\"SETCONTCTRMANY\\nSETCONTMANY\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"EDE3mm\",\"stack\":\"c - c'\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_setcont_ctr_many\",\"line\":926,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/f58297f1b668c7b49e8b30b65062951ca7c18acc/crypto/vm/contops.cpp\"}],\"mnemonic\":\"SETCONTCTRMANY\",\"since_version\":9,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"EDE4\",\"tlb\":\"#EDE4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Takes continuation, performs the equivalent of <code>c[i] PUSHCTR SWAP c[i] SETCONTCNR</code> for each <code>i</code> that is set in <code>mask</code> (mask is in <code>0..255</code>).</p>\\n\",\"fift\":\"SETCONTCTRMANYX\\nSETCONTMANYX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"EDE4\",\"stack\":\"c mask - c'\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_setcont_ctr_many_var\",\"line\":943,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/f58297f1b668c7b49e8b30b65062951ca7c18acc/crypto/vm/contops.cpp\"}],\"mnemonic\":\"SETCONTCTRMANYX\",\"since_version\":9,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]},{\"name\":\"mask\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"EDF0\",\"tlb\":\"#EDF0\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Computes the composition <code>compose0(c, c')</code>, which has the meaning of ''perform <code>c</code>, and, if successful, perform <code>c'</code>'' (if <code>c</code> is a boolean circuit) or simply ''perform <code>c</code>, then <code>c'</code>''. Equivalent to <code>SWAP</code> <code>c0 SETCONT</code>.</p>\\n\",\"fift\":\"COMPOS\\nBOOLAND\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"EDF0\",\"stack\":\"c c' - c''\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_compos\",\"line\":961,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"COMPOS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]},{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c3\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"EDF1\",\"tlb\":\"#EDF1\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Computes the alternative composition <code>compose1(c, c')</code>, which has the meaning of ''perform <code>c</code>, and, if not successful, perform <code>c'</code>'' (if <code>c</code> is a boolean circuit). Equivalent to <code>SWAP</code> <code>c1 SETCONT</code>.</p>\\n\",\"fift\":\"COMPOSALT\\nBOOLOR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"EDF1\",\"stack\":\"c c' - c''\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_compos\",\"line\":961,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"COMPOSALT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]},{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c3\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"EDF2\",\"tlb\":\"#EDF2\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Computes composition <code>compose1(compose0(c, c'), c')</code>, which has the meaning of ''compute boolean circuit <code>c</code>, then compute <code>c'</code>, regardless of the result of <code>c</code>''.</p>\\n\",\"fift\":\"COMPOSBOTH\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"EDF2\",\"stack\":\"c c' - c''\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_compos\",\"line\":961,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"COMPOSBOTH\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]},{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c3\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"EDF3\",\"tlb\":\"#EDF3\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Sets <code>c0</code> to <code>compose0(c, c0)</code>. In other words, <code>c</code> will be executed before exiting current subroutine.</p>\\n\",\"fift\":\"ATEXIT\",\"fift_examples\":[{\"description\":\"Equivalent to `<{ code }> CONT` `ATEXIT`.\",\"fift\":\"ATEXIT:<{ code }> <{ code }>ATEXIT\"}],\"gas\":\"26\",\"opcode\":\"EDF3\",\"stack\":\"c - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_atexit\",\"line\":983,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"ATEXIT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":0,\"type\":\"constant\"}],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[{\"index\":0,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"EDF4\",\"tlb\":\"#EDF4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Sets <code>c1</code> to <code>compose1(c, c1)</code>. In other words, <code>c</code> will be executed before exiting current subroutine by its alternative return path.</p>\\n\",\"fift\":\"ATEXITALT\",\"fift_examples\":[{\"description\":\"Equivalent to `<{ code }> CONT` `ATEXITALT`.\",\"fift\":\"ATEXITALT:<{ code }> <{ code }>ATEXITALT\"}],\"gas\":\"26\",\"opcode\":\"EDF4\",\"stack\":\"c - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_atexit_alt\",\"line\":992,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"ATEXITALT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":1,\"type\":\"constant\"}],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[{\"index\":1,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"EDF5\",\"tlb\":\"#EDF5\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Sets <code>c1</code> to <code>compose1(compose0(c, c0), c1)</code>,\\nIn this way, a subsequent <code>RETALT</code> will first execute <code>c</code>, then transfer control to the original <code>c0</code>. This can be used, for instance, to exit from nested loops.</p>\\n\",\"fift\":\"SETEXITALT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"EDF5\",\"stack\":\"c - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_setexit_alt\",\"line\":1001,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"SETEXITALT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":0,\"type\":\"constant\"},{\"index\":1,\"type\":\"constant\"}],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[{\"index\":1,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"EDF6\",\"tlb\":\"#EDF6\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Computes <code>compose0(c, c0)</code>.</p>\\n\",\"fift\":\"THENRET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"EDF6\",\"stack\":\"c - c'\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_thenret\",\"line\":1011,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"THENRET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":0,\"type\":\"constant\"}],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"EDF7\",\"tlb\":\"#EDF7\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Computes <code>compose0(c, c1)</code></p>\\n\",\"fift\":\"THENRETALT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"EDF7\",\"stack\":\"c - c'\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_thenret_alt\",\"line\":1020,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"THENRETALT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":1,\"type\":\"constant\"}],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"EDF8\",\"tlb\":\"#EDF8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Interchanges <code>c0</code> and <code>c1</code>.</p>\\n\",\"fift\":\"INVERT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"EDF8\",\"stack\":\"-\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_invert\",\"line\":1029,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"INVERT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":0,\"type\":\"constant\"},{\"index\":1,\"type\":\"constant\"}],\"stack\":[]},\"outputs\":{\"registers\":[{\"index\":0,\"type\":\"constant\"},{\"index\":1,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"EDF9\",\"tlb\":\"#EDF9\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"args\":{\"next\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"},\"c1\":{\"index\":1,\"type\":\"register\"}},\"type\":\"cc\"},\"value\":-1},\"name\":\"pushint\",\"type\":\"special\"},\"c1\":{\"args\":{\"next\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"},\"c1\":{\"index\":1,\"type\":\"register\"}},\"type\":\"cc\"},\"value\":0},\"name\":\"pushint\",\"type\":\"special\"}},\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Performs <code>cc:=compose1(compose0(c, compose0(-1 PUSHINT, cc)), compose0(0 PUSHINT, cc))</code>. If <code>c</code> represents a boolean circuit, the net effect is to evaluate it and push either <code>-1</code> or <code>0</code> into the stack before continuing.</p>\\n\",\"fift\":\"BOOLEVAL\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"EDF9\",\"stack\":\"c - ?\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_booleval\",\"line\":1037,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"BOOLEVAL\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"EDFA\",\"tlb\":\"#EDFA\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Sets <code>c1</code> to <code>c0</code>. Equivalent to <code>c0 PUSHCTR</code> <code>c1 POPCTR</code>.</p>\\n\",\"fift\":\"SAMEALT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"EDFA\",\"stack\":\"-\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_samealt\",\"line\":862,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"SAMEALT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":0,\"type\":\"constant\"}],\"stack\":[]},\"outputs\":{\"registers\":[{\"index\":1,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"EDFB\",\"tlb\":\"#EDFB\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_registers\",\"description\":\"<p>Sets <code>c1</code> to <code>c0</code>, but first saves the old value of <code>c1</code> into the savelist of <code>c0</code>.\\nEquivalent to <code>c1 SAVE</code> <code>SAMEALT</code>.</p>\\n\",\"fift\":\"SAMEALTSAVE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"EDFB\",\"stack\":\"-\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_samealt\",\"line\":862,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"SAMEALTSAVE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":0,\"type\":\"constant\"},{\"index\":1,\"type\":\"constant\"}],\"stack\":[]},\"outputs\":{\"registers\":[{\"index\":0,\"type\":\"constant\"},{\"index\":1,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":255,\"min_value\":0,\"name\":\"n\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"F0\",\"tlb\":\"#F0 n:uint8\"},\"control_flow\":{\"branches\":[{\"index\":3,\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"register\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_dict\",\"description\":\"<p>Calls the continuation in <code>c3</code>, pushing integer <code>0 &lt;= nn &lt;= 255</code> into its stack as an argument.\\nApproximately equivalent to <code>[nn] PUSHINT</code> <code>c3 PUSHCTR</code> <code>EXECUTE</code>.</p>\\n\",\"fift\":\"[nn] CALL\\n[nn] CALLDICT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F0nn\",\"stack\":\"- nn\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_calldict_short\",\"line\":1092,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"CALLDICT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":16383,\"min_value\":0,\"name\":\"n\",\"size\":14,\"type\":\"uint\"}],\"prefix\":\"F12_\",\"tlb\":\"#F12_ n:uint14\"},\"control_flow\":{\"branches\":[{\"index\":3,\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"register\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_dict\",\"description\":\"<p>For <code>0 &lt;= n &lt; 2^14</code>, an encoding of <code>[n] CALL</code> for larger values of <code>n</code>.</p>\\n\",\"fift\":\"[n] CALL\\n[n] CALLDICT\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"F12_n\",\"stack\":\"- n\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_calldict\",\"line\":1099,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"CALLDICT_LONG\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":16383,\"min_value\":0,\"name\":\"n\",\"size\":14,\"type\":\"uint\"}],\"prefix\":\"F16_\",\"tlb\":\"#F16_ n:uint14\"},\"control_flow\":{\"branches\":[{\"index\":3,\"type\":\"register\"}],\"nobranch\":false},\"doc\":{\"category\":\"cont_dict\",\"description\":\"<p>Jumps to the continuation in <code>c3</code>, pushing integer <code>0 &lt;= n &lt; 2^14</code> as its argument.\\nApproximately equivalent to <code>n PUSHINT</code> <code>c3 PUSHCTR</code> <code>JMPX</code>.</p>\\n\",\"fift\":\"[n] JMP\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"F16_n\",\"stack\":\" - n\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_jmpdict\",\"line\":1106,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"JMPDICT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":16383,\"min_value\":0,\"name\":\"n\",\"size\":14,\"type\":\"uint\"}],\"prefix\":\"F1A_\",\"tlb\":\"#F1A_ n:uint14\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"cont_dict\",\"description\":\"<p>Equivalent to <code>n PUSHINT</code> <code>c3 PUSHCTR</code>, for <code>0 &lt;= n &lt; 2^14</code>.\\nIn this way, <code>[n] CALL</code> is approximately equivalent to <code>[n] PREPARE</code> <code>EXECUTE</code>, and <code>[n] JMP</code> is approximately equivalent to <code>[n] PREPARE</code> <code>JMPX</code>.\\nOne might use, for instance, <code>CALLXARGS</code> or <code>CALLCC</code> instead of <code>EXECUTE</code> here.</p>\\n\",\"fift\":\"[n] PREPARE\\n[n] PREPAREDICT\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"F1A_n\",\"stack\":\" - n c\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_preparedict\",\"line\":1113,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"PREPAREDICT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":3,\"type\":\"constant\"}],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":63,\"min_value\":0,\"name\":\"n\",\"size\":6,\"type\":\"uint\"}],\"prefix\":\"F22_\",\"tlb\":\"#F22_ n:uint6\"},\"control_flow\":{\"branches\":[],\"nobranch\":false},\"doc\":{\"category\":\"exceptions\",\"description\":\"<p>Throws exception <code>0 &lt;= n &lt;= 63</code> with parameter zero.\\nIn other words, it transfers control to the continuation in <code>c2</code>, pushing <code>0</code> and <code>n</code> into its stack, and discarding the old stack altogether.</p>\\n\",\"fift\":\"[n] THROW\",\"fift_examples\":[],\"gas\":\"76\",\"opcode\":\"F22_n\",\"stack\":\" - 0 n\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_throw_fixed\",\"line\":1130,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"THROW_SHORT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":63,\"min_value\":0,\"name\":\"n\",\"size\":6,\"type\":\"uint\"}],\"prefix\":\"F26_\",\"tlb\":\"#F26_ n:uint6\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"exceptions\",\"description\":\"<p>Throws exception <code>0 &lt;= n &lt;= 63</code> with  parameter zero only if integer <code>f!=0</code>.</p>\\n\",\"fift\":\"[n] THROWIF\",\"fift_examples\":[],\"gas\":\"26/76\",\"opcode\":\"F26_n\",\"stack\":\"f - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_throw_fixed\",\"line\":1130,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"THROWIF_SHORT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":63,\"min_value\":0,\"name\":\"n\",\"size\":6,\"type\":\"uint\"}],\"prefix\":\"F2A_\",\"tlb\":\"#F2A_ n:uint6\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"exceptions\",\"description\":\"<p>Throws exception <code>0 &lt;= n &lt;= 63</code> with parameter zero only if integer <code>f=0</code>.</p>\\n\",\"fift\":\"[n] THROWIFNOT\",\"fift_examples\":[],\"gas\":\"26/76\",\"opcode\":\"F2A_n\",\"stack\":\"f - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_throw_fixed\",\"line\":1130,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"THROWIFNOT_SHORT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":2047,\"min_value\":0,\"name\":\"n\",\"size\":11,\"type\":\"uint\"}],\"prefix\":\"F2C4_\",\"tlb\":\"#F2C4_ n:uint11\"},\"control_flow\":{\"branches\":[],\"nobranch\":false},\"doc\":{\"category\":\"exceptions\",\"description\":\"<p>For <code>0 &lt;= n &lt; 2^11</code>, an encoding of <code>[n] THROW</code> for larger values of <code>n</code>.</p>\\n\",\"fift\":\"[n] THROW\",\"fift_examples\":[],\"gas\":\"84\",\"opcode\":\"F2C4_n\",\"stack\":\"- 0 nn\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_throw_fixed\",\"line\":1130,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"THROW\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":2047,\"min_value\":0,\"name\":\"n\",\"size\":11,\"type\":\"uint\"}],\"prefix\":\"F2CC_\",\"tlb\":\"#F2CC_ n:uint11\"},\"control_flow\":{\"branches\":[],\"nobranch\":false},\"doc\":{\"category\":\"exceptions\",\"description\":\"<p>Throws exception <code>0 &lt;= n &lt;  2^11</code> with parameter <code>x</code>, by copying <code>x</code> and <code>n</code> into the stack of <code>c2</code> and transferring control to <code>c2</code>.</p>\\n\",\"fift\":\"[n] THROWARG\",\"fift_examples\":[],\"gas\":\"84\",\"opcode\":\"F2CC_n\",\"stack\":\"x - x nn\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_throw_arg_fixed\",\"line\":1140,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"THROWARG\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":2047,\"min_value\":0,\"name\":\"n\",\"size\":11,\"type\":\"uint\"}],\"prefix\":\"F2D4_\",\"tlb\":\"#F2D4_ n:uint11\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"exceptions\",\"description\":\"<p>For <code>0 &lt;= n &lt; 2^11</code>, an encoding of <code>[n] THROWIF</code> for larger values of <code>n</code>.</p>\\n\",\"fift\":\"[n] THROWIF\",\"fift_examples\":[],\"gas\":\"34/84\",\"opcode\":\"F2D4_n\",\"stack\":\"f - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_throw_fixed\",\"line\":1130,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"THROWIF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":2047,\"min_value\":0,\"name\":\"n\",\"size\":11,\"type\":\"uint\"}],\"prefix\":\"F2DC_\",\"tlb\":\"#F2DC_ n:uint11\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"exceptions\",\"description\":\"<p>Throws exception <code>0 &lt;= nn &lt; 2^11</code> with parameter <code>x</code> only if integer <code>f!=0</code>.</p>\\n\",\"fift\":\"[n] THROWARGIF\",\"fift_examples\":[],\"gas\":\"34/84\",\"opcode\":\"F2DC_n\",\"stack\":\"x f - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_throw_arg_fixed\",\"line\":1140,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"THROWARGIF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":2047,\"min_value\":0,\"name\":\"n\",\"size\":11,\"type\":\"uint\"}],\"prefix\":\"F2E4_\",\"tlb\":\"#F2E4_ n:uint11\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"exceptions\",\"description\":\"<p>For <code>0 &lt;= n &lt; 2^11</code>, an encoding of <code>[n] THROWIFNOT</code> for larger values of <code>n</code>.</p>\\n\",\"fift\":\"[n] THROWIFNOT\",\"fift_examples\":[],\"gas\":\"34/84\",\"opcode\":\"F2E4_n\",\"stack\":\"f - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_throw_fixed\",\"line\":1130,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"THROWIFNOT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":2047,\"min_value\":0,\"name\":\"n\",\"size\":11,\"type\":\"uint\"}],\"prefix\":\"F2EC_\",\"tlb\":\"#F2EC_ n:uint11\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"exceptions\",\"description\":\"<p>Throws exception <code>0 &lt;= n &lt; 2^11</code> with parameter <code>x</code> only if integer <code>f=0</code>.</p>\\n\",\"fift\":\"[n] THROWARGIFNOT\",\"fift_examples\":[],\"gas\":\"34/84\",\"opcode\":\"F2EC_n\",\"stack\":\"x f - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_throw_arg_fixed\",\"line\":1140,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"THROWARGIFNOT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F2F0\",\"tlb\":\"#F2F0\"},\"control_flow\":{\"branches\":[],\"nobranch\":false},\"doc\":{\"category\":\"exceptions\",\"description\":\"<p>Throws exception <code>0 &lt;= n &lt; 2^16</code> with parameter zero.\\nApproximately equivalent to <code>ZERO</code> <code>SWAP</code> <code>THROWARGANY</code>.</p>\\n\",\"fift\":\"THROWANY\",\"fift_examples\":[],\"gas\":\"76\",\"opcode\":\"F2F0\",\"stack\":\"n - 0 n\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_throw_any\",\"line\":1153,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"THROWANY\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F2F1\",\"tlb\":\"#F2F1\"},\"control_flow\":{\"branches\":[],\"nobranch\":false},\"doc\":{\"category\":\"exceptions\",\"description\":\"<p>Throws exception <code>0 &lt;= n &lt; 2^16</code> with parameter <code>x</code>, transferring control to the continuation in <code>c2</code>.\\nApproximately equivalent to <code>c2 PUSHCTR</code> <code>2 JMPXARGS</code>.</p>\\n\",\"fift\":\"THROWARGANY\",\"fift_examples\":[],\"gas\":\"76\",\"opcode\":\"F2F1\",\"stack\":\"x n - x n\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_throw_any\",\"line\":1153,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"THROWARGANY\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F2F2\",\"tlb\":\"#F2F2\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"exceptions\",\"description\":\"<p>Throws exception <code>0 &lt;= n &lt; 2^16</code> with parameter zero only if <code>f!=0</code>.</p>\\n\",\"fift\":\"THROWANYIF\",\"fift_examples\":[],\"gas\":\"26/76\",\"opcode\":\"F2F2\",\"stack\":\"n f - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_throw_any\",\"line\":1153,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"THROWANYIF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F2F3\",\"tlb\":\"#F2F3\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"exceptions\",\"description\":\"<p>Throws exception <code>0 &lt;= n&lt;2^16</code> with parameter <code>x</code> only if <code>f!=0</code>.</p>\\n\",\"fift\":\"THROWARGANYIF\",\"fift_examples\":[],\"gas\":\"26/76\",\"opcode\":\"F2F3\",\"stack\":\"x n f - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_throw_any\",\"line\":1153,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"THROWARGANYIF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F2F4\",\"tlb\":\"#F2F4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"exceptions\",\"description\":\"<p>Throws exception <code>0 &lt;= n&lt;2^16</code> with parameter zero only if <code>f=0</code>.</p>\\n\",\"fift\":\"THROWANYIFNOT\",\"fift_examples\":[],\"gas\":\"26/76\",\"opcode\":\"F2F4\",\"stack\":\"n f - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_throw_any\",\"line\":1153,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"THROWANYIFNOT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F2F5\",\"tlb\":\"#F2F5\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"exceptions\",\"description\":\"<p>Throws exception <code>0 &lt;= n&lt;2^16</code> with parameter <code>x</code> only if <code>f=0</code>.</p>\\n\",\"fift\":\"THROWARGANYIFNOT\",\"fift_examples\":[],\"gas\":\"26/76\",\"opcode\":\"F2F5\",\"stack\":\"x n f - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_throw_any\",\"line\":1153,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"THROWARGANYIFNOT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F2FF\",\"tlb\":\"#F2FF\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"},\"c1\":{\"index\":1,\"type\":\"register\"},\"c2\":{\"index\":2,\"type\":\"register\"}},\"type\":\"cc\"},\"c2\":{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"},\"c1\":{\"index\":1,\"type\":\"register\"},\"c2\":{\"index\":2,\"type\":\"register\"}},\"type\":\"cc\"},\"c2\":{\"index\":2,\"type\":\"register\"}},\"type\":\"variable\",\"var_name\":\"c2\"}},\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"exceptions\",\"description\":\"<p>Sets <code>c2</code> to <code>c'</code>, first saving the old value of <code>c2</code> both into the savelist of <code>c'</code> and into the savelist of the current continuation, which is stored into <code>c.c0</code> and <code>c'.c0</code>. Then runs <code>c</code> similarly to <code>EXECUTE</code>. If <code>c</code> does not throw any exceptions, the original value of <code>c2</code> is automatically restored on return from <code>c</code>. If an exception occurs, the execution is transferred to <code>c'</code>, but the original value of <code>c2</code> is restored in the process, so that <code>c'</code> can re-throw the exception by <code>THROWANY</code> if it cannot handle it by itself.</p>\\n\",\"fift\":\"TRY\",\"fift_examples\":[{\"description\":\"Equivalent to `<{ code1 }> CONT` `<{ code2 }> CONT` `TRY`.\",\"fift\":\"TRY:<{ code1 }>CATCH<{ code2 }>\"}],\"gas\":\"26\",\"opcode\":\"F2FF\",\"stack\":\"c c' - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_try\",\"line\":1186,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"TRY\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]},{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"p\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"r\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"F3\",\"tlb\":\"#F3 p:uint4 r:uint4\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"},\"c1\":{\"index\":1,\"type\":\"register\"},\"c2\":{\"index\":2,\"type\":\"register\"}},\"type\":\"cc\"},\"c2\":{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"},\"c1\":{\"index\":1,\"type\":\"register\"},\"c2\":{\"index\":2,\"type\":\"register\"}},\"type\":\"cc\"},\"c2\":{\"index\":2,\"type\":\"register\"}},\"type\":\"variable\",\"var_name\":\"c2\"}},\"type\":\"variable\",\"var_name\":\"c\"}],\"nobranch\":false},\"doc\":{\"category\":\"exceptions\",\"description\":\"<p>Similar to <code>TRY</code>, but with <code>[p] [r] CALLXARGS</code> internally used instead of <code>EXECUTE</code>.\\nIn this way, all but the top <code>0 &lt;= p &lt;= 15</code> stack elements will be saved into current continuation's stack, and then restored upon return from either <code>c</code> or <code>c'</code>, with the top <code>0 &lt;= r &lt;= 15</code> values of the resulting stack of <code>c</code> or <code>c'</code> copied as return values.</p>\\n\",\"fift\":\"[p] [r] TRYARGS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F3pr\",\"stack\":\"c c' - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_try\",\"line\":1186,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"TRYARGS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"arg\",\"type\":\"simple\"}],\"length_var\":\"r\",\"name\":\"args\",\"type\":\"array\"},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]},{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Continuation\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F400\",\"tlb\":\"#F400\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_serial\",\"description\":\"<p>Stores dictionary <code>D</code> into <em>Builder</em> <code>b</code>, returning the resulting <em>Builder</em> <code>b'</code>.\\nIn other words, if <code>D</code> is a cell, performs <code>STONE</code> and <code>STREF</code>; if <code>D</code> is <em>Null</em>, performs <code>NIP</code> and <code>STZERO</code>; otherwise throws a type checking exception.</p>\\n\",\"fift\":\"STDICT\\nSTOPTREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F400\",\"stack\":\"D b - b'\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_store_dict\",\"line\":53,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"STDICT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F401\",\"tlb\":\"#F401\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_serial\",\"description\":\"<p>Equivalent to <code>LDDICT</code> <code>NIP</code>.</p>\\n\",\"fift\":\"SKIPDICT\\nSKIPOPTREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F401\",\"stack\":\"s - s'\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_skip_dict\",\"line\":82,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"SKIPDICT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F402\",\"tlb\":\"#F402\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_serial\",\"description\":\"<p>Loads (parses) a (<em>Slice</em>-represented) dictionary <code>s'</code> from <em>Slice</em> <code>s</code>, and returns the remainder of <code>s</code> as <code>s''</code>.\\nThis is a ''split function'' for all <code>HashmapE(n,X)</code> dictionary types.</p>\\n\",\"fift\":\"LDDICTS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F402\",\"stack\":\"s - s' s''\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_load_dict_slice\",\"line\":121,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"LDDICTS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F403\",\"tlb\":\"#F403\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_serial\",\"description\":\"<p>Preloads a (<em>Slice</em>-represented) dictionary <code>s'</code> from <em>Slice</em> <code>s</code>.\\nApproximately equivalent to <code>LDDICTS</code> <code>DROP</code>.</p>\\n\",\"fift\":\"PLDDICTS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F403\",\"stack\":\"s - s'\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_load_dict_slice\",\"line\":121,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"PLDDICTS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F404\",\"tlb\":\"#F404\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_serial\",\"description\":\"<p>Loads (parses) a dictionary <code>D</code> from <em>Slice</em> <code>s</code>, and returns the remainder of <code>s</code> as <code>s'</code>. May be applied to dictionaries or to values of arbitrary <code>(^Y)?</code> types.</p>\\n\",\"fift\":\"LDDICT\\nLDOPTREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F404\",\"stack\":\"s - D s'\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_load_dict\",\"line\":148,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"LDDICT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F405\",\"tlb\":\"#F405\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_serial\",\"description\":\"<p>Preloads a dictionary <code>D</code> from <em>Slice</em> <code>s</code>.\\nApproximately equivalent to <code>LDDICT</code> <code>DROP</code>.</p>\\n\",\"fift\":\"PLDDICT\\nPLDOPTREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F405\",\"stack\":\"s - D\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_load_dict\",\"line\":148,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"PLDDICT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F406\",\"tlb\":\"#F406\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_serial\",\"description\":\"<p>A quiet version of <code>LDDICT</code>.</p>\\n\",\"fift\":\"LDDICTQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F406\",\"stack\":\"s - D s' -1 or s 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_load_dict\",\"line\":148,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"LDDICTQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":0},{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F407\",\"tlb\":\"#F407\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_serial\",\"description\":\"<p>A quiet version of <code>PLDDICT</code>.</p>\\n\",\"fift\":\"PLDDICTQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F407\",\"stack\":\"s - D -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_load_dict\",\"line\":148,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"PLDDICTQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F40A\",\"tlb\":\"#F40A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_get\",\"description\":\"<p>Looks up key <code>k</code> (represented by a <em>Slice</em>, the first <code>0 &lt;= n &lt;= 1023</code> data bits of which are used as a key) in dictionary <code>D</code> of type <code>HashmapE(n,X)</code> with <code>n</code>-bit keys.\\nOn success, returns the value found as a <em>Slice</em> <code>x</code>.</p>\\n\",\"fift\":\"DICTGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F40A\",\"stack\":\"k D n - x -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_get\",\"line\":207,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F40B\",\"tlb\":\"#F40B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_get\",\"description\":\"<p>Similar to <code>DICTGET</code>, but with a <code>LDREF</code> <code>ENDS</code> applied to <code>x</code> on success.\\nThis operation is useful for dictionaries of type <code>HashmapE(n,^Y)</code>.</p>\\n\",\"fift\":\"DICTGETREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F40B\",\"stack\":\"k D n - c -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_get_optref\",\"line\":247,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTGETREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F40C\",\"tlb\":\"#F40C\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_get\",\"description\":\"<p>Similar to <code>DICTGET</code>, but with a signed (big-endian) <code>n</code>-bit <em>Integer</em> <code>i</code> as a key. If <code>i</code> does not fit into <code>n</code> bits, returns <code>0</code>. If <code>i</code> is a <code>NaN</code>, throws an integer overflow exception.</p>\\n\",\"fift\":\"DICTIGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F40C\",\"stack\":\"i D n - x -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_get\",\"line\":207,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F40D\",\"tlb\":\"#F40D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_get\",\"description\":\"<p>Combines <code>DICTIGET</code> with <code>DICTGETREF</code>: it uses signed <code>n</code>-bit <em>Integer</em> <code>i</code> as a key and returns a <em>Cell</em> instead of a <em>Slice</em> on success.</p>\\n\",\"fift\":\"DICTIGETREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F40D\",\"stack\":\"i D n - c -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_get_optref\",\"line\":247,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIGETREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F40E\",\"tlb\":\"#F40E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_get\",\"description\":\"<p>Similar to <code>DICTIGET</code>, but with <em>unsigned</em> (big-endian) <code>n</code>-bit <em>Integer</em> <code>i</code> used as a key.</p>\\n\",\"fift\":\"DICTUGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F40E\",\"stack\":\"i D n - x -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_get\",\"line\":207,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F40F\",\"tlb\":\"#F40F\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_get\",\"description\":\"<p>Similar to <code>DICTIGETREF</code>, but with an unsigned <code>n</code>-bit <em>Integer</em> key <code>i</code>.</p>\\n\",\"fift\":\"DICTUGETREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F40F\",\"stack\":\"i D n - c -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_get_optref\",\"line\":247,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUGETREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F412\",\"tlb\":\"#F412\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p>Sets the value associated with <code>n</code>-bit key <code>k</code> (represented by a <em>Slice</em> as in <code>DICTGET</code>) in dictionary <code>D</code> (also represented by a <em>Slice</em>) to value <code>x</code> (again a <em>Slice</em>), and returns the resulting dictionary as <code>D'</code>.</p>\\n\",\"fift\":\"DICTSET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F412\",\"stack\":\"x k D n - D'\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTSET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F413\",\"tlb\":\"#F413\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p>Similar to <code>DICTSET</code>, but with the value set to a reference to <em>Cell</em> <code>c</code>.</p>\\n\",\"fift\":\"DICTSETREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F413\",\"stack\":\"c k D n - D'\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTSETREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F414\",\"tlb\":\"#F414\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p>Similar to <code>DICTSET</code>, but with the key represented by a (big-endian) signed <code>n</code>-bit integer <code>i</code>. If <code>i</code> does not fit into <code>n</code> bits, a range check exception is generated.</p>\\n\",\"fift\":\"DICTISET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F414\",\"stack\":\"x i D n - D'\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTISET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F415\",\"tlb\":\"#F415\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p>Similar to <code>DICTSETREF</code>, but with the key a signed <code>n</code>-bit integer as in <code>DICTISET</code>.</p>\\n\",\"fift\":\"DICTISETREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F415\",\"stack\":\"c i D n - D'\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTISETREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F416\",\"tlb\":\"#F416\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p>Similar to <code>DICTISET</code>, but with <code>i</code> an <em>unsigned</em> <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTUSET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F416\",\"stack\":\"x i D n - D'\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUSET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F417\",\"tlb\":\"#F417\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p>Similar to <code>DICTISETREF</code>, but with <code>i</code> unsigned.</p>\\n\",\"fift\":\"DICTUSETREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F417\",\"stack\":\"c i D n - D'\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUSETREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F41A\",\"tlb\":\"#F41A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p>Combines <code>DICTSET</code> with <code>DICTGET</code>: it sets the value corresponding to key <code>k</code> to <code>x</code>, but also returns the old value <code>y</code> associated with the key in question, if present.</p>\\n\",\"fift\":\"DICTSETGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F41A\",\"stack\":\"x k D n - D' y -1 or D' 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTSETGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F41B\",\"tlb\":\"#F41B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p>Combines <code>DICTSETREF</code> with <code>DICTGETREF</code> similarly to <code>DICTSETGET</code>.</p>\\n\",\"fift\":\"DICTSETGETREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F41B\",\"stack\":\"c k D n - D' c' -1 or D' 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTSETGETREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F41C\",\"tlb\":\"#F41C\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p><code>DICTISETGET</code>, but with <code>i</code> a signed <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTISETGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F41C\",\"stack\":\"x i D n - D' y -1 or D' 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTISETGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F41D\",\"tlb\":\"#F41D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p><code>DICTISETGETREF</code>, but with <code>i</code> a signed <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTISETGETREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F41D\",\"stack\":\"c i D n - D' c' -1 or D' 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTISETGETREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F41E\",\"tlb\":\"#F41E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p><code>DICTISETGET</code>, but with <code>i</code> an unsigned <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTUSETGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F41E\",\"stack\":\"x i D n - D' y -1 or D' 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUSETGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F41F\",\"tlb\":\"#F41F\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p><code>DICTISETGETREF</code>, but with <code>i</code> an unsigned <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTUSETGETREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F41F\",\"stack\":\"c i D n - D' c' -1 or D' 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUSETGETREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F422\",\"tlb\":\"#F422\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p>A <em>Replace</em> operation, which is similar to <code>DICTSET</code>, but sets the value of key <code>k</code> in dictionary <code>D</code> to <code>x</code> only if the key <code>k</code> was already present in <code>D</code>.</p>\\n\",\"fift\":\"DICTREPLACE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F422\",\"stack\":\"x k D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTREPLACE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F423\",\"tlb\":\"#F423\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p>A <em>Replace</em> counterpart of <code>DICTSETREF</code>.</p>\\n\",\"fift\":\"DICTREPLACEREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F423\",\"stack\":\"c k D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTREPLACEREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F424\",\"tlb\":\"#F424\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p><code>DICTREPLACE</code>, but with <code>i</code> a signed <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTIREPLACE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F424\",\"stack\":\"x i D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIREPLACE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F425\",\"tlb\":\"#F425\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p><code>DICTREPLACEREF</code>, but with <code>i</code> a signed <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTIREPLACEREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F425\",\"stack\":\"c i D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIREPLACEREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F426\",\"tlb\":\"#F426\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p><code>DICTREPLACE</code>, but with <code>i</code> an unsigned <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTUREPLACE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F426\",\"stack\":\"x i D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUREPLACE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F427\",\"tlb\":\"#F427\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p><code>DICTREPLACEREF</code>, but with <code>i</code> an unsigned <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTUREPLACEREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F427\",\"stack\":\"c i D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUREPLACEREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F42A\",\"tlb\":\"#F42A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p>A <em>Replace</em> counterpart of <code>DICTSETGET</code>: on success, also returns the old value associated with the key in question.</p>\\n\",\"fift\":\"DICTREPLACEGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F42A\",\"stack\":\"x k D n - D' y -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTREPLACEGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F42B\",\"tlb\":\"#F42B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p>A <em>Replace</em> counterpart of <code>DICTSETGETREF</code>.</p>\\n\",\"fift\":\"DICTREPLACEGETREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F42B\",\"stack\":\"c k D n - D' c' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTREPLACEGETREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F42C\",\"tlb\":\"#F42C\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p><code>DICTREPLACEGET</code>, but with <code>i</code> a signed <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTIREPLACEGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F42C\",\"stack\":\"x i D n - D' y -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIREPLACEGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F42D\",\"tlb\":\"#F42D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p><code>DICTREPLACEGETREF</code>, but with <code>i</code> a signed <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTIREPLACEGETREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F42D\",\"stack\":\"c i D n - D' c' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIREPLACEGETREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F42E\",\"tlb\":\"#F42E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p><code>DICTREPLACEGET</code>, but with <code>i</code> an unsigned <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTUREPLACEGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F42E\",\"stack\":\"x i D n - D' y -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUREPLACEGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F42F\",\"tlb\":\"#F42F\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p><code>DICTREPLACEGETREF</code>, but with <code>i</code> an unsigned <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTUREPLACEGETREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F42F\",\"stack\":\"c i D n - D' c' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUREPLACEGETREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F432\",\"tlb\":\"#F432\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p>An <em>Add</em> counterpart of <code>DICTSET</code>: sets the value associated with key <code>k</code> in dictionary <code>D</code> to <code>x</code>, but only if it is not already present in <code>D</code>.</p>\\n\",\"fift\":\"DICTADD\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F432\",\"stack\":\"x k D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTADD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F433\",\"tlb\":\"#F433\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p>An <em>Add</em> counterpart of <code>DICTSETREF</code>.</p>\\n\",\"fift\":\"DICTADDREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F433\",\"stack\":\"c k D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTADDREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F434\",\"tlb\":\"#F434\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p><code>DICTADD</code>, but with <code>i</code> a signed <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTIADD\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F434\",\"stack\":\"x i D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIADD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F435\",\"tlb\":\"#F435\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p><code>DICTADDREF</code>, but with <code>i</code> a signed <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTIADDREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F435\",\"stack\":\"c i D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIADDREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F436\",\"tlb\":\"#F436\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p><code>DICTADD</code>, but with <code>i</code> an unsigned <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTUADD\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F436\",\"stack\":\"x i D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUADD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F437\",\"tlb\":\"#F437\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p><code>DICTADDREF</code>, but with <code>i</code> an unsigned <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTUADDREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F437\",\"stack\":\"c i D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUADDREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F43A\",\"tlb\":\"#F43A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p>An <em>Add</em> counterpart of <code>DICTSETGET</code>: sets the value associated with key <code>k</code> in dictionary <code>D</code> to <code>x</code>, but only if key <code>k</code> is not already present in <code>D</code>. Otherwise, just returns the old value <code>y</code> without changing the dictionary.</p>\\n\",\"fift\":\"DICTADDGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F43A\",\"stack\":\"x k D n - D' -1 or D y 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTADDGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F43B\",\"tlb\":\"#F43B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p>An <em>Add</em> counterpart of <code>DICTSETGETREF</code>.</p>\\n\",\"fift\":\"DICTADDGETREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F43B\",\"stack\":\"c k D n - D' -1 or D c' 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTADDGETREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F43C\",\"tlb\":\"#F43C\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p><code>DICTADDGET</code>, but with <code>i</code> a signed <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTIADDGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F43C\",\"stack\":\"x i D n - D' -1 or D y 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIADDGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F43D\",\"tlb\":\"#F43D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p><code>DICTADDGETREF</code>, but with <code>i</code> a signed <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTIADDGETREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F43D\",\"stack\":\"c i D n - D' -1 or D c' 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIADDGETREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F43E\",\"tlb\":\"#F43E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p><code>DICTADDGET</code>, but with <code>i</code> an unsigned <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTUADDGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F43E\",\"stack\":\"x i D n - D' -1 or D y 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUADDGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F43F\",\"tlb\":\"#F43F\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set\",\"description\":\"<p><code>DICTADDGETREF</code>, but with <code>i</code> an unsigned <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTUADDGETREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F43F\",\"stack\":\"c i D n - D' -1 or D c' 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUADDGETREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F441\",\"tlb\":\"#F441\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set_builder\",\"description\":\"\",\"fift\":\"DICTSETB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F441\",\"stack\":\"b k D n - D'\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTSETB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F442\",\"tlb\":\"#F442\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set_builder\",\"description\":\"\",\"fift\":\"DICTISETB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F442\",\"stack\":\"b i D n - D'\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTISETB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F443\",\"tlb\":\"#F443\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set_builder\",\"description\":\"\",\"fift\":\"DICTUSETB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F443\",\"stack\":\"b i D n - D'\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUSETB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F445\",\"tlb\":\"#F445\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set_builder\",\"description\":\"\",\"fift\":\"DICTSETGETB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F445\",\"stack\":\"b k D n - D' y -1 or D' 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_setget\",\"line\":315,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTSETGETB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F446\",\"tlb\":\"#F446\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set_builder\",\"description\":\"\",\"fift\":\"DICTISETGETB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F446\",\"stack\":\"b i D n - D' y -1 or D' 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_setget\",\"line\":315,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTISETGETB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F447\",\"tlb\":\"#F447\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set_builder\",\"description\":\"\",\"fift\":\"DICTUSETGETB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F447\",\"stack\":\"b i D n - D' y -1 or D' 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_setget\",\"line\":315,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUSETGETB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F449\",\"tlb\":\"#F449\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set_builder\",\"description\":\"\",\"fift\":\"DICTREPLACEB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F449\",\"stack\":\"b k D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTREPLACEB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F44A\",\"tlb\":\"#F44A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set_builder\",\"description\":\"\",\"fift\":\"DICTIREPLACEB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F44A\",\"stack\":\"b i D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIREPLACEB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F44B\",\"tlb\":\"#F44B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set_builder\",\"description\":\"\",\"fift\":\"DICTUREPLACEB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F44B\",\"stack\":\"b i D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUREPLACEB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F44D\",\"tlb\":\"#F44D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set_builder\",\"description\":\"\",\"fift\":\"DICTREPLACEGETB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F44D\",\"stack\":\"b k D n - D' y -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_setget\",\"line\":315,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTREPLACEGETB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F44E\",\"tlb\":\"#F44E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set_builder\",\"description\":\"\",\"fift\":\"DICTIREPLACEGETB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F44E\",\"stack\":\"b i D n - D' y -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_setget\",\"line\":315,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIREPLACEGETB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F44F\",\"tlb\":\"#F44F\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set_builder\",\"description\":\"\",\"fift\":\"DICTUREPLACEGETB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F44F\",\"stack\":\"b i D n - D' y -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_setget\",\"line\":315,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUREPLACEGETB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F451\",\"tlb\":\"#F451\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set_builder\",\"description\":\"\",\"fift\":\"DICTADDB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F451\",\"stack\":\"b k D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTADDB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F452\",\"tlb\":\"#F452\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set_builder\",\"description\":\"\",\"fift\":\"DICTIADDB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F452\",\"stack\":\"b i D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIADDB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F453\",\"tlb\":\"#F453\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set_builder\",\"description\":\"\",\"fift\":\"DICTUADDB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F453\",\"stack\":\"b i D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_set\",\"line\":271,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUADDB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F455\",\"tlb\":\"#F455\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set_builder\",\"description\":\"\",\"fift\":\"DICTADDGETB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F455\",\"stack\":\"b k D n - D' -1 or D y 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_setget\",\"line\":315,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTADDGETB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F456\",\"tlb\":\"#F456\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set_builder\",\"description\":\"\",\"fift\":\"DICTIADDGETB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F456\",\"stack\":\"b i D n - D' -1 or D y 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_setget\",\"line\":315,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIADDGETB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F457\",\"tlb\":\"#F457\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_set_builder\",\"description\":\"\",\"fift\":\"DICTUADDGETB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F457\",\"stack\":\"b i D n - D' -1 or D y 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_setget\",\"line\":315,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUADDGETB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F459\",\"tlb\":\"#F459\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_delete\",\"description\":\"<p>Deletes <code>n</code>-bit key, represented by a <em>Slice</em> <code>k</code>, from dictionary <code>D</code>. If the key is present, returns the modified dictionary <code>D'</code> and the success flag <code>-1</code>. Otherwise, returns the original dictionary <code>D</code> and <code>0</code>.</p>\\n\",\"fift\":\"DICTDEL\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F459\",\"stack\":\"k D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_delete\",\"line\":374,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTDEL\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F45A\",\"tlb\":\"#F45A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_delete\",\"description\":\"<p>A version of <code>DICTDEL</code> with the key represented by a signed <code>n</code>-bit <em>Integer</em> <code>i</code>. If <code>i</code> does not fit into <code>n</code> bits, simply returns <code>D</code> <code>0</code> (''key not found, dictionary unmodified'').</p>\\n\",\"fift\":\"DICTIDEL\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F45A\",\"stack\":\"i D n - D' ?\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_delete\",\"line\":374,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIDEL\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F45B\",\"tlb\":\"#F45B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_delete\",\"description\":\"<p>Similar to <code>DICTIDEL</code>, but with <code>i</code> an unsigned <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTUDEL\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F45B\",\"stack\":\"i D n - D' ?\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_delete\",\"line\":374,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUDEL\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F462\",\"tlb\":\"#F462\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_delete\",\"description\":\"<p>Deletes <code>n</code>-bit key, represented by a <em>Slice</em> <code>k</code>, from dictionary <code>D</code>. If the key is present, returns the modified dictionary <code>D'</code>, the original value <code>x</code> associated with the key <code>k</code> (represented by a <em>Slice</em>), and the success flag <code>-1</code>. Otherwise, returns the original dictionary <code>D</code> and <code>0</code>.</p>\\n\",\"fift\":\"DICTDELGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F462\",\"stack\":\"k D n - D' x -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_deleteget\",\"line\":401,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTDELGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F463\",\"tlb\":\"#F463\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_delete\",\"description\":\"<p>Similar to <code>DICTDELGET</code>, but with <code>LDREF</code> <code>ENDS</code> applied to <code>x</code> on success, so that the value returned <code>c</code> is a <em>Cell</em>.</p>\\n\",\"fift\":\"DICTDELGETREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F463\",\"stack\":\"k D n - D' c -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_deleteget\",\"line\":401,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTDELGETREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F464\",\"tlb\":\"#F464\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_delete\",\"description\":\"<p><code>DICTDELGET</code>, but with <code>i</code> a signed <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTIDELGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F464\",\"stack\":\"i D n - D' x -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_deleteget\",\"line\":401,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIDELGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F465\",\"tlb\":\"#F465\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_delete\",\"description\":\"<p><code>DICTDELGETREF</code>, but with <code>i</code> a signed <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTIDELGETREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F465\",\"stack\":\"i D n - D' c -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_deleteget\",\"line\":401,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIDELGETREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F466\",\"tlb\":\"#F466\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_delete\",\"description\":\"<p><code>DICTDELGET</code>, but with <code>i</code> an unsigned <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTUDELGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F466\",\"stack\":\"i D n - D' x -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_deleteget\",\"line\":401,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUDELGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F467\",\"tlb\":\"#F467\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_delete\",\"description\":\"<p><code>DICTDELGETREF</code>, but with <code>i</code> an unsigned <code>n</code>-bit integer.</p>\\n\",\"fift\":\"DICTUDELGETREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F467\",\"stack\":\"i D n - D' c -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_deleteget\",\"line\":401,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUDELGETREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F469\",\"tlb\":\"#F469\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_mayberef\",\"description\":\"<p>A variant of <code>DICTGETREF</code> that returns <em>Null</em> instead of the value <code>c^?</code> if the key <code>k</code> is absent from dictionary <code>D</code>.</p>\\n\",\"fift\":\"DICTGETOPTREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F469\",\"stack\":\"k D n - c^?\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_get_optref\",\"line\":247,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTGETOPTREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F46A\",\"tlb\":\"#F46A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_mayberef\",\"description\":\"<p><code>DICTGETOPTREF</code>, but with <code>i</code> a signed <code>n</code>-bit integer. If the key <code>i</code> is out of range, also returns <em>Null</em>.</p>\\n\",\"fift\":\"DICTIGETOPTREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F46A\",\"stack\":\"i D n - c^?\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_get_optref\",\"line\":247,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIGETOPTREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F46B\",\"tlb\":\"#F46B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_mayberef\",\"description\":\"<p><code>DICTGETOPTREF</code>, but with <code>i</code> an unsigned <code>n</code>-bit integer. If the key <code>i</code> is out of range, also returns <em>Null</em>.</p>\\n\",\"fift\":\"DICTUGETOPTREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F46B\",\"stack\":\"i D n - c^?\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_get_optref\",\"line\":247,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUGETOPTREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F46D\",\"tlb\":\"#F46D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_mayberef\",\"description\":\"<p>A variant of both <code>DICTGETOPTREF</code> and <code>DICTSETGETREF</code> that sets the value corresponding to key <code>k</code> in dictionary <code>D</code> to <code>c^?</code> (if <code>c^?</code> is <em>Null</em>, then the key is deleted instead), and returns the old value <code>~c^?</code> (if the key <code>k</code> was absent before, returns <em>Null</em> instead).</p>\\n\",\"fift\":\"DICTSETGETOPTREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F46D\",\"stack\":\"c^? k D n - D' ~c^?\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_setget_optref\",\"line\":442,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTSETGETOPTREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F46E\",\"tlb\":\"#F46E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_mayberef\",\"description\":\"<p>Similar to primitive <code>DICTSETGETOPTREF</code>, but using signed <code>n</code>-bit <em>Integer</em> <code>i</code> as a key. If <code>i</code> does not fit into <code>n</code> bits, throws a range checking exception.</p>\\n\",\"fift\":\"DICTISETGETOPTREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F46E\",\"stack\":\"c^? i D n - D' ~c^?\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_setget_optref\",\"line\":442,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTISETGETOPTREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F46F\",\"tlb\":\"#F46F\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_mayberef\",\"description\":\"<p>Similar to primitive <code>DICTSETGETOPTREF</code>, but using unsigned <code>n</code>-bit <em>Integer</em> <code>i</code> as a key.</p>\\n\",\"fift\":\"DICTUSETGETOPTREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F46F\",\"stack\":\"c^? i D n - D' ~c^?\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_setget_optref\",\"line\":442,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUSETGETOPTREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"c2\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F470\",\"tlb\":\"#F470\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_prefix\",\"description\":\"\",\"fift\":\"PFXDICTSET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F470\",\"stack\":\"x k D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_pfx_dict_set\",\"line\":566,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"PFXDICTSET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F471\",\"tlb\":\"#F471\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_prefix\",\"description\":\"\",\"fift\":\"PFXDICTREPLACE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F471\",\"stack\":\"x k D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_pfx_dict_set\",\"line\":566,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"PFXDICTREPLACE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F472\",\"tlb\":\"#F472\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_prefix\",\"description\":\"\",\"fift\":\"PFXDICTADD\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F472\",\"stack\":\"x k D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_pfx_dict_set\",\"line\":566,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"PFXDICTADD\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F473\",\"tlb\":\"#F473\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_prefix\",\"description\":\"\",\"fift\":\"PFXDICTDEL\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F473\",\"stack\":\"k D n - D' -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_pfx_dict_delete\",\"line\":580,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"PFXDICTDEL\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F474\",\"tlb\":\"#F474\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_next\",\"description\":\"<p>Computes the minimal key <code>k'</code> in dictionary <code>D</code> that is lexicographically greater than <code>k</code>, and returns <code>k'</code> (represented by a <em>Slice</em>) along with associated value <code>x'</code> (also represented by a <em>Slice</em>).</p>\\n\",\"fift\":\"DICTGETNEXT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F474\",\"stack\":\"k D n - x' k' -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getnear\",\"line\":523,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTGETNEXT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F475\",\"tlb\":\"#F475\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_next\",\"description\":\"<p>Similar to <code>DICTGETNEXT</code>, but computes the minimal key <code>k'</code> that is lexicographically greater than or equal to <code>k</code>.</p>\\n\",\"fift\":\"DICTGETNEXTEQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F475\",\"stack\":\"k D n - x' k' -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getnear\",\"line\":523,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTGETNEXTEQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F476\",\"tlb\":\"#F476\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_next\",\"description\":\"<p>Similar to <code>DICTGETNEXT</code>, but computes the maximal key <code>k'</code> lexicographically smaller than <code>k</code>.</p>\\n\",\"fift\":\"DICTGETPREV\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F476\",\"stack\":\"k D n - x' k' -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getnear\",\"line\":523,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTGETPREV\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F477\",\"tlb\":\"#F477\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_next\",\"description\":\"<p>Similar to <code>DICTGETPREV</code>, but computes the maximal key <code>k'</code> lexicographically smaller than or equal to <code>k</code>.</p>\\n\",\"fift\":\"DICTGETPREVEQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F477\",\"stack\":\"k D n - x' k' -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getnear\",\"line\":523,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTGETPREVEQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F478\",\"tlb\":\"#F478\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_next\",\"description\":\"<p>Similar to <code>DICTGETNEXT</code>, but interprets all keys in dictionary <code>D</code> as big-endian signed <code>n</code>-bit integers, and computes the minimal key <code>i'</code> that is larger than <em>Integer</em> <code>i</code> (which does not necessarily fit into <code>n</code> bits).</p>\\n\",\"fift\":\"DICTIGETNEXT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F478\",\"stack\":\"i D n - x' i' -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getnear\",\"line\":523,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIGETNEXT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F479\",\"tlb\":\"#F479\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_next\",\"description\":\"<p>Similar to <code>DICTGETNEXTEQ</code>, but interprets keys as signed <code>n</code>-bit integers.</p>\\n\",\"fift\":\"DICTIGETNEXTEQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F479\",\"stack\":\"i D n - x' i' -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getnear\",\"line\":523,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIGETNEXTEQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F47A\",\"tlb\":\"#F47A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_next\",\"description\":\"<p>Similar to <code>DICTGETPREV</code>, but interprets keys as signed <code>n</code>-bit integers.</p>\\n\",\"fift\":\"DICTIGETPREV\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F47A\",\"stack\":\"i D n - x' i' -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getnear\",\"line\":523,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIGETPREV\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F47B\",\"tlb\":\"#F47B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_next\",\"description\":\"<p>Similar to <code>DICTGETPREVEQ</code>, but interprets keys as signed <code>n</code>-bit integers.</p>\\n\",\"fift\":\"DICTIGETPREVEQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F47B\",\"stack\":\"i D n - x' i' -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getnear\",\"line\":523,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIGETPREVEQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F47C\",\"tlb\":\"#F47C\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_next\",\"description\":\"<p>Similar to <code>DICTGETNEXT</code>, but interprets all keys in dictionary <code>D</code> as big-endian unsigned <code>n</code>-bit integers, and computes the minimal key <code>i'</code> that is larger than <em>Integer</em> <code>i</code> (which does not necessarily fit into <code>n</code> bits, and is not necessarily non-negative).</p>\\n\",\"fift\":\"DICTUGETNEXT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F47C\",\"stack\":\"i D n - x' i' -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getnear\",\"line\":523,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUGETNEXT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F47D\",\"tlb\":\"#F47D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_next\",\"description\":\"<p>Similar to <code>DICTGETNEXTEQ</code>, but interprets keys as unsigned <code>n</code>-bit integers.</p>\\n\",\"fift\":\"DICTUGETNEXTEQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F47D\",\"stack\":\"i D n - x' i' -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getnear\",\"line\":523,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUGETNEXTEQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F47E\",\"tlb\":\"#F47E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_next\",\"description\":\"<p>Similar to <code>DICTGETPREV</code>, but interprets keys as unsigned <code>n</code>-bit integers.</p>\\n\",\"fift\":\"DICTUGETPREV\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F47E\",\"stack\":\"i D n - x' i' -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getnear\",\"line\":523,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUGETPREV\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F47F\",\"tlb\":\"#F47F\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_next\",\"description\":\"<p>Similar to <code>DICTGETPREVEQ</code>, but interprets keys a unsigned <code>n</code>-bit integers.</p>\\n\",\"fift\":\"DICTUGETPREVEQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F47F\",\"stack\":\"i D n - x' i' -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getnear\",\"line\":523,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUGETPREVEQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F482\",\"tlb\":\"#F482\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Computes the minimal key <code>k</code> (represented by a <em>Slice</em> with <code>n</code> data bits) in dictionary <code>D</code>, and returns <code>k</code> along with the associated value <code>x</code>.</p>\\n\",\"fift\":\"DICTMIN\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F482\",\"stack\":\"D n - x k -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTMIN\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F483\",\"tlb\":\"#F483\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Similar to <code>DICTMIN</code>, but returns the only reference in the value as a <em>Cell</em> <code>c</code>.</p>\\n\",\"fift\":\"DICTMINREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F483\",\"stack\":\"D n - c k -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTMINREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F484\",\"tlb\":\"#F484\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Similar to <code>DICTMIN</code>, but computes the minimal key <code>i</code> under the assumption that all keys are big-endian signed <code>n</code>-bit integers. Notice that the key and value returned may differ from those computed by <code>DICTMIN</code> and <code>DICTUMIN</code>.</p>\\n\",\"fift\":\"DICTIMIN\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F484\",\"stack\":\"D n - x i -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIMIN\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F485\",\"tlb\":\"#F485\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Similar to <code>DICTIMIN</code>, but returns the only reference in the value.</p>\\n\",\"fift\":\"DICTIMINREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F485\",\"stack\":\"D n - c i -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIMINREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F486\",\"tlb\":\"#F486\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Similar to <code>DICTMIN</code>, but returns the key as an unsigned <code>n</code>-bit <em>Integer</em> <code>i</code>.</p>\\n\",\"fift\":\"DICTUMIN\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F486\",\"stack\":\"D n - x i -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUMIN\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F487\",\"tlb\":\"#F487\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Similar to <code>DICTUMIN</code>, but returns the only reference in the value.</p>\\n\",\"fift\":\"DICTUMINREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F487\",\"stack\":\"D n - c i -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUMINREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F48A\",\"tlb\":\"#F48A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Computes the maximal key <code>k</code> (represented by a <em>Slice</em> with <code>n</code> data bits) in dictionary <code>D</code>, and returns <code>k</code> along with the associated value <code>x</code>.</p>\\n\",\"fift\":\"DICTMAX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F48A\",\"stack\":\"D n - x k -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTMAX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F48B\",\"tlb\":\"#F48B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Similar to <code>DICTMAX</code>, but returns the only reference in the value.</p>\\n\",\"fift\":\"DICTMAXREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F48B\",\"stack\":\"D n - c k -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTMAXREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F48C\",\"tlb\":\"#F48C\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Similar to <code>DICTMAX</code>, but computes the maximal key <code>i</code> under the assumption that all keys are big-endian signed <code>n</code>-bit integers. Notice that the key and value returned may differ from those computed by <code>DICTMAX</code> and <code>DICTUMAX</code>.</p>\\n\",\"fift\":\"DICTIMAX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F48C\",\"stack\":\"D n - x i -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIMAX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F48D\",\"tlb\":\"#F48D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Similar to <code>DICTIMAX</code>, but returns the only reference in the value.</p>\\n\",\"fift\":\"DICTIMAXREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F48D\",\"stack\":\"D n - c i -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIMAXREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F48E\",\"tlb\":\"#F48E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Similar to <code>DICTMAX</code>, but returns the key as an unsigned <code>n</code>-bit <em>Integer</em> <code>i</code>.</p>\\n\",\"fift\":\"DICTUMAX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F48E\",\"stack\":\"D n - x i -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUMAX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F48F\",\"tlb\":\"#F48F\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Similar to <code>DICTUMAX</code>, but returns the only reference in the value.</p>\\n\",\"fift\":\"DICTUMAXREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F48F\",\"stack\":\"D n - c i -1 or 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUMAXREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F492\",\"tlb\":\"#F492\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Computes the minimal key <code>k</code> (represented by a <em>Slice</em> with <code>n</code> data bits) in dictionary <code>D</code>, removes <code>k</code> from the dictionary, and returns <code>k</code> along with the associated value <code>x</code> and the modified dictionary <code>D'</code>.</p>\\n\",\"fift\":\"DICTREMMIN\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F492\",\"stack\":\"D n - D' x k -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTREMMIN\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F493\",\"tlb\":\"#F493\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Similar to <code>DICTREMMIN</code>, but returns the only reference in the value as a <em>Cell</em> <code>c</code>.</p>\\n\",\"fift\":\"DICTREMMINREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F493\",\"stack\":\"D n - D' c k -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTREMMINREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F494\",\"tlb\":\"#F494\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Similar to <code>DICTREMMIN</code>, but computes the minimal key <code>i</code> under the assumption that all keys are big-endian signed <code>n</code>-bit integers. Notice that the key and value returned may differ from those computed by <code>DICTREMMIN</code> and <code>DICTUREMMIN</code>.</p>\\n\",\"fift\":\"DICTIREMMIN\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F494\",\"stack\":\"D n - D' x i -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIREMMIN\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F495\",\"tlb\":\"#F495\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Similar to <code>DICTIREMMIN</code>, but returns the only reference in the value.</p>\\n\",\"fift\":\"DICTIREMMINREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F495\",\"stack\":\"D n - D' c i -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIREMMINREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F496\",\"tlb\":\"#F496\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Similar to <code>DICTREMMIN</code>, but returns the key as an unsigned <code>n</code>-bit <em>Integer</em> <code>i</code>.</p>\\n\",\"fift\":\"DICTUREMMIN\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F496\",\"stack\":\"D n - D' x i -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUREMMIN\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F497\",\"tlb\":\"#F497\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Similar to <code>DICTUREMMIN</code>, but returns the only reference in the value.</p>\\n\",\"fift\":\"DICTUREMMINREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F497\",\"stack\":\"D n - D' c i -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUREMMINREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F49A\",\"tlb\":\"#F49A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Computes the maximal key <code>k</code> (represented by a <em>Slice</em> with <code>n</code> data bits) in dictionary <code>D</code>, removes <code>k</code> from the dictionary, and returns <code>k</code> along with the associated value <code>x</code> and the modified dictionary <code>D'</code>.</p>\\n\",\"fift\":\"DICTREMMAX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F49A\",\"stack\":\"D n - D' x k -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTREMMAX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F49B\",\"tlb\":\"#F49B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Similar to <code>DICTREMMAX</code>, but returns the only reference in the value as a <em>Cell</em> <code>c</code>.</p>\\n\",\"fift\":\"DICTREMMAXREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F49B\",\"stack\":\"D n - D' c k -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTREMMAXREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F49C\",\"tlb\":\"#F49C\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Similar to <code>DICTREMMAX</code>, but computes the minimal key <code>i</code> under the assumption that all keys are big-endian signed <code>n</code>-bit integers. Notice that the key and value returned may differ from those computed by <code>DICTREMMAX</code> and <code>DICTUREMMAX</code>.</p>\\n\",\"fift\":\"DICTIREMMAX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F49C\",\"stack\":\"D n - D' x i -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIREMMAX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F49D\",\"tlb\":\"#F49D\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Similar to <code>DICTIREMMAX</code>, but returns the only reference in the value.</p>\\n\",\"fift\":\"DICTIREMMAXREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F49D\",\"stack\":\"D n - D' c i -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIREMMAXREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F49E\",\"tlb\":\"#F49E\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Similar to <code>DICTREMMAX</code>, but returns the key as an unsigned <code>n</code>-bit <em>Integer</em> <code>i</code>.</p>\\n\",\"fift\":\"DICTUREMMAX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F49E\",\"stack\":\"D n - D' x i -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUREMMAX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F49F\",\"tlb\":\"#F49F\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_min\",\"description\":\"<p>Similar to <code>DICTUREMMAX</code>, but returns the only reference in the value.</p>\\n\",\"fift\":\"DICTUREMMAXREF\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F49F\",\"stack\":\"D n - D' c i -1 or D 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_getmin\",\"line\":470,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUREMMAXREF\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}],\"value\":0},{\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F4A0\",\"tlb\":\"#F4A0\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"x\"}],\"nobranch\":false},\"doc\":{\"category\":\"dict_special\",\"description\":\"<p>Similar to <code>DICTIGET</code>, but with <code>x</code> <code>BLESS</code>ed into a continuation with a subsequent <code>JMPX</code> to it on success. On failure, does nothing. This is useful for implementing <code>switch</code>/<code>case</code> constructions.</p>\\n\",\"fift\":\"DICTIGETJMP\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F4A0\",\"stack\":\"i D n - \"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_get_exec\",\"line\":593,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIGETJMP\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F4A1\",\"tlb\":\"#F4A1\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"x\"}],\"nobranch\":false},\"doc\":{\"category\":\"dict_special\",\"description\":\"<p>Similar to <code>DICTIGETJMP</code>, but performs <code>DICTUGET</code> instead of <code>DICTIGET</code>.</p>\\n\",\"fift\":\"DICTUGETJMP\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F4A1\",\"stack\":\"i D n - \"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_get_exec\",\"line\":593,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUGETJMP\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F4A2\",\"tlb\":\"#F4A2\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"x\"}],\"nobranch\":false},\"doc\":{\"category\":\"dict_special\",\"description\":\"<p>Similar to <code>DICTIGETJMP</code>, but with <code>EXECUTE</code> instead of <code>JMPX</code>.</p>\\n\",\"fift\":\"DICTIGETEXEC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F4A2\",\"stack\":\"i D n - \"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_get_exec\",\"line\":593,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIGETEXEC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F4A3\",\"tlb\":\"#F4A3\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"x\"}],\"nobranch\":false},\"doc\":{\"category\":\"dict_special\",\"description\":\"<p>Similar to <code>DICTUGETJMP</code>, but with <code>EXECUTE</code> instead of <code>JMPX</code>.</p>\\n\",\"fift\":\"DICTUGETEXEC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F4A3\",\"stack\":\"i D n - \"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_get_exec\",\"line\":593,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUGETEXEC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"size_var\":\"n\",\"type\":\"dictionary\"}],\"name\":\"d\",\"type\":\"ref\"},{\"display_hints\":[],\"max_value\":1023,\"min_value\":0,\"name\":\"n\",\"size\":10,\"type\":\"uint\"}],\"prefix\":\"F4A6_\",\"tlb\":\"#F4A6_ d:^Cell n:uint10\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_special\",\"description\":\"<p>Pushes a non-empty constant dictionary <code>D</code> (as a <code>Cell^?</code>) along with its key length <code>0 &lt;= n &lt;= 1023</code>, stored as a part of the instruction. The dictionary itself is created from the first of remaining references of the current continuation. In this way, the complete <code>DICTPUSHCONST</code> instruction can be obtained by first serializing <code>xF4A4_</code>, then the non-empty dictionary itself (one <code>1</code> bit and a cell reference), and then the unsigned 10-bit integer <code>n</code> (as if by a <code>STU 10</code> instruction). An empty dictionary can be pushed by a <code>NEWDICT</code> primitive instead.</p>\\n\",\"fift\":\"[ref] [n] DICTPUSHCONST\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"F4A6_n\",\"stack\":\" - D n\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_push_const_dict\",\"line\":620,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTPUSHCONST\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F4A8\",\"tlb\":\"#F4A8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_special\",\"description\":\"<p>Looks up the unique prefix of <em>Slice</em> <code>s</code> present in the prefix code dictionary represented by <code>Cell^?</code> <code>D</code> and <code>0 &lt;= n &lt;= 1023</code>. If found, the prefix of <code>s</code> is returned as <code>s'</code>, and the corresponding value (also a <em>Slice</em>) as <code>x</code>. The remainder of <code>s</code> is returned as a <em>Slice</em> <code>s''</code>. If no prefix of <code>s</code> is a key in prefix code dictionary <code>D</code>, returns the unchanged <code>s</code> and a zero flag to indicate failure.</p>\\n\",\"fift\":\"PFXDICTGETQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F4A8\",\"stack\":\"s D n - s' x s'' -1 or s 0\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_pfx_dict_get\",\"line\":658,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"PFXDICTGETQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F4A9\",\"tlb\":\"#F4A9\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_special\",\"description\":\"<p>Similar to <code>PFXDICTGET</code>, but throws a cell deserialization failure exception on failure.</p>\\n\",\"fift\":\"PFXDICTGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F4A9\",\"stack\":\"s D n - s' x s''\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_pfx_dict_get\",\"line\":658,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"PFXDICTGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F4AA\",\"tlb\":\"#F4AA\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"x\"}],\"nobranch\":false},\"doc\":{\"category\":\"dict_special\",\"description\":\"<p>Similar to <code>PFXDICTGETQ</code>, but on success <code>BLESS</code>es the value <code>x</code> into a <em>Continuation</em> and transfers control to it as if by a <code>JMPX</code>. On failure, returns <code>s</code> unchanged and continues execution.</p>\\n\",\"fift\":\"PFXDICTGETJMP\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F4AA\",\"stack\":\"s D n - s' s'' or s\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_pfx_dict_get\",\"line\":658,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"PFXDICTGETJMP\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F4AB\",\"tlb\":\"#F4AB\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"x\"}],\"nobranch\":false},\"doc\":{\"category\":\"dict_special\",\"description\":\"<p>Similar to <code>PFXDICTGETJMP</code>, but <code>EXEC</code>utes the continuation found instead of jumping to it. On failure, throws a cell deserialization exception.</p>\\n\",\"fift\":\"PFXDICTGETEXEC\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F4AB\",\"stack\":\"s D n - s' s''\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_pfx_dict_get\",\"line\":658,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"PFXDICTGETEXEC\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"size_var\":\"n\",\"type\":\"dictionary\"}],\"name\":\"d\",\"type\":\"ref\"},{\"display_hints\":[],\"max_value\":1023,\"min_value\":0,\"name\":\"n\",\"size\":10,\"type\":\"uint\"}],\"prefix\":\"F4AE_\",\"tlb\":\"#F4AE_ d:^Cell n:uint10\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"x\"}],\"nobranch\":false},\"doc\":{\"category\":\"dict_special\",\"description\":\"<p>Combines <code>[n] DICTPUSHCONST</code> for <code>0 &lt;= n &lt;= 1023</code> with <code>PFXDICTGETJMP</code>.</p>\\n\",\"fift\":\"[ref] [n] PFXDICTCONSTGETJMP\\n[ref] [n] PFXDICTSWITCH\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"F4AE_n\",\"stack\":\"s - s' s'' or s\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_const_pfx_dict_switch\",\"line\":692,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"PFXDICTCONSTGETJMP\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F4BC\",\"tlb\":\"#F4BC\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"x\"}],\"nobranch\":false},\"doc\":{\"category\":\"dict_special\",\"description\":\"<p>A variant of <code>DICTIGETJMP</code> that returns index <code>i</code> on failure.</p>\\n\",\"fift\":\"DICTIGETJMPZ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F4BC\",\"stack\":\"i D n - i or nothing\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_get_exec\",\"line\":593,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIGETJMPZ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F4BD\",\"tlb\":\"#F4BD\"},\"control_flow\":{\"branches\":[{\"type\":\"variable\",\"var_name\":\"x\"}],\"nobranch\":false},\"doc\":{\"category\":\"dict_special\",\"description\":\"<p>A variant of <code>DICTUGETJMP</code> that returns index <code>i</code> on failure.</p>\\n\",\"fift\":\"DICTUGETJMPZ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F4BD\",\"stack\":\"i D n - i or nothing\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_get_exec\",\"line\":593,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUGETJMPZ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F4BE\",\"tlb\":\"#F4BE\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"x\"}],\"nobranch\":false},\"doc\":{\"category\":\"dict_special\",\"description\":\"<p>A variant of <code>DICTIGETEXEC</code> that returns index <code>i</code> on failure.</p>\\n\",\"fift\":\"DICTIGETEXECZ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F4BE\",\"stack\":\"i D n - i or nothing\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_get_exec\",\"line\":593,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTIGETEXECZ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F4BF\",\"tlb\":\"#F4BF\"},\"control_flow\":{\"branches\":[{\"save\":{\"c0\":{\"save\":{\"c0\":{\"index\":0,\"type\":\"register\"}},\"type\":\"cc\"}},\"type\":\"variable\",\"var_name\":\"x\"}],\"nobranch\":false},\"doc\":{\"category\":\"dict_special\",\"description\":\"<p>A variant of <code>DICTUGETEXEC</code> that returns index <code>i</code> on failure.</p>\\n\",\"fift\":\"DICTUGETEXECZ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F4BF\",\"stack\":\"i D n - i or nothing\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_dict_get_exec\",\"line\":593,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"DICTUGETEXECZ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[]},\"outputs\":{\"registers\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F4B1\",\"tlb\":\"#F4B1\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_sub\",\"description\":\"<p>Constructs a subdictionary consisting of all keys beginning with prefix <code>k</code> (represented by a <em>Slice</em>, the first <code>0 &lt;= l &lt;= n &lt;= 1023</code> data bits of which are used as a key) of length <code>l</code> in dictionary <code>D</code> of type <code>HashmapE(n,X)</code> with <code>n</code>-bit keys. On success, returns the new subdictionary of the same type <code>HashmapE(n,X)</code> as a <em>Slice</em> <code>D'</code>.</p>\\n\",\"fift\":\"SUBDICTGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F4B1\",\"stack\":\"k l D n - D'\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_subdict_get\",\"line\":722,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"SUBDICTGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F4B2\",\"tlb\":\"#F4B2\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_sub\",\"description\":\"<p>Variant of <code>SUBDICTGET</code> with the prefix represented by a signed big-endian <code>l</code>-bit <em>Integer</em> <code>x</code>, where necessarily <code>l &lt;= 257</code>.</p>\\n\",\"fift\":\"SUBDICTIGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F4B2\",\"stack\":\"x l D n - D'\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_subdict_get\",\"line\":722,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"SUBDICTIGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F4B3\",\"tlb\":\"#F4B3\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_sub\",\"description\":\"<p>Variant of <code>SUBDICTGET</code> with the prefix represented by an unsigned big-endian <code>l</code>-bit <em>Integer</em> <code>x</code>, where necessarily <code>l &lt;= 256</code>.</p>\\n\",\"fift\":\"SUBDICTUGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F4B3\",\"stack\":\"x l D n - D'\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_subdict_get\",\"line\":722,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"SUBDICTUGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F4B5\",\"tlb\":\"#F4B5\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_sub\",\"description\":\"<p>Similar to <code>SUBDICTGET</code>, but removes the common prefix <code>k</code> from all keys of the new dictionary <code>D'</code>, which becomes of type <code>HashmapE(n-l,X)</code>.</p>\\n\",\"fift\":\"SUBDICTRPGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F4B5\",\"stack\":\"k l D n - D'\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_subdict_get\",\"line\":722,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"SUBDICTRPGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F4B6\",\"tlb\":\"#F4B6\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_sub\",\"description\":\"<p>Variant of <code>SUBDICTRPGET</code> with the prefix represented by a signed big-endian <code>l</code>-bit <em>Integer</em> <code>x</code>, where necessarily <code>l &lt;= 257</code>.</p>\\n\",\"fift\":\"SUBDICTIRPGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F4B6\",\"stack\":\"x l D n - D'\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_subdict_get\",\"line\":722,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"SUBDICTIRPGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F4B7\",\"tlb\":\"#F4B7\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"dict_sub\",\"description\":\"<p>Variant of <code>SUBDICTRPGET</code> with the prefix represented by an unsigned big-endian <code>l</code>-bit <em>Integer</em> <code>x</code>, where necessarily <code>l &lt;= 256</code>.</p>\\n\",\"fift\":\"SUBDICTURPGET\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F4B7\",\"stack\":\"x l D n - D'\"},\"implementation\":[{\"file\":\"dictops.cpp\",\"function_name\":\"exec_subdict_get\",\"line\":722,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/dictops.cpp\"}],\"mnemonic\":\"SUBDICTURPGET\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"l\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"D2\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F800\",\"tlb\":\"#F800\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_gas\",\"description\":\"<p>Sets current gas limit <code>g_l</code> to its maximal allowed value <code>g_m</code>, and resets the gas credit <code>g_c</code> to zero, decreasing the value of <code>g_r</code> by <code>g_c</code> in the process.\\nIn other words, the current smart contract agrees to buy some gas to finish the current transaction. This action is required to process external messages, which bring no value (hence no gas) with themselves.</p>\\n\",\"fift\":\"ACCEPT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F800\",\"stack\":\"-\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_accept\",\"line\":81,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"ACCEPT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"name\":\"gas\",\"type\":\"special\"}],\"stack\":[]},\"outputs\":{\"registers\":[{\"name\":\"gas\",\"type\":\"special\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F801\",\"tlb\":\"#F801\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_gas\",\"description\":\"<p>Sets current gas limit <code>g_l</code> to the minimum of <code>g</code> and <code>g_m</code>, and resets the gas credit <code>g_c</code> to zero. If the gas consumed so far (including the present instruction) exceeds the resulting value of <code>g_l</code>, an (unhandled) out of gas exception is thrown before setting new gas limits. Notice that <code>SETGASLIMIT</code> with an argument <code>g &gt;= 2^63-1</code> is equivalent to <code>ACCEPT</code>.</p>\\n\",\"fift\":\"SETGASLIMIT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F801\",\"stack\":\"g - \"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_set_gas_limit\",\"line\":86,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"SETGASLIMIT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"name\":\"gas\",\"type\":\"special\"}],\"stack\":[{\"name\":\"g\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[{\"name\":\"gas\",\"type\":\"special\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F807\",\"tlb\":\"#F807\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_gas\",\"description\":\"<p>Returns gas consumed by VM so far (including this instruction).</p>\\n\",\"fift\":\"GASCONSUMED\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F807\",\"stack\":\"- g_c\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_gas_consumed\",\"line\":96,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"GASCONSUMED\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[{\"name\":\"gas\",\"type\":\"special\"}],\"stack\":[{\"name\":\"g_c\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F80F\",\"tlb\":\"#F80F\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_gas\",\"description\":\"<p>Commits the current state of registers <code>c4</code> (''persistent data'') and <code>c5</code> (''actions'') so that the current execution is considered ''successful'' with the saved values even if an exception is thrown later.</p>\\n\",\"fift\":\"COMMIT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F80F\",\"stack\":\"-\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_commit\",\"line\":102,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"COMMIT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":4,\"type\":\"constant\"},{\"index\":5,\"type\":\"constant\"}],\"stack\":[]},\"outputs\":{\"registers\":[{\"name\":\"cstate\",\"type\":\"special\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F810\",\"tlb\":\"#F810\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_rnd\",\"description\":\"<p>Generates a new pseudo-random unsigned 256-bit <em>Integer</em> <code>x</code>. The algorithm is as follows: if <code>r</code> is the old value of the random seed, considered as a 32-byte array (by constructing the big-endian representation of an unsigned 256-bit integer), then its <code>sha512(r)</code> is computed; the first 32 bytes of this hash are stored as the new value <code>r'</code> of the random seed, and the remaining 32 bytes are returned as the next random value <code>x</code>.</p>\\n\",\"fift\":\"RANDU256\",\"fift_examples\":[],\"gas\":\"26+|c7|+|c1_1|\",\"opcode\":\"F810\",\"stack\":\"- x\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_randu256\",\"line\":542,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"RANDU256\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[]},\"outputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F811\",\"tlb\":\"#F811\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_rnd\",\"description\":\"<p>Generates a new pseudo-random integer <code>z</code> in the range <code>0...y-1</code> (or <code>y...-1</code>, if <code>y&lt;0</code>). More precisely, an unsigned random value <code>x</code> is generated as in <code>RAND256U</code>; then <code>z:=floor(x*y/2^256)</code> is computed.\\nEquivalent to <code>RANDU256</code> <code>256 MULRSHIFT</code>.</p>\\n\",\"fift\":\"RAND\",\"fift_examples\":[],\"gas\":\"26+|c7|+|c1_1|\",\"opcode\":\"F811\",\"stack\":\"y - z\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_rand_int\",\"line\":548,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"RAND\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F814\",\"tlb\":\"#F814\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_rnd\",\"description\":\"<p>Sets the random seed to unsigned 256-bit <em>Integer</em> <code>x</code>.</p>\\n\",\"fift\":\"SETRAND\",\"fift_examples\":[],\"gas\":\"26+|c7|+|c1_1|\",\"opcode\":\"F814\",\"stack\":\"x - \"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_set_rand\",\"line\":561,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"SETRAND\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F815\",\"tlb\":\"#F815\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_rnd\",\"description\":\"<p>Mixes unsigned 256-bit <em>Integer</em> <code>x</code> into the random seed <code>r</code> by setting the random seed to <code>Sha</code> of the concatenation of two 32-byte strings: the first with the big-endian representation of the old seed <code>r</code>, and the second with the big-endian representation of <code>x</code>.</p>\\n\",\"fift\":\"ADDRAND\\nRANDOMIZE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F815\",\"stack\":\"x - \"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_set_rand\",\"line\":561,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"ADDRAND\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"F82\",\"tlb\":\"#F82 i:uint4\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_config\",\"description\":\"<p>Returns the <code>i</code>-th parameter from the <em>Tuple</em> provided at <code>c7</code> for <code>0 &lt;= i &lt;= 15</code>. Equivalent to <code>c7 PUSHCTR</code> <code>FIRST</code> <code>[i] INDEX</code>.\\nIf one of these internal operations fails, throws an appropriate type checking or range checking exception.</p>\\n\",\"fift\":\"[i] GETPARAM\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F82i\",\"stack\":\" - x\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_get_var_param\",\"line\":152,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"GETPARAM\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F830\",\"tlb\":\"#F830\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_config\",\"description\":\"<p>Returns the global configuration dictionary along with its key length (32).\\nEquivalent to <code>CONFIGROOT</code> <code>32 PUSHINT</code>.</p>\\n\",\"fift\":\"CONFIGDICT\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F830\",\"stack\":\" - D 32\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_get_config_dict\",\"line\":182,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"CONFIGDICT\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"type\":\"const\",\"value\":32,\"value_type\":\"Integer\"}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F832\",\"tlb\":\"#F832\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_config\",\"description\":\"<p>Returns the value of the global configuration parameter with integer index <code>i</code> as a <em>Cell</em> <code>c</code>, and a flag to indicate success.\\nEquivalent to <code>CONFIGDICT</code> <code>DICTIGETREF</code>.</p>\\n\",\"fift\":\"CONFIGPARAM\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F832\",\"stack\":\"i - c -1 or 0\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_get_config_param\",\"line\":188,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"CONFIGPARAM\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F833\",\"tlb\":\"#F833\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_config\",\"description\":\"<p>Returns the value of the global configuration parameter with integer index <code>i</code> as a <em>Maybe Cell</em> <code>c^?</code>.\\nEquivalent to <code>CONFIGDICT</code> <code>DICTIGETOPTREF</code>.</p>\\n\",\"fift\":\"CONFIGOPTPARAM\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F833\",\"stack\":\"i - c^?\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_get_config_param\",\"line\":188,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"CONFIGOPTPARAM\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F83400\",\"tlb\":\"#F83400\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_config\",\"description\":\"<p>Retrives <code>last_mc_blocks</code> part of PrevBlocksInfo from c7 (parameter 13).</p>\\n\",\"fift\":\"PREVMCBLOCKS\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"F83400\",\"stack\":\"- t\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_get_prev_blocks_info\",\"line\":259,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"PREVMCBLOCKS\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F83401\",\"tlb\":\"#F83401\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_config\",\"description\":\"<p>Retrives <code>prev_key_block</code> part of PrevBlocksInfo from c7 (parameter 13).</p>\\n\",\"fift\":\"PREVKEYBLOCK\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"F83401\",\"stack\":\"- t\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_get_prev_blocks_info\",\"line\":259,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"PREVKEYBLOCK\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F83402\",\"tlb\":\"#F83402\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_config\",\"description\":\"<p>Retrives <code>last_mc_blocks_divisible_by_100</code> part of PrevBlocksInfo from c7 (parameter 13).</p>\\n\",\"fift\":\"PREVMCBLOCKS_100\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"F83402\",\"stack\":\"- t\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_get_prev_blocks_info\",\"line\":259,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"PREVMCBLOCKS_100\",\"since_version\":9,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F835\",\"tlb\":\"#F835\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_config\",\"description\":\"<p>Retrieves <code>global_id</code> from 19 network config.</p>\\n\",\"fift\":\"GLOBALID\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F835\",\"stack\":\"- i\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_get_global_id\",\"line\":276,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"GLOBALID\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"i\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F836\",\"tlb\":\"#F836\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_config\",\"description\":\"<p>Calculates gas fee</p>\\n\",\"fift\":\"GETGASFEE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F836\",\"stack\":\"gas_used is_mc - price\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_get_gas_fee\",\"line\":306,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"GETGASFEE\",\"since_version\":6,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[{\"name\":\"gas_used\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"is_mc\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"price\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F837\",\"tlb\":\"#F837\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_config\",\"description\":\"<p>Calculates storage fees (only current StoragePrices entry is used).</p>\\n\",\"fift\":\"GETSTORAGEFEE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F837\",\"stack\":\"cells bits seconds is_mc - price\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_get_storage_fee\",\"line\":317,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"GETSTORAGEFEE\",\"since_version\":6,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[{\"name\":\"cells\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"bits\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"seconds\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"is_mc\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"price\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F838\",\"tlb\":\"#F838\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_config\",\"description\":\"<p>Calculates forward fee.</p>\\n\",\"fift\":\"GETFORWARDFEE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F838\",\"stack\":\"cells bits is_mc - price\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_get_forward_fee\",\"line\":331,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"GETFORWARDFEE\",\"since_version\":6,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[{\"name\":\"cells\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"bits\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"is_mc\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"price\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F839\",\"tlb\":\"#F839\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_config\",\"description\":\"<p>Returns gas usage for the current contract if it is precompiled, <code>null</code> otherwise.</p>\\n\",\"fift\":\"GETPRECOMPILEDGAS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F839\",\"stack\":\"- x\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_get_precompiled_gas\",\"line\":343,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"GETPRECOMPILEDGAS\",\"since_version\":6,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F83A\",\"tlb\":\"#F83A\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_config\",\"description\":\"<p>Calculate <code>(fwd_fee * 2^16) / (2^16 - first_frac)</code>. Can be used to get the original <code>fwd_fee</code> of the message.</p>\\n\",\"fift\":\"GETORIGINALFWDFEE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F83A\",\"stack\":\"fwd_fee is_mc - orig_fwd_fee\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_get_original_fwd_fee\",\"line\":350,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"GETORIGINALFWDFEE\",\"since_version\":6,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[{\"name\":\"fwd_fee\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"is_mc\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"orig_fwd_fee\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F83B\",\"tlb\":\"#F83B\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_config\",\"description\":\"<p>Same as <code>GETGASFEE</code>, but without flat price (just <code>(gas_used * price) / 2^16)</code>.</p>\\n\",\"fift\":\"GETGASFEESIMPLE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F83B\",\"stack\":\"gas_used is_mc - price\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_get_gas_fee_simple\",\"line\":364,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"GETGASFEESIMPLE\",\"since_version\":6,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[{\"name\":\"gas_used\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"is_mc\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"price\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F83C\",\"tlb\":\"#F83C\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_config\",\"description\":\"<p>Same as <code>GETFORWARDFEE</code>, but without lump price (just (<code>bits*bit_price + cells*cell_price) / 2^16</code>).</p>\\n\",\"fift\":\"GETFORWARDFEESIMPLE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F83C\",\"stack\":\"cells bits is_mc - price\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_get_forward_fee_simple\",\"line\":375,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"GETFORWARDFEESIMPLE\",\"since_version\":6,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[{\"name\":\"cells\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"bits\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"is_mc\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"price\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F840\",\"tlb\":\"#F840\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_global\",\"description\":\"<p>Returns the <code>k</code>-th global variable for <code>0 &lt;= k &lt; 255</code>.\\nEquivalent to <code>c7 PUSHCTR</code> <code>SWAP</code> <code>INDEXVARQ</code>.</p>\\n\",\"fift\":\"GETGLOBVAR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F840\",\"stack\":\"k - x\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_get_global_var\",\"line\":221,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"GETGLOBVAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":31,\"min_value\":1,\"name\":\"k\",\"size\":5,\"type\":\"uint\"}],\"operands_range_check\":{\"from\":1,\"length\":5,\"to\":31},\"prefix\":\"F85_\",\"tlb\":\"#F85_ k:(## 5) {1 <= k}\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_global\",\"description\":\"<p>Returns the <code>k</code>-th global variable for <code>1 &lt;= k &lt;= 31</code>.\\nEquivalent to <code>c7 PUSHCTR</code> <code>[k] INDEXQ</code>.</p>\\n\",\"fift\":\"[k] GETGLOB\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F85_k\",\"stack\":\" - x\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_get_global\",\"line\":215,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"GETGLOB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F860\",\"tlb\":\"#F860\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_global\",\"description\":\"<p>Assigns <code>x</code> to the <code>k</code>-th global variable for <code>0 &lt;= k &lt; 255</code>.\\nEquivalent to <code>c7 PUSHCTR</code> <code>ROTREV</code> <code>SETINDEXVARQ</code> <code>c7 POPCTR</code>.</p>\\n\",\"fift\":\"SETGLOBVAR\",\"fift_examples\":[],\"gas\":\"26+|c7'|\",\"opcode\":\"F860\",\"stack\":\"x k - \"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_set_global_var\",\"line\":252,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"SETGLOBVAR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":31,\"min_value\":1,\"name\":\"k\",\"size\":5,\"type\":\"uint\"}],\"operands_range_check\":{\"from\":1,\"length\":5,\"to\":31},\"prefix\":\"F87_\",\"tlb\":\"#F87_ k:(## 5) {1 <= k}\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_global\",\"description\":\"<p>Assigns <code>x</code> to the <code>k</code>-th global variable for <code>1 &lt;= k &lt;= 31</code>.\\nEquivalent to <code>c7 PUSHCTR</code> <code>SWAP</code> <code>k SETINDEXQ</code> <code>c7 POPCTR</code>.</p>\\n\",\"fift\":\"[k] SETGLOB\",\"fift_examples\":[],\"gas\":\"26+|c7'|\",\"opcode\":\"F87_k\",\"stack\":\"x - \"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_set_global\",\"line\":245,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"SETGLOB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[{\"name\":\"x\",\"type\":\"simple\"}]},\"outputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F880\",\"tlb\":\"#F880\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_global\",\"description\":\"<p>Takes id of the extra currency (integer in range <code>0..2^32-1</code>), returns the amount of this extra currency on the account balance. The first <code>5</code> executions of <code>GETEXTRABALANCE</code> consume at most <code>26 + 200</code> gas each. The subsequent executions incur the full gas cost of <code>26</code> (normal instruction cost) plus gas for loading cells (up to <code>3300</code> if the dictionary has maximum depth).</p>\\n\",\"fift\":\"GETEXTRABALANCE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F880\",\"stack\":\"id - amount\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_get_extra_currency_balance\",\"line\":388,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/f58297f1b668c7b49e8b30b65062951ca7c18acc/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"GETEXTRABALANCE\",\"since_version\":10,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[{\"name\":\"id\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"amount\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":255,\"min_value\":0,\"name\":\"i\",\"size\":8,\"type\":\"uint\"}],\"prefix\":\"F881\",\"tlb\":\"#F881 i:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_config\",\"description\":\"<p>Returns the <code>i</code>-th parameter from the <em>Tuple</em> provided at <code>c7</code> for <code>0 &lt;= i &lt;= 255</code>. Equivalent to <code>c7 PUSHCTR</code> <code>FIRST</code> <code>[i] INDEX</code>.\\nIf one of these internal operations fails, throws an appropriate type checking or range checking exception.</p>\\n\",\"fift\":\"[i] GETPARAMLONG\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"F881ii\",\"stack\":\" - x\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_get_var_param_long\",\"line\":158,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/f58297f1b668c7b49e8b30b65062951ca7c18acc/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"GETPARAMLONG\",\"since_version\":11,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"}],\"prefix\":\"F89\",\"tlb\":\"#F89 i:uint8\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_config\",\"description\":\"<p>Equivalent to <code>INMSGPARAMS</code> <code>i INDEX</code></p>\\n\",\"fift\":\"[i] INMSGPARAM\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F89i\",\"stack\":\" - x\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_get_var_in_msg_param\",\"line\":176,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/f58297f1b668c7b49e8b30b65062951ca7c18acc/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"INMSGPARAM\",\"since_version\":11,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":7,\"type\":\"constant\"}],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F900\",\"tlb\":\"#F900\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Computes the representation hash of a <em>Cell</em> <code>c</code> and returns it as a 256-bit unsigned integer <code>x</code>. Useful for signing and checking signatures of arbitrary entities represented by a tree of cells.</p>\\n\",\"fift\":\"HASHCU\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F900\",\"stack\":\"c - x\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_compute_hash\",\"line\":612,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHCU\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F901\",\"tlb\":\"#F901\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Computes the hash of a <em>Slice</em> <code>s</code> and returns it as a 256-bit unsigned integer <code>x</code>. The result is the same as if an ordinary cell containing only data and references from <code>s</code> had been created and its hash computed by <code>HASHCU</code>.</p>\\n\",\"fift\":\"HASHSU\",\"fift_examples\":[],\"gas\":\"526\",\"opcode\":\"F901\",\"stack\":\"s - x\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_compute_hash\",\"line\":612,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHSU\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F902\",\"tlb\":\"#F902\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Computes <code>Sha</code> of the data bits of <em>Slice</em> <code>s</code>. If the bit length of <code>s</code> is not divisible by eight, throws a cell underflow exception. The hash value is returned as a 256-bit unsigned integer <code>x</code>.</p>\\n\",\"fift\":\"SHA256U\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F902\",\"stack\":\"s - x\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_compute_sha256\",\"line\":634,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"SHA256U\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F90400\",\"tlb\":\"#F90400\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates and returns hash of the concatenation of slices (or builders) <code>s_1...s_n</code>.</p>\\n\",\"fift\":\"HASHEXT_SHA256\",\"fift_examples\":[],\"gas\":\"1/33 gas per byte\",\"opcode\":\"F90400\",\"stack\":\"s_1 ... s_n n - h\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_hash_ext\",\"line\":652,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHEXT_SHA256\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Builder\"]}],\"length_var\":\"n\",\"name\":\"input_parts\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"h\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F90401\",\"tlb\":\"#F90401\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates and returns hash of the concatenation of slices (or builders) <code>s_1...s_n</code>.</p>\\n\",\"fift\":\"HASHEXT_SHA512\",\"fift_examples\":[],\"gas\":\"1/16 gas per byte\",\"opcode\":\"F90401\",\"stack\":\"s_1 ... s_n n - h1 h2\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_hash_ext\",\"line\":652,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHEXT_SHA512\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Builder\"]}],\"length_var\":\"n\",\"name\":\"input_parts\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"h1\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"h2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F90402\",\"tlb\":\"#F90402\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates and returns hash of the concatenation of slices (or builders) <code>s_1...s_n</code>.</p>\\n\",\"fift\":\"HASHEXT_BLAKE2B\",\"fift_examples\":[],\"gas\":\"1/19 gas per byte\",\"opcode\":\"F90402\",\"stack\":\"s_1 ... s_n n - h1 h2\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_hash_ext\",\"line\":652,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHEXT_BLAKE2B\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Builder\"]}],\"length_var\":\"n\",\"name\":\"input_parts\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"h1\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"h2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F90403\",\"tlb\":\"#F90403\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates and returns hash of the concatenation of slices (or builders) <code>s_1...s_n</code>.</p>\\n\",\"fift\":\"HASHEXT_KECCAK256\",\"fift_examples\":[],\"gas\":\"1/11 gas per byte\",\"opcode\":\"F90403\",\"stack\":\"s_1 ... s_n n - h\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_hash_ext\",\"line\":652,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHEXT_KECCAK256\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Builder\"]}],\"length_var\":\"n\",\"name\":\"input_parts\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"h\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F90404\",\"tlb\":\"#F90404\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates and returns hash of the concatenation of slices (or builders) <code>s_1...s_n</code>.</p>\\n\",\"fift\":\"HASHEXT_KECCAK512\",\"fift_examples\":[],\"gas\":\"1/19 gas per byte\",\"opcode\":\"F90404\",\"stack\":\"s_1 ... s_n n - h1 h2\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_hash_ext\",\"line\":652,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHEXT_KECCAK512\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Builder\"]}],\"length_var\":\"n\",\"name\":\"input_parts\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"h1\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"h2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F90500\",\"tlb\":\"#F90500\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates and returns hash of the concatenation of slices (or builders) <code>s_1...s_n</code>.</p>\\n\",\"fift\":\"HASHEXTR_SHA256\",\"fift_examples\":[],\"gas\":\"1/33 gas per byte\",\"opcode\":\"F90500\",\"stack\":\"s_n ... s_1 n - h\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_hash_ext\",\"line\":652,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHEXTR_SHA256\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Builder\"]}],\"length_var\":\"n\",\"name\":\"input_parts\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"h\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F90501\",\"tlb\":\"#F90501\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates and returns hash of the concatenation of slices (or builders) <code>s_1...s_n</code>.</p>\\n\",\"fift\":\"HASHEXTR_SHA512\",\"fift_examples\":[],\"gas\":\"1/16 gas per byte\",\"opcode\":\"F90501\",\"stack\":\"s_n ... s_1 n - h1 h2\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_hash_ext\",\"line\":652,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHEXTR_SHA512\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Builder\"]}],\"length_var\":\"n\",\"name\":\"input_parts\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"h1\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"h2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F90502\",\"tlb\":\"#F90502\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates and returns hash of the concatenation of slices (or builders) <code>s_1...s_n</code>.</p>\\n\",\"fift\":\"HASHEXTR_BLAKE2B\",\"fift_examples\":[],\"gas\":\"1/19 gas per byte\",\"opcode\":\"F90502\",\"stack\":\"s_n ... s_1 n - h1 h2\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_hash_ext\",\"line\":652,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHEXTR_BLAKE2B\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Builder\"]}],\"length_var\":\"n\",\"name\":\"input_parts\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"h1\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"h2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F90503\",\"tlb\":\"#F90503\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates and returns hash of the concatenation of slices (or builders) <code>s_1...s_n</code>.</p>\\n\",\"fift\":\"HASHEXTR_KECCAK256\",\"fift_examples\":[],\"gas\":\"1/11 gas per byte\",\"opcode\":\"F90503\",\"stack\":\"s_n ... s_1 n - h\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_hash_ext\",\"line\":652,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHEXTR_KECCAK256\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Builder\"]}],\"length_var\":\"n\",\"name\":\"input_parts\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"h\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F90504\",\"tlb\":\"#F90504\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates and returns hash of the concatenation of slices (or builders) <code>s_1...s_n</code>.</p>\\n\",\"fift\":\"HASHEXTR_KECCAK512\",\"fift_examples\":[],\"gas\":\"1/19 gas per byte\",\"opcode\":\"F90504\",\"stack\":\"s_n ... s_1 n - h1 h2\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_hash_ext\",\"line\":652,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHEXTR_KECCAK512\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Builder\"]}],\"length_var\":\"n\",\"name\":\"input_parts\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"h1\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"h2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F90600\",\"tlb\":\"#F90600\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates hash of the concatenation of slices (or builders) <code>s_1...s_n</code>. Appends the resulting hash to a builder <code>b</code>.</p>\\n\",\"fift\":\"HASHEXTA_SHA256\",\"fift_examples\":[],\"gas\":\"1/33 gas per byte\",\"opcode\":\"F90600\",\"stack\":\"b s_1 ... s_n n - b'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_hash_ext\",\"line\":652,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHEXTA_SHA256\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"array_entry\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Builder\"]}],\"length_var\":\"n\",\"name\":\"input_parts\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F90601\",\"tlb\":\"#F90601\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates hash of the concatenation of slices (or builders) <code>s_1...s_n</code>. Appends the resulting hash to a builder <code>b</code>.</p>\\n\",\"fift\":\"HASHEXTA_SHA512\",\"fift_examples\":[],\"gas\":\"1/16 gas per byte\",\"opcode\":\"F90601\",\"stack\":\"b s_1 ... s_n n - b'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_hash_ext\",\"line\":652,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHEXTA_SHA512\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"array_entry\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Builder\"]}],\"length_var\":\"n\",\"name\":\"input_parts\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F90602\",\"tlb\":\"#F90602\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates hash of the concatenation of slices (or builders) <code>s_1...s_n</code>. Appends the resulting hash to a builder <code>b</code>.</p>\\n\",\"fift\":\"HASHEXTA_BLAKE2B\",\"fift_examples\":[],\"gas\":\"1/19 gas per byte\",\"opcode\":\"F90602\",\"stack\":\"b s_1 ... s_n n - b'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_hash_ext\",\"line\":652,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHEXTA_BLAKE2B\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"array_entry\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Builder\"]}],\"length_var\":\"n\",\"name\":\"input_parts\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F90603\",\"tlb\":\"#F90603\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates hash of the concatenation of slices (or builders) <code>s_1...s_n</code>. Appends the resulting hash to a builder <code>b</code>.</p>\\n\",\"fift\":\"HASHEXTA_KECCAK256\",\"fift_examples\":[],\"gas\":\"1/11 gas per byte\",\"opcode\":\"F90603\",\"stack\":\"b s_1 ... s_n n - b'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_hash_ext\",\"line\":652,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHEXTA_KECCAK256\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"array_entry\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Builder\"]}],\"length_var\":\"n\",\"name\":\"input_parts\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F90604\",\"tlb\":\"#F90604\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates hash of the concatenation of slices (or builders) <code>s_1...s_n</code>. Appends the resulting hash to a builder <code>b</code>.</p>\\n\",\"fift\":\"HASHEXTA_KECCAK512\",\"fift_examples\":[],\"gas\":\"1/6 gas per byte\",\"opcode\":\"F90604\",\"stack\":\"b s_1 ... s_n n - b'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_hash_ext\",\"line\":652,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHEXTA_KECCAK512\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"array_entry\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Builder\"]}],\"length_var\":\"n\",\"name\":\"input_parts\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F90700\",\"tlb\":\"#F90700\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates hash of the concatenation of slices (or builders) <code>s_1...s_n</code>. Appends the resulting hash to a builder <code>b</code>.</p>\\n\",\"fift\":\"HASHEXTAR_SHA256\",\"fift_examples\":[],\"gas\":\"1/33 gas per byte\",\"opcode\":\"F90700\",\"stack\":\"b s_1 ... s_n n - b'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_hash_ext\",\"line\":652,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHEXTAR_SHA256\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"array_entry\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Builder\"]}],\"length_var\":\"n\",\"name\":\"input_parts\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F90701\",\"tlb\":\"#F90701\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates hash of the concatenation of slices (or builders) <code>s_1...s_n</code>. Appends the resulting hash to a builder <code>b</code>.</p>\\n\",\"fift\":\"HASHEXTAR_SHA512\",\"fift_examples\":[],\"gas\":\"1/16 gas per byte\",\"opcode\":\"F90701\",\"stack\":\"b s_n ... s_1 n - b'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_hash_ext\",\"line\":652,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHEXTAR_SHA512\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"array_entry\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Builder\"]}],\"length_var\":\"n\",\"name\":\"input_parts\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F90702\",\"tlb\":\"#F90702\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates hash of the concatenation of slices (or builders) <code>s_1...s_n</code>. Appends the resulting hash to a builder <code>b</code>.</p>\\n\",\"fift\":\"HASHEXTAR_BLAKE2B\",\"fift_examples\":[],\"gas\":\"1/19 gas per byte\",\"opcode\":\"F90702\",\"stack\":\"b s_n ... s_1 n - b'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_hash_ext\",\"line\":652,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHEXTAR_BLAKE2B\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"array_entry\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Builder\"]}],\"length_var\":\"n\",\"name\":\"input_parts\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F90703\",\"tlb\":\"#F90703\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates hash of the concatenation of slices (or builders) <code>s_1...s_n</code>. Appends the resulting hash to a builder <code>b</code>.</p>\\n\",\"fift\":\"HASHEXTAR_KECCAK256\",\"fift_examples\":[],\"gas\":\"1/11 gas per byte\",\"opcode\":\"F90703\",\"stack\":\"b s_n ... s_1 n - b'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_hash_ext\",\"line\":652,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHEXTAR_KECCAK256\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"array_entry\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Builder\"]}],\"length_var\":\"n\",\"name\":\"input_parts\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F90704\",\"tlb\":\"#F90704\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates hash of the concatenation of slices (or builders) <code>s_1...s_n</code>. Appends the resulting hash to a builder <code>b</code>.</p>\\n\",\"fift\":\"HASHEXTAR_KECCAK512\",\"fift_examples\":[],\"gas\":\"1/6 gas per byte\",\"opcode\":\"F90704\",\"stack\":\"b s_n ... s_1 n - b'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_hash_ext\",\"line\":652,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHEXTAR_KECCAK512\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"array_entry\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Builder\"]}],\"length_var\":\"n\",\"name\":\"input_parts\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F910\",\"tlb\":\"#F910\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Checks the Ed25519-signature <code>s</code> of a hash <code>h</code> (a 256-bit unsigned integer, usually computed as the hash of some data) using public key <code>k</code> (also represented by a 256-bit unsigned integer).\\nThe signature <code>s</code> must be a <em>Slice</em> containing at least 512 data bits; only the first 512 bits are used. The result is <code>-1</code> if the signature is valid, <code>0</code> otherwise.\\nNotice that <code>CHKSIGNU</code> is equivalent to <code>ROT</code> <code>NEWC</code> <code>256 STU</code> <code>ENDC</code> <code>ROTREV</code> <code>CHKSIGNS</code>, i.e., to <code>CHKSIGNS</code> with the first argument <code>d</code> set to 256-bit <em>Slice</em> containing <code>h</code>. Therefore, if <code>h</code> is computed as the hash of some data, these data are hashed <em>twice</em>, the second hashing occurring inside <code>CHKSIGNS</code>.</p>\\n\",\"fift\":\"CHKSIGNU\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F910\",\"stack\":\"h s k - ?\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_ed25519_check_signature\",\"line\":724,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"CHKSIGNU\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"h\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F911\",\"tlb\":\"#F911\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Checks whether <code>s</code> is a valid Ed25519-signature of the data portion of <em>Slice</em> <code>d</code> using public key <code>k</code>, similarly to <code>CHKSIGNU</code>. If the bit length of <em>Slice</em> <code>d</code> is not divisible by eight, throws a cell underflow exception. The verification of Ed25519 signatures is the standard one, with <code>Sha</code> used to reduce <code>d</code> to the 256-bit number that is actually signed.</p>\\n\",\"fift\":\"CHKSIGNS\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F911\",\"stack\":\"d s k - ?\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_ed25519_check_signature\",\"line\":724,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"CHKSIGNS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"d\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F912\",\"tlb\":\"#F912\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Recovers the public key from a secp256k1 signature, identical to Bitcoin/Ethereum operations. Takes a 32-byte hash as <code>uint256 hash</code> and a 65-byte signature as <code>uint8 v</code>, <code>uint256 r</code>, and <code>uint256 s</code>. In TON, the <code>v</code> value is strictly 0 or 1; no extra flags or extended values are supported. If the public key cannot be recovered, the instruction returns <code>0</code>. On success, it returns the recovered 65-byte public key as <code>uint8 h</code>, <code>uint256 x1</code>, and <code>uint256 x2</code>, followed by <code>-1</code>.</p>\\n\",\"fift\":\"ECRECOVER\",\"fift_examples\":[],\"gas\":\"1526\",\"opcode\":\"F912\",\"stack\":\"hash v r s - 0 or h x1 x2 -1\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_ecrecover\",\"line\":760,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"ECRECOVER\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"hash\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"v\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"r\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"h\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"x1\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"x2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F913\",\"tlb\":\"#F913\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>performs <a href=\\\"https://github.com/bitcoin-core/secp256k1/blob/master/include/secp256k1_extrakeys.h#L120\\\"><code>secp256k1_xonly_pubkey_tweak_add</code></a>. <code>key</code> and <code>tweak</code> are 256-bit unsigned integers. 65-byte public key is returned as <code>uint8 f</code>, <code>uint256 x, y</code> (as in <code>ECRECOVER</code>).</p>\\n\",\"fift\":\"SECP256K1_XONLY_PUBKEY_TWEAK_ADD\",\"fift_examples\":[],\"gas\":\"1576\",\"opcode\":\"F913\",\"stack\":\"key tweak - 0 or f x y -1\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_secp256k1_xonly_pubkey_tweak_add\",\"line\":798,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/f58297f1b668c7b49e8b30b65062951ca7c18acc/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"SECP256K1_XONLY_PUBKEY_TWEAK_ADD\",\"since_version\":9,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"key\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"tweak\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F914\",\"tlb\":\"#F914\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Checks seck256r1-signature <code>sig</code> of a number <code>h</code> (a 256-bit unsigned integer, usually computed as the hash of some data) and public key <code>k</code>. Returns -1 on success, 0 on failure. Public key is a 33-byte slice (encoded according to Sec. 2.3.4 point 2 of <a href=\\\"https://www.secg.org/sec1-v2.pdf\\\">SECG SEC 1</a>). Signature <code>sig</code> is a 64-byte slice (two 256-bit unsigned integers <code>r</code> and <code>s</code>).</p>\\n\",\"fift\":\"P256_CHKSIGNU\",\"fift_examples\":[],\"gas\":\"3526\",\"opcode\":\"F914\",\"stack\":\"h sig k - ?\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_p256_chksign\",\"line\":829,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"P256_CHKSIGNU\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"d\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"sig\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F915\",\"tlb\":\"#F915\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Checks seck256r1-signature <code>sig</code> of data portion of slice <code>d</code> and public key <code>k</code>. Returns -1 on success, 0 on failure. Public key is a 33-byte slice (encoded according to Sec. 2.3.4 point 2 of <a href=\\\"https://www.secg.org/sec1-v2.pdf\\\">SECG SEC 1</a>). Signature <code>sig</code> is a 64-byte slice (two 256-bit unsigned integers <code>r</code> and <code>s</code>).</p>\\n\",\"fift\":\"P256_CHKSIGNS\",\"fift_examples\":[],\"gas\":\"3526\",\"opcode\":\"F915\",\"stack\":\"d sig k - ?\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_p256_chksign\",\"line\":829,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"P256_CHKSIGNS\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"d\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"sig\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"k\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F916\",\"tlb\":\"#F916\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Same as <code>ENDC HASHCU</code>, but without gas cost for cell creation.</p>\\n\",\"fift\":\"HASHBU\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F916\",\"stack\":\"b - hash\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_compute_hash\",\"line\":612,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/f58297f1b668c7b49e8b30b65062951ca7c18acc/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"HASHBU\",\"since_version\":12,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"hash\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F920\",\"tlb\":\"#F920\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Deterministically generates a valid point <code>x</code> from a 512-bit hash (given as two 256-bit integers).</p>\\n\",\"fift\":\"RIST255_FROMHASH\",\"fift_examples\":[],\"gas\":\"626\",\"opcode\":\"F920\",\"stack\":\"h1 h2 - x\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_ristretto255_from_hash\",\"line\":874,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"RIST255_FROMHASH\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"h1\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"h2\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F921\",\"tlb\":\"#F921\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Checks that integer <code>x</code> is a valid representation of some curve point. Throws range_chk on error.</p>\\n\",\"fift\":\"RIST255_VALIDATE\",\"fift_examples\":[],\"gas\":\"226\",\"opcode\":\"F921\",\"stack\":\"x -\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_ristretto255_validate\",\"line\":895,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"RIST255_VALIDATE\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F922\",\"tlb\":\"#F922\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Addition of two points on a curve.</p>\\n\",\"fift\":\"RIST255_ADD\",\"fift_examples\":[],\"gas\":\"626\",\"opcode\":\"F922\",\"stack\":\"x y - x+y\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_ristretto255_add\",\"line\":914,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"RIST255_ADD\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F923\",\"tlb\":\"#F923\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Subtraction of two points on curve.</p>\\n\",\"fift\":\"RIST255_SUB\",\"fift_examples\":[],\"gas\":\"626\",\"opcode\":\"F923\",\"stack\":\"x y - x-y\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_ristretto255_sub\",\"line\":938,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"RIST255_SUB\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F924\",\"tlb\":\"#F924\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Multiplies point <code>x</code> by a scalar <code>n</code>. Any <code>n</code> is valid, including negative.</p>\\n\",\"fift\":\"RIST255_MUL\",\"fift_examples\":[],\"gas\":\"2026\",\"opcode\":\"F924\",\"stack\":\"x n - x*n\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_ristretto255_mul\",\"line\":976,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"RIST255_MUL\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F925\",\"tlb\":\"#F925\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Multiplies the generator point <code>g</code> by a scalar <code>n</code>. Any <code>n</code> is valid, including negative.</p>\\n\",\"fift\":\"RIST255_MULBASE\",\"fift_examples\":[],\"gas\":\"776\",\"opcode\":\"F925\",\"stack\":\"n - g*n\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_ristretto255_mul_base\",\"line\":1007,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"RIST255_MULBASE\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F926\",\"tlb\":\"#F926\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Pushes integer l=2^252+27742317777372353535851937790883648493, which is the order of the group.</p>\\n\",\"fift\":\"RIST255_PUSHL\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F926\",\"stack\":\"- l\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_ristretto255_push_l\",\"line\":1032,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"RIST255_PUSHL\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7F921\",\"tlb\":\"#B7F921\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Checks that integer <code>x</code> is a valid representation of some curve point. Returns -1 on success and 0 on failure.</p>\\n\",\"fift\":\"RIST255_QVALIDATE\",\"fift_examples\":[],\"gas\":\"234\",\"opcode\":\"B7F921\",\"stack\":\"x - 0 or -1\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_ristretto255_validate\",\"line\":895,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"RIST255_QVALIDATE\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7F922\",\"tlb\":\"#B7F922\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Addition of two points on a curve. Returns -1 on success and 0 on failure.</p>\\n\",\"fift\":\"RIST255_QADD\",\"fift_examples\":[],\"gas\":\"634\",\"opcode\":\"B7F922\",\"stack\":\"x y - 0 or x+y -1\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_ristretto255_add\",\"line\":914,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"RIST255_QADD\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7F923\",\"tlb\":\"#B7F923\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Subtraction of two points on curve. Returns -1 on success and 0 on failure.</p>\\n\",\"fift\":\"RIST255_QSUB\",\"fift_examples\":[],\"gas\":\"634\",\"opcode\":\"B7F923\",\"stack\":\"x y - 0 or x-y -1\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_ristretto255_sub\",\"line\":938,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"RIST255_QSUB\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7F924\",\"tlb\":\"#B7F924\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Multiplies point <code>x</code> by a scalar <code>n</code>. Any <code>n</code> is valid, including negative. Returns -1 on success and 0 on failure.</p>\\n\",\"fift\":\"RIST255_QMUL\",\"fift_examples\":[],\"gas\":\"2034\",\"opcode\":\"B7F924\",\"stack\":\"x n - 0 or x*n -1\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_ristretto255_mul\",\"line\":976,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"RIST255_QMUL\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"B7F925\",\"tlb\":\"#B7F925\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Multiplies the generator point <code>g</code> by a scalar <code>n</code>. Any <code>n</code> is valid, including negative.</p>\\n\",\"fift\":\"RIST255_QMULBASE\",\"fift_examples\":[],\"gas\":\"784\",\"opcode\":\"B7F925\",\"stack\":\"n - 0 or g*n -1\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_ristretto255_mul_base\",\"line\":1007,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"RIST255_QMULBASE\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93000\",\"tlb\":\"#F93000\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Checks BLS signature, return true on success, false otherwise.</p>\\n\",\"fift\":\"BLS_VERIFY\",\"fift_examples\":[],\"gas\":\"61034\",\"opcode\":\"F93000\",\"stack\":\"pk msg sgn - bool\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_verify\",\"line\":1095,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_VERIFY\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"pk\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"msg\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"sgn\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93001\",\"tlb\":\"#F93001\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Aggregates signatures. <code>n&gt;0</code>. Throw exception if <code>n=0</code> or if some <code>sig_i</code> is not a valid signature.</p>\\n\",\"fift\":\"BLS_AGGREGATE\",\"fift_examples\":[],\"gas\":\"n*4350-2616\",\"opcode\":\"F93001\",\"stack\":\"sig_1 ... sig_n n - sig\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_aggregate\",\"line\":1107,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_AGGREGATE\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"sig\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"length_var\":\"n\",\"name\":\"signatures\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93002\",\"tlb\":\"#F93002\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Checks aggregated BLS signature for keys <code>pk_1...pk_n</code> and message <code>msg</code>. Return true on success, false otherwise. Return false if <code>n=0</code>.</p>\\n\",\"fift\":\"BLS_FASTAGGREGATEVERIFY\",\"fift_examples\":[],\"gas\":\"58034+n*3000\",\"opcode\":\"F93002\",\"stack\":\"pk_1 ... pk_n n msg sig - bool\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_fast_aggregate_verify\",\"line\":1121,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_FASTAGGREGATEVERIFY\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"pk\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"length_var\":\"n\",\"name\":\"public_keys\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"msg\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"sig\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93003\",\"tlb\":\"#F93003\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Checks aggregated BLS signature for key-message pairs <code>pk_1 msg_1...pk_n msg_n</code>. Return true on success, false otherwise. Return false if <code>n=0</code>.</p>\\n\",\"fift\":\"BLS_AGGREGATEVERIFY\",\"fift_examples\":[],\"gas\":\"38534+n*22500\",\"opcode\":\"F93003\",\"stack\":\"pk_1 msg_1 ... pk_n msg_n n sgn - bool\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_aggregate_verify\",\"line\":1138,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_AGGREGATEVERIFY\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"pk\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"msg\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"length_var\":\"n\",\"name\":\"key_message_pairs\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"sgn\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93010\",\"tlb\":\"#F93010\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Addition on G1.</p>\\n\",\"fift\":\"BLS_G1_ADD\",\"fift_examples\":[],\"gas\":\"3934\",\"opcode\":\"F93010\",\"stack\":\"x y - x+y\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_g1_add\",\"line\":1155,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_G1_ADD\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93011\",\"tlb\":\"#F93011\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Subtraction on G1.</p>\\n\",\"fift\":\"BLS_G1_SUB\",\"fift_examples\":[],\"gas\":\"3934\",\"opcode\":\"F93011\",\"stack\":\"x y - x-y\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_g1_sub\",\"line\":1166,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_G1_SUB\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93012\",\"tlb\":\"#F93012\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Negation on G1.</p>\\n\",\"fift\":\"BLS_G1_NEG\",\"fift_examples\":[],\"gas\":\"784\",\"opcode\":\"F93012\",\"stack\":\"x - -x\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_g1_neg\",\"line\":1177,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_G1_NEG\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93013\",\"tlb\":\"#F93013\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Multiplies G1 point <code>x</code> by scalar <code>s</code>. Any <code>s</code> is valid, including negative.</p>\\n\",\"fift\":\"BLS_G1_MUL\",\"fift_examples\":[],\"gas\":\"5234\",\"opcode\":\"F93013\",\"stack\":\"x s - x*s\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_g1_mul\",\"line\":1186,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_G1_MUL\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93014\",\"tlb\":\"#F93014\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates <code>x_1*s_1+...+x_n*s_n</code> for G1 points <code>x_i</code> and scalars <code>s_i</code>. Returns zero point if <code>n=0</code>. Any <code>s_i</code> is valid, including negative.</p>\\n\",\"fift\":\"BLS_G1_MULTIEXP\",\"fift_examples\":[],\"gas\":\"11409+n*630+n/floor(max(log2(n),4))*8820\",\"opcode\":\"F93014\",\"stack\":\"x_1 s_1 ... x_n s_n n - x_1*s_1+...+x_n*s_n\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_g1_multiexp\",\"line\":1197,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_G1_MULTIEXP\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"length_var\":\"n\",\"name\":\"components\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93015\",\"tlb\":\"#F93015\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Pushes zero point in G1.</p>\\n\",\"fift\":\"BLS_G1_ZERO\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"F93015\",\"stack\":\"- zero\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_g1_zero\",\"line\":1213,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_G1_ZERO\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"zero\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93016\",\"tlb\":\"#F93016\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Converts FP element <code>f</code> to a G1 point.</p>\\n\",\"fift\":\"BLS_MAP_TO_G1\",\"fift_examples\":[],\"gas\":\"2384\",\"opcode\":\"F93016\",\"stack\":\"f - x\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_map_to_g1\",\"line\":1220,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_MAP_TO_G1\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93017\",\"tlb\":\"#F93017\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Checks that slice <code>x</code> represents a valid element of G1.</p>\\n\",\"fift\":\"BLS_G1_INGROUP\",\"fift_examples\":[],\"gas\":\"2984\",\"opcode\":\"F93017\",\"stack\":\"x - bool\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_g1_in_group\",\"line\":1229,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_G1_INGROUP\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93018\",\"tlb\":\"#F93018\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Checks that G1 point <code>x</code> is equal to zero.</p>\\n\",\"fift\":\"BLS_G1_ISZERO\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"F93018\",\"stack\":\"x - bool\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_g1_is_zero\",\"line\":1238,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_G1_ISZERO\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93020\",\"tlb\":\"#F93020\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Addition on G2.</p>\\n\",\"fift\":\"BLS_G2_ADD\",\"fift_examples\":[],\"gas\":\"6134\",\"opcode\":\"F93020\",\"stack\":\"x y - x+y\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_g2_add\",\"line\":1246,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_G2_ADD\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93021\",\"tlb\":\"#F93021\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Subtraction on G2.</p>\\n\",\"fift\":\"BLS_G2_SUB\",\"fift_examples\":[],\"gas\":\"6134\",\"opcode\":\"F93021\",\"stack\":\"x y - x-y\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_g2_sub\",\"line\":1257,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_G2_SUB\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93022\",\"tlb\":\"#F93022\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Negation on G2.</p>\\n\",\"fift\":\"BLS_G2_NEG\",\"fift_examples\":[],\"gas\":\"1584\",\"opcode\":\"F93022\",\"stack\":\"x - -x\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_g2_neg\",\"line\":1268,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_G2_NEG\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93023\",\"tlb\":\"#F93023\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Multiplies G2 point <code>x</code> by scalar <code>s</code>. Any <code>s</code> is valid, including negative.</p>\\n\",\"fift\":\"BLS_G2_MUL\",\"fift_examples\":[],\"gas\":\"10584\",\"opcode\":\"F93023\",\"stack\":\"x s - x*s\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_g2_mul\",\"line\":1277,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_G2_MUL\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93024\",\"tlb\":\"#F93024\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Calculates <code>x_1*s_1+...+x_n*s_n</code> for G2 points <code>x_i</code> and scalars <code>s_i</code>. Returns zero point if <code>n=0</code>. Any <code>s_i</code> is valid, including negative.</p>\\n\",\"fift\":\"BLS_G2_MULTIEXP\",\"fift_examples\":[],\"gas\":\"30422+n*1280+n/floor(max(log2(n),4))*22840\",\"opcode\":\"F93024\",\"stack\":\"x_1 s_1 ... x_n s_n n - x_1*s_1+...+x_n*s_n\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_g2_multiexp\",\"line\":1288,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_G2_MULTIEXP\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"length_var\":\"n\",\"name\":\"components\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93025\",\"tlb\":\"#F93025\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Pushes zero point in G2.</p>\\n\",\"fift\":\"BLS_G2_ZERO\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"F93025\",\"stack\":\"- zero\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_g2_zero\",\"line\":1304,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_G2_ZERO\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"zero\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93026\",\"tlb\":\"#F93026\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Converts FP2 element <code>f</code> to a G2 point.</p>\\n\",\"fift\":\"BLS_MAP_TO_G2\",\"fift_examples\":[],\"gas\":\"7984\",\"opcode\":\"F93026\",\"stack\":\"f - x\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_map_to_g2\",\"line\":1311,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_MAP_TO_G2\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"f\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93027\",\"tlb\":\"#F93027\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Checks that slice <code>x</code> represents a valid element of G2.</p>\\n\",\"fift\":\"BLS_G2_INGROUP\",\"fift_examples\":[],\"gas\":\"4284\",\"opcode\":\"F93027\",\"stack\":\"x - bool\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_g2_in_group\",\"line\":1320,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_G2_INGROUP\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93028\",\"tlb\":\"#F93028\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Checks that G2 point <code>x</code> is equal to zero.</p>\\n\",\"fift\":\"BLS_G2_ISZERO\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"F93028\",\"stack\":\"x - bool\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_g2_is_zero\",\"line\":1329,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_G2_ISZERO\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93030\",\"tlb\":\"#F93030\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Given G1 points <code>x_i</code> and G2 points <code>y_i</code>, calculates and multiply pairings of <code>x_i,y_i</code>. Returns true if the result is the multiplicative identity in FP12, false otherwise. Returns false if <code>n=0</code>.</p>\\n\",\"fift\":\"BLS_PAIRING\",\"fift_examples\":[],\"gas\":\"20034+n*11800\",\"opcode\":\"F93030\",\"stack\":\"x_1 y_1 ... x_n y_n n - bool\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_pairing\",\"line\":1337,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_PAIRING\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"array_entry\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"length_var\":\"n\",\"name\":\"components\",\"type\":\"array\"},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F93031\",\"tlb\":\"#F93031\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_crypto\",\"description\":\"<p>Pushes the order of G1 and G2 (approx. <code>2^255</code>).</p>\\n\",\"fift\":\"BLS_PUSHR\",\"fift_examples\":[],\"gas\":\"34\",\"opcode\":\"F93031\",\"stack\":\"- r\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_bls_push_r\",\"line\":1351,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"BLS_PUSHR\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"result\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F940\",\"tlb\":\"#F940\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_misc\",\"description\":\"<p>Recursively computes the count of distinct cells <code>x</code>, data bits <code>y</code>, and cell references <code>z</code> in the dag rooted at <em>Cell</em> <code>c</code>, effectively returning the total storage used by this dag taking into account the identification of equal cells. The values of <code>x</code>, <code>y</code>, and <code>z</code> are computed by a depth-first traversal of this dag, with a hash table of visited cell hashes used to prevent visits of already-visited cells. The total count of visited cells <code>x</code> cannot exceed non-negative <em>Integer</em> <code>n</code>; otherwise the computation is aborted before visiting the <code>(n+1)</code>-st cell and a zero is returned to indicate failure. If <code>c</code> is <em>Null</em>, returns <code>x=y=z=0</code>.</p>\\n\",\"fift\":\"CDATASIZEQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F940\",\"stack\":\"c n - x y z -1 or 0\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_compute_data_size\",\"line\":1415,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"CDATASIZEQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F941\",\"tlb\":\"#F941\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_misc\",\"description\":\"<p>A non-quiet version of <code>CDATASIZEQ</code> that throws a cell overflow exception (8) on failure.</p>\\n\",\"fift\":\"CDATASIZE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F941\",\"stack\":\"c n - x y z\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_compute_data_size\",\"line\":1415,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"CDATASIZE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F942\",\"tlb\":\"#F942\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_misc\",\"description\":\"<p>Similar to <code>CDATASIZEQ</code>, but accepting a <em>Slice</em> <code>s</code> instead of a <em>Cell</em>. The returned value of <code>x</code> does not take into account the cell that contains the slice <code>s</code> itself; however, the data bits and the cell references of <code>s</code> are accounted for in <code>y</code> and <code>z</code>.</p>\\n\",\"fift\":\"SDATASIZEQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F942\",\"stack\":\"s n - x y z -1 or 0\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_compute_data_size\",\"line\":1415,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"SDATASIZEQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"F943\",\"tlb\":\"#F943\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_misc\",\"description\":\"<p>A non-quiet version of <code>SDATASIZEQ</code> that throws a cell overflow exception (8) on failure.</p>\\n\",\"fift\":\"SDATASIZE\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"F943\",\"stack\":\"s n - x y z\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_compute_data_size\",\"line\":1415,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"SDATASIZE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"n\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"z\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA00\",\"tlb\":\"#FA00\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_currency\",\"description\":\"<p>Loads (deserializes) a <code>Gram</code> or <code>VarUInteger 16</code> amount from <em>Slice</em> <code>s</code>, and returns the amount as <em>Integer</em> <code>x</code> along with the remainder <code>s'</code> of <code>s</code>. The expected serialization of <code>x</code> consists of a 4-bit unsigned big-endian integer <code>l</code>, followed by an <code>8l</code>-bit unsigned big-endian representation of <code>x</code>.\\nThe net effect is approximately equivalent to <code>4 LDU</code> <code>SWAP</code> <code>3 LSHIFT#</code> <code>LDUX</code>.</p>\\n\",\"fift\":\"LDGRAMS\\nLDVARUINT16\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA00\",\"stack\":\"s - x s'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_load_var_integer\",\"line\":1453,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"LDGRAMS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA01\",\"tlb\":\"#FA01\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_currency\",\"description\":\"<p>Similar to <code>LDVARUINT16</code>, but loads a <em>signed</em> <em>Integer</em> <code>x</code>.\\nApproximately equivalent to <code>4 LDU</code> <code>SWAP</code> <code>3 LSHIFT#</code> <code>LDIX</code>.</p>\\n\",\"fift\":\"LDVARINT16\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA01\",\"stack\":\"s - x s'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_load_var_integer\",\"line\":1453,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"LDVARINT16\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA02\",\"tlb\":\"#FA02\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_currency\",\"description\":\"<p>Stores (serializes) an <em>Integer</em> <code>x</code> in the range <code>0...2^120-1</code> into <em>Builder</em> <code>b</code>, and returns the resulting <em>Builder</em> <code>b'</code>. The serialization of <code>x</code> consists of a 4-bit unsigned big-endian integer <code>l</code>, which is the smallest integer <code>l&gt;=0</code>, such that <code>x&lt;2^(8l)</code>, followed by an <code>8l</code>-bit unsigned big-endian representation of <code>x</code>. If <code>x</code> does not belong to the supported range, a range check exception is thrown.</p>\\n\",\"fift\":\"STGRAMS\\nSTVARUINT16\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA02\",\"stack\":\"b x - b'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_store_var_integer\",\"line\":1474,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"STGRAMS\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA03\",\"tlb\":\"#FA03\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_currency\",\"description\":\"<p>Similar to <code>STVARUINT16</code>, but serializes a <em>signed</em> <em>Integer</em> <code>x</code> in the range <code>-2^119...2^119-1</code>.</p>\\n\",\"fift\":\"STVARINT16\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA03\",\"stack\":\"b x - b'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_store_var_integer\",\"line\":1474,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"STVARINT16\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA04\",\"tlb\":\"#FA04\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_currency\",\"description\":\"<p>Loads (deserializes) a <code>VarUInteger 32</code> amount from <em>Slice</em> <code>s</code>, and returns the amount as <em>Integer</em> <code>x</code> along with the remainder <code>s'</code> of <code>s</code>. The expected serialization of <code>x</code> consists of a 5-bit unsigned big-endian integer <code>l</code>, followed by an <code>8l</code>-bit unsigned big-endian representation of <code>x</code>.\\nThe net effect is approximately equivalent to <code>4 LDU</code> <code>SWAP</code> <code>3 LSHIFT#</code> <code>LDUX</code>.</p>\\n\",\"fift\":\"LDVARUINT32\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA04\",\"stack\":\"s - x s'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_load_var_integer\",\"line\":1453,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"LDVARUINT32\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA05\",\"tlb\":\"#FA05\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_currency\",\"description\":\"<p>Similar to <code>LDVARUINT32</code>, but loads a <em>signed</em> <em>Integer</em> <code>x</code>.\\nApproximately equivalent to <code>5 LDU</code> <code>SWAP</code> <code>3 LSHIFT#</code> <code>LDIX</code>.</p>\\n\",\"fift\":\"LDVARINT32\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA05\",\"stack\":\"s - x s'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_load_var_integer\",\"line\":1453,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"LDVARINT32\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA06\",\"tlb\":\"#FA06\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_currency\",\"description\":\"<p>Stores (serializes) an <em>Integer</em> <code>x</code> in the range <code>0...2^248-1</code> into <em>Builder</em> <code>b</code>, and returns the resulting <em>Builder</em> <code>b'</code>. The serialization of <code>x</code> consists of a 5-bit unsigned big-endian integer <code>l</code>, which is the smallest integer <code>l&gt;=0</code>, such that <code>x&lt;2^(8l)</code>, followed by an <code>8l</code>-bit unsigned big-endian representation of <code>x</code>. If <code>x</code> does not belong to the supported range, a range check exception is thrown.</p>\\n\",\"fift\":\"STVARUINT32\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA06\",\"stack\":\"b x - b'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_store_var_integer\",\"line\":1474,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"STVARUINT32\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA07\",\"tlb\":\"#FA07\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_currency\",\"description\":\"<p>Similar to <code>STVARUINT32</code>, but serializes a <em>signed</em> <em>Integer</em> <code>x</code> in the range <code>-2^247...2^247-1</code>.</p>\\n\",\"fift\":\"STVARINT32\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA07\",\"stack\":\"b x - b'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_store_var_integer\",\"line\":1474,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"STVARINT32\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA40\",\"tlb\":\"#FA40\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_addr\",\"description\":\"<p>Loads from <em>Slice</em> <code>s</code> the only prefix that is a valid <code>MsgAddress</code>, and returns both this prefix <code>s'</code> and the remainder <code>s''</code> of <code>s</code> as slices.</p>\\n\",\"fift\":\"LDMSGADDR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA40\",\"stack\":\"s - s' s''\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_load_message_addr\",\"line\":1536,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"LDMSGADDR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA41\",\"tlb\":\"#FA41\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_addr\",\"description\":\"<p>A quiet version of <code>LDMSGADDR</code>: on success, pushes an extra <code>-1</code>; on failure, pushes the original <code>s</code> and a zero.</p>\\n\",\"fift\":\"LDMSGADDRQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA41\",\"stack\":\"s - s' s'' -1 or s 0\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_load_message_addr\",\"line\":1536,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"LDMSGADDRQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s3\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA42\",\"tlb\":\"#FA42\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_addr\",\"description\":\"<p>Decomposes <em>Slice</em> <code>s</code> containing a valid <code>MsgAddress</code> into a <em>Tuple</em> <code>t</code> with separate fields of this <code>MsgAddress</code>. If <code>s</code> is not a valid <code>MsgAddress</code>, a cell deserialization exception is thrown.</p>\\n\",\"fift\":\"PARSEMSGADDR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA42\",\"stack\":\"s - t\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_parse_message_addr\",\"line\":1629,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"PARSEMSGADDR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA43\",\"tlb\":\"#FA43\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_addr\",\"description\":\"<p>A quiet version of <code>PARSEMSGADDR</code>: returns a zero on error instead of throwing an exception.</p>\\n\",\"fift\":\"PARSEMSGADDRQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA43\",\"stack\":\"s - t -1 or 0\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_parse_message_addr\",\"line\":1629,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"PARSEMSGADDRQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"t\",\"type\":\"simple\",\"value_types\":[\"Tuple\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA44\",\"tlb\":\"#FA44\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_addr\",\"description\":\"<p>Parses <em>Slice</em> <code>s</code> containing a valid <code>MsgAddressInt</code> (usually a <code>msg_addr_std</code>), applies rewriting from the <code>anycast</code> (if present) to the same-length prefix of the address, and returns both the workchain <code>x</code> and the 256-bit address <code>y</code> as integers. If the address is not 256-bit, or if <code>s</code> is not a valid serialization of <code>MsgAddressInt</code>, throws a cell deserialization exception.</p>\\n\",\"fift\":\"REWRITESTDADDR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA44\",\"stack\":\"s - x y\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_rewrite_message_addr\",\"line\":1669,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"REWRITESTDADDR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA45\",\"tlb\":\"#FA45\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_addr\",\"description\":\"<p>A quiet version of primitive <code>REWRITESTDADDR</code>.</p>\\n\",\"fift\":\"REWRITESTDADDRQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA45\",\"stack\":\"s - x y -1 or 0\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_rewrite_message_addr\",\"line\":1669,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"REWRITESTDADDRQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA46\",\"tlb\":\"#FA46\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_addr\",\"description\":\"<p><code>msg_addr_var</code> not allowed since TVM v10, so it behaves like <code>REWRITESTDADDR</code>, but returns account id in <code>Slice</code>, not <code>Integer</code>: parses address <code>s</code> into workchain <code>x</code> and account id <code>s</code>.</p>\\n\",\"fift\":\"REWRITEVARADDR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA46\",\"stack\":\"s - x s'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_rewrite_message_addr\",\"line\":1669,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"REWRITEVARADDR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA47\",\"tlb\":\"#FA47\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_addr\",\"description\":\"<p>A quiet version of primitive <code>REWRITEVARADDR</code>.</p>\\n\",\"fift\":\"REWRITEVARADDRQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA47\",\"stack\":\"s - x s' -1 or 0\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_rewrite_message_addr\",\"line\":1669,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"REWRITEVARADDRQ\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[],\"value\":0},{\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"s'\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA48\",\"tlb\":\"#FA48\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_addr\",\"description\":\"<p>Loads <code>addr_std$10</code>, if address is not <code>addr_std</code>, throws an error 9 (<code>cannot load a MsgAddressInt</code>).</p>\\n\",\"fift\":\"LDSTDADDR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA48\",\"stack\":\"s - a s'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_load_std_message_addr\",\"line\":1568,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/f58297f1b668c7b49e8b30b65062951ca7c18acc/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"LDSTDADDR\",\"since_version\":12,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"a\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA49\",\"tlb\":\"#FA49\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_addr\",\"description\":\"<p>A quiet version of primitive <code>LDSTDADDR</code>.</p>\\n\",\"fift\":\"LDSTDADDRQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA49\",\"stack\":\"s - a s' -1 or s 0\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_load_std_message_addr\",\"line\":1568,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/f58297f1b668c7b49e8b30b65062951ca7c18acc/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"LDSTDADDRQ\",\"since_version\":12,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"a\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"s'\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA50\",\"tlb\":\"#FA50\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_addr\",\"description\":\"<p>Loads <code>addr_std$10</code> or <code>addr_none$00</code>, if address is <code>addr_none$00</code> pushes a Null, if address is not <code>addr_std</code> or <code>addr_none</code>, throws an error 9 (<code>cannot load a MsgAddressInt</code>).</p>\\n\",\"fift\":\"LDOPTSTDADDR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA50\",\"stack\":\"s - a s'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_load_opt_std_message_addr\",\"line\":1586,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/f58297f1b668c7b49e8b30b65062951ca7c18acc/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"LDOPTSTDADDR\",\"since_version\":12,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"a\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"s2\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA51\",\"tlb\":\"#FA51\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_addr\",\"description\":\"<p>A quiet version of primitive <code>LDOPTSTDADDR</code>.</p>\\n\",\"fift\":\"LDOPTSTDADDRQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA51\",\"stack\":\"s - a s' -1 or s 0\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_load_opt_std_message_addr\",\"line\":1586,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/f58297f1b668c7b49e8b30b65062951ca7c18acc/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"LDOPTSTDADDRQ\",\"since_version\":12,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"s\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":0},{\"stack\":[{\"name\":\"a\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"s'\",\"type\":\"simple\",\"value_types\":[\"Slice\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA52\",\"tlb\":\"#FA52\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_addr\",\"description\":\"<p>Stores <code>addr_std$10</code>, if address is not <code>addr_std</code>, throws an error 9 (<code>cannot load a MsgAddressInt</code>).</p>\\n\",\"fift\":\"STSTDADDR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA52\",\"stack\":\"a b - b'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_store_std_address\",\"line\":1822,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/f58297f1b668c7b49e8b30b65062951ca7c18acc/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"STSTDADDR\",\"since_version\":12,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"a\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA53\",\"tlb\":\"#FA53\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_addr\",\"description\":\"<p>A quiet version of primitive <code>STSTDADDR</code>.</p>\\n\",\"fift\":\"STSTDADDRQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA53\",\"stack\":\"a b - b' 0 or a b -1\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_store_std_address\",\"line\":1822,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/f58297f1b668c7b49e8b30b65062951ca7c18acc/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"STSTDADDRQ\",\"since_version\":12,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"a\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":0},{\"stack\":[{\"name\":\"a\",\"type\":\"simple\",\"value_types\":[\"Slice\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA54\",\"tlb\":\"#FA54\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_addr\",\"description\":\"<p>stores <code>addr_std$10</code> or Null. Null is stored as <code>addr_none$00</code>, if address is not <code>addr_std</code>, throws an error 9 (<code>cannot load a MsgAddressInt</code>).</p>\\n\",\"fift\":\"STOPTSTDADDR\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA54\",\"stack\":\"a b - b'\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_store_opt_std_address\",\"line\":1855,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/f58297f1b668c7b49e8b30b65062951ca7c18acc/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"STOPTSTDADDR\",\"since_version\":12,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"a\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FA55\",\"tlb\":\"#FA55\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_addr\",\"description\":\"<p>A quiet version of primitive <code>STOPTSTDADDR</code>.</p>\\n\",\"fift\":\"STOPTSTDADDRQ\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FA55\",\"stack\":\"a b - b' 0 or a b -1\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_store_opt_std_address\",\"line\":1855,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/f58297f1b668c7b49e8b30b65062951ca7c18acc/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"STOPTSTDADDRQ\",\"since_version\":12,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"a\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}]},\"outputs\":{\"registers\":[],\"stack\":[{\"match\":[{\"stack\":[{\"name\":\"b2\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":0},{\"stack\":[{\"name\":\"a\",\"type\":\"simple\",\"value_types\":[\"Slice\",\"Null\"]},{\"name\":\"b\",\"type\":\"simple\",\"value_types\":[\"Builder\"]}],\"value\":-1}],\"name\":\"status\",\"type\":\"conditional\"},{\"name\":\"status\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FB00\",\"tlb\":\"#FB00\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_actions\",\"description\":\"<p>Sends a raw message contained in <em>Cell <code>c</code></em>, which should contain a correctly serialized object <code>Message X</code>, with the only exception that the source address is allowed to have dummy value <code>addr_none</code> (to be automatically replaced with the current smart-contract address), and <code>ihr_fee</code>, <code>fwd_fee</code>, <code>created_lt</code> and <code>created_at</code> fields can have arbitrary values (to be rewritten with correct values during the action phase of the current transaction). Integer parameter <code>x</code> contains the flags. Currently <code>x=0</code> is used for ordinary messages; <code>x=128</code> is used for messages that are to carry all the remaining balance of the current smart contract (instead of the value originally indicated in the message); <code>x=64</code> is used for messages that carry all the remaining value of the inbound message in addition to the value initially indicated in the new message (if bit 0 is not set, the gas fees are deducted from this amount); <code>x'=x+1</code> means that the sender wants to pay transfer fees separately; <code>x'=x+2</code> means that any errors arising while processing this message during the action phase should be ignored. Finally, <code>x'=x+32</code> means that the current account must be destroyed if its resulting balance is zero. This flag is usually employed together with <code>+128</code>.</p>\\n\",\"fift\":\"SENDRAWMSG\",\"fift_examples\":[],\"gas\":\"526\",\"opcode\":\"FB00\",\"stack\":\"c x - \"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_send_raw_message\",\"line\":1762,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"SENDRAWMSG\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":5,\"type\":\"constant\"}],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[{\"index\":5,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FB02\",\"tlb\":\"#FB02\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_actions\",\"description\":\"<p>Creates an output action which would reserve exactly <code>x</code> nanograms (if <code>y=0</code>), at most <code>x</code> nanograms (if <code>y=2</code>), or all but <code>x</code> nanograms (if <code>y=1</code> or <code>y=3</code>), from the remaining balance of the account. It is roughly equivalent to creating an outbound message carrying <code>x</code> nanograms (or <code>b-x</code> nanograms, where <code>b</code> is the remaining balance) to oneself, so that the subsequent output actions would not be able to spend more money than the remainder. Bit <code>+2</code> in <code>y</code> means that the external action does not fail if the specified amount cannot be reserved; instead, all remaining balance is reserved. Bit <code>+8</code> in <code>y</code> means <code>x:=-x</code> before performing any further actions. Bit <code>+4</code> in <code>y</code> means that <code>x</code> is increased by the original balance of the current account (before the compute phase), including all extra currencies, before performing any other checks and actions. Currently <code>x</code> must be a non-negative integer, and <code>y</code> must be in the range <code>0...15</code>.</p>\\n\",\"fift\":\"RAWRESERVE\",\"fift_examples\":[],\"gas\":\"526\",\"opcode\":\"FB02\",\"stack\":\"x y - \"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_reserve_raw\",\"line\":2035,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"RAWRESERVE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":5,\"type\":\"constant\"}],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[{\"index\":5,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FB03\",\"tlb\":\"#FB03\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_actions\",\"description\":\"<p>Similar to <code>RAWRESERVE</code>, but also accepts a dictionary <code>D</code> (represented by a <em>Cell</em> or <em>Null</em>) with extra currencies. In this way currencies other than Grams can be reserved.</p>\\n\",\"fift\":\"RAWRESERVEX\",\"fift_examples\":[],\"gas\":\"526\",\"opcode\":\"FB03\",\"stack\":\"x D y - \"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_reserve_raw\",\"line\":2035,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"RAWRESERVEX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":5,\"type\":\"constant\"}],\"stack\":[{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"D\",\"type\":\"simple\",\"value_types\":[\"Cell\",\"Null\"]},{\"name\":\"y\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[{\"index\":5,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FB04\",\"tlb\":\"#FB04\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_actions\",\"description\":\"<p>Creates an output action that would change this smart contract code to that given by <em>Cell</em> <code>c</code>. Notice that this change will take effect only after the successful termination of the current run of the smart contract.</p>\\n\",\"fift\":\"SETCODE\",\"fift_examples\":[],\"gas\":\"526\",\"opcode\":\"FB04\",\"stack\":\"c - \"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_set_code\",\"line\":2059,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"SETCODE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":5,\"type\":\"constant\"}],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]}]},\"outputs\":{\"registers\":[{\"index\":5,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FB06\",\"tlb\":\"#FB06\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_actions\",\"description\":\"<p>Creates an output action that would modify the collection of this smart contract libraries by adding or removing library with code given in <em>Cell</em> <code>c</code>. If <code>x=0</code>, the library is actually removed if it was previously present in the collection (if not, this action does nothing). If <code>x=1</code>, the library is added as a private library, and if <code>x=2</code>, the library is added as a public library (and becomes available to all smart contracts if the current smart contract resides in the masterchain); if the library was present in the collection before, its public/private status is changed according to <code>x</code>. Values of <code>x</code> other than <code>0...2</code> are invalid.</p>\\n\",\"fift\":\"SETLIBCODE\",\"fift_examples\":[],\"gas\":\"526\",\"opcode\":\"FB06\",\"stack\":\"c x - \"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_set_lib_code\",\"line\":2071,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"SETLIBCODE\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":5,\"type\":\"constant\"}],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[{\"index\":5,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FB07\",\"tlb\":\"#FB07\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_actions\",\"description\":\"<p>Creates an output action similarly to <code>SETLIBCODE</code>, but instead of the library code accepts its hash as an unsigned 256-bit integer <code>h</code>. If <code>x!=0</code> and the library with hash <code>h</code> is absent from the library collection of this smart contract, this output action will fail.</p>\\n\",\"fift\":\"CHANGELIB\",\"fift_examples\":[],\"gas\":\"526\",\"opcode\":\"FB07\",\"stack\":\"h x - \"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_change_lib\",\"line\":2095,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"CHANGELIB\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":5,\"type\":\"constant\"}],\"stack\":[{\"name\":\"h\",\"type\":\"simple\",\"value_types\":[\"Integer\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[{\"index\":5,\"type\":\"constant\"}],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FB08\",\"tlb\":\"#FB08\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"app_actions\",\"description\":\"<p>Creates an output action and returns a fee for creating a message. Mode has the same effect as in the case of <code>SENDRAWMSG</code>. Additionally <code>+1024</code> means - do not create an action, only estimate fee. Other modes affect the fee calculation as follows: <code>+64</code> substitutes the entire balance of the incoming message as an outcoming value (slightly inaccurate, gas expenses that cannot be estimated before the computation is completed are not taken into account), <code>+128</code> substitutes the value of the entire balance of the contract before the start of the computation phase (slightly inaccurate, since gas expenses that cannot be estimated before the completion of the computation phase are not taken into account).</p>\\n\",\"fift\":\"SENDMSG\",\"fift_examples\":[],\"gas\":\"526\",\"opcode\":\"FB08\",\"stack\":\"c x - fee\"},\"implementation\":[{\"file\":\"tonops.cpp\",\"function_name\":\"exec_send_message\",\"line\":1800,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/tonops.cpp\"}],\"mnemonic\":\"SENDMSG\",\"since_version\":4,\"value_flow\":{\"inputs\":{\"registers\":[{\"index\":5,\"type\":\"constant\"}],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Cell\"]},{\"name\":\"x\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[{\"index\":5,\"type\":\"constant\"}],\"stack\":[{\"name\":\"fee\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":14,\"min_value\":0,\"name\":\"i\",\"size\":4,\"type\":\"uint\"},{\"display_hints\":[],\"max_value\":15,\"min_value\":0,\"name\":\"j\",\"size\":4,\"type\":\"uint\"}],\"operands_range_check\":{\"from\":0,\"length\":4,\"to\":14},\"prefix\":\"FE\",\"tlb\":\"#FE i:(#<= 14) j:(## 4)\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"debug\",\"description\":\"\",\"fift\":\"{i*16+j} DEBUG\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FEij\",\"stack\":\"-\"},\"implementation\":[{\"file\":\"debugops.cpp\",\"function_name\":\"exec_dummy_debug\",\"line\":35,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/debugops.cpp\"}],\"mnemonic\":\"DEBUG\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"bits_length_var_size\":4,\"bits_padding\":8,\"completion_tag\":false,\"display_hints\":[],\"max_bits\":128,\"max_refs\":0,\"min_bits\":8,\"min_refs\":0,\"name\":\"s\",\"type\":\"subslice\"}],\"prefix\":\"FEF\",\"tlb\":\"#FEF n:(## 4) ssss:((n * 8 + 8) * Bit)\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"debug\",\"description\":\"<p><code>0 &lt;= n &lt; 16</code>. Length of <code>ssss</code> is <code>n+1</code> bytes.\\n<code>{string}</code> is a <a href=\\\"https://github.com/Piterden/TON-docs/blob/master/Fift.%20A%20Brief%20Introduction.md#user-content-29-string-literals\\\">string literal</a>.\\n<code>DEBUGSTR</code>: <code>ssss</code> is the given string.\\n<code>DEBUGSTRI</code>: <code>ssss</code> is one-byte integer <code>0 &lt;= x &lt;= 255</code> followed by the given string.</p>\\n\",\"fift\":\"{string} DEBUGSTR\\n{string} {x} DEBUGSTRI\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FEFnssss\",\"stack\":\"-\"},\"implementation\":[{\"file\":\"debugops.cpp\",\"function_name\":\"exec_dummy_debug_str\",\"line\":41,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/debugops.cpp\"}],\"mnemonic\":\"DEBUGSTR\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[],\"max_value\":239,\"min_value\":0,\"name\":\"n\",\"size\":8,\"type\":\"uint\"}],\"operands_range_check\":{\"from\":0,\"length\":8,\"to\":239},\"prefix\":\"FF\",\"tlb\":\"#FF nn:(#<= 239)\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"codepage\",\"description\":\"<p>Selects TVM codepage <code>0 &lt;= nn &lt; 240</code>. If the codepage is not supported, throws an invalid opcode exception.</p>\\n\",\"fift\":\"[nn] SETCP\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FFnn\",\"stack\":\"-\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_set_cp\",\"line\":1237,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"SETCP\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[{\"display_hints\":[{\"type\":\"add\",\"value\":-16}],\"max_value\":15,\"min_value\":1,\"name\":\"z\",\"size\":4,\"type\":\"uint\"}],\"operands_range_check\":{\"from\":1,\"length\":4,\"to\":15},\"prefix\":\"FFF\",\"tlb\":\"#FFF z:(## 4) {1 <= z}\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"codepage\",\"description\":\"<p>Selects TVM codepage <code>z-16</code> for <code>1 &lt;= z &lt;= 15</code>. Negative codepages <code>-13...-1</code> are reserved for restricted versions of TVM needed to validate runs of TVM in other codepages. Negative codepage <code>-14</code> is reserved for experimental codepages, not necessarily compatible between different TVM implementations, and should be disabled in the production versions of TVM.</p>\\n\",\"fift\":\"[z-16] SETCP\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FFFz\",\"stack\":\"-\"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_set_cp\",\"line\":1237,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"SETCP_SPECIAL\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[]},\"outputs\":{\"registers\":[],\"stack\":[]}}},{\"bytecode\":{\"operands\":[],\"prefix\":\"FFF0\",\"tlb\":\"#FFF0\"},\"control_flow\":{\"branches\":[],\"nobranch\":true},\"doc\":{\"category\":\"codepage\",\"description\":\"<p>Selects codepage <code>c</code> with <code>-2^15 &lt;= c &lt; 2^15</code> passed in the top of the stack.</p>\\n\",\"fift\":\"SETCPX\",\"fift_examples\":[],\"gas\":\"26\",\"opcode\":\"FFF0\",\"stack\":\"c - \"},\"implementation\":[{\"file\":\"contops.cpp\",\"function_name\":\"exec_set_cp_any\",\"line\":1243,\"path\":\"https://raw.githubusercontent.com/ton-blockchain/ton/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/vm/contops.cpp\"}],\"mnemonic\":\"SETCPX\",\"since_version\":0,\"value_flow\":{\"inputs\":{\"registers\":[],\"stack\":[{\"name\":\"c\",\"type\":\"simple\",\"value_types\":[\"Integer\"]}]},\"outputs\":{\"registers\":[],\"stack\":[]}}}]}"
  },
  {
    "path": "scripts/check-navigation.mjs",
    "content": "/*─────────────────────────────────────────────────────────────────────────────╗\n│                                  IMPORTANT:                                  │\n│  Run this script from the root of the docs, not from the scripts directory!  │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│  The script can check:                                                       │\n│  1. Uniqueness of navigation paths                                           │\n│  2. Existence of .mdx files on navigation paths                              │\n│  3. Coverage of .mdx files by navigation structure in docs.json              │\n│                                                                              │\n│  By default, it checks all, but to only check one specify `unique`,          │\n│  `exist` or `coverage` as a command-line argument, respectively.             │\n│                                                                              │\n│  For example, this command will run the 1st check only:                      │\n│  $ node scripts/check-navigation.mjs unique                                  │\n╚─────────────────────────────────────────────────────────────────────────────*/\n\n// Node.js\nimport { existsSync, statSync } from 'node:fs';\n\n// Common utils\nimport {\n  composeSuccess,\n  composeWarningList,\n  composeErrorList,\n  prefixWithSlash,\n  getNavLinks,\n  getNavLinksSet,\n  getConfig,\n  findUnignoredFiles,\n  initMdxParser,\n  hasStub,\n} from './common.mjs';\n\n/**\n * Types\n * @typedef {import('./common.mjs').DocsConfig} DocsConfig\n * @typedef {import('./common.mjs').CheckResult} CheckResult\n */\n\n/**\n * Check that all navigation paths are unique.\n *\n * @param config {Readonly<DocsConfig>} Local docs.json configuration\n * @return {CheckResult}\n */\nconst checkUnique = (config) => {\n  const navLinksSet = getNavLinksSet(config);\n  const navLinks = getNavLinks(config);\n  if (navLinks.length != navLinksSet.size) {\n    const duplicates = navLinks.filter(\n      (val, idx) => navLinks.indexOf(val) !== idx && navLinks.indexOf(val, idx + 1) === -1\n    );\n    return {\n      ok: false,\n      error: composeErrorList(\n        'Found duplicate navigation paths:',\n        duplicates,\n        'Navigation paths in docs.json must be unique!',\n      ),\n    };\n  }\n  // Otherwise\n  return { ok: true };\n};\n/**\n * Check that all navigation .mdx pages exist.\n *\n * @param config {Readonly<DocsConfig>} Local docs.json configuration\n * @return {CheckResult}\n */\nconst checkExist = (config) => {\n  const uniqPages = [...getNavLinksSet(config)];\n  const missingPages = uniqPages.filter((it) => {\n    const rel = it.replace(/^\\/+/, '').replace(/#.*$/, '') + '.mdx';\n    return !(existsSync(rel) && statSync(rel).isFile());\n  });\n  if (missingPages.length !== 0) {\n    return {\n      ok: false,\n      error: composeErrorList(\n        'Nonexistent paths found:',\n        missingPages,\n        'Some navigation paths in docs.json point to nonexisting .mdx pages!',\n      ),\n    };\n  }\n  // Otherwise\n  return { ok: true };\n};\n\n/**\n * Check that all existing non-API .mdx pages are covered by `config`.\n *\n * @param config {Readonly<DocsConfig>} Local docs.json configuration\n * @return {Promise<CheckResult>}\n */\nconst checkCover = async (config) => {\n  const uniqPages = getNavLinksSet(config);\n  const parser = await initMdxParser();\n  /** @type string[] */\n  const stubPages = [];\n\n  /** Non-API, non-snippet .mdx pages, excluding the root index.mdx */\n  const allRelevantMdxPages = findUnignoredFiles('mdx');\n  const forgottenPages = allRelevantMdxPages.filter((it) => {\n    // Present in the navigation\n    if (uniqPages.has(prefixWithSlash(it.replace(/\\.mdx$/, '')))) {\n      return false;\n    }\n    // Lost from the navigation and not a stub\n    if (!hasStub(parser, it)) {\n      return true;\n    }\n    // Lost from the navigation and is a stub,\n    // which makes it be a warning, not an error\n    stubPages.push(it);\n    return false;\n  });\n  if (stubPages.length !== 0) {\n    const msg = 'Found stub pages not present in docs.json navigation!';\n    console.log(composeWarningList(msg, stubPages));\n  }\n  if (forgottenPages.length !== 0) {\n    return {\n      ok: false,\n      error: composeErrorList(\n        'Missing navigation entries for the following files:',\n        forgottenPages,\n        'Some non-API and non-stub .mdx pages are not present in docs.json!',\n      ),\n    };\n  }\n  // Otherwise\n  return { ok: true };\n};\n\nconst main = async () => {\n  const config = getConfig();\n  console.log(); // intentional break\n\n  // Running either one check or all checks\n  const rawArgs = process.argv.slice(2);\n  const argUnique = rawArgs.includes('unique'); // all references are unique\n  const argExist = rawArgs.includes('exist'); // all referenced .mdx files exist\n  const argCover = rawArgs.includes('cover'); // all .mdx files are covered by docs.json\n  const args = [argUnique, argCover, argExist];\n  const shouldRunAll = args.every((it) => it) || args.every((it) => !it);\n  let errored = false;\n\n  /**\n   * @param res {CheckResult}\n   * @param rawSuccessMsg {string}\n   */\n  const handleCheckResult = (res, rawSuccessMsg) => {\n    if (!res.ok) {\n      errored = true;\n      console.log(res.error);\n    } else {\n      console.log(composeSuccess(rawSuccessMsg));\n    }\n    if (shouldRunAll) {\n      console.log(); // intentional break\n    }\n  };\n\n  if (shouldRunAll || argUnique) {\n    console.log('🏁 Checking the uniqueness of navigation paths in docs.json...');\n    handleCheckResult(checkUnique(config), 'All paths are unique.');\n  }\n\n  if (shouldRunAll || argExist) {\n    console.log('🏁 Checking the existence of navigation .mdx pages in docs.json...');\n    handleCheckResult(checkExist(config), 'All referenced pages exist.');\n  }\n\n  if (shouldRunAll || argCover) {\n    console.log('🏁 Checking the coverage of .mdx pages by docs.json...');\n    handleCheckResult(await checkCover(config), 'All non-API, regular .mdx pages without stubs are present in docs.json.');\n  }\n\n  // In case of errors, exit with code 1\n  if (errored) {\n    process.exit(1);\n  }\n};\n\nawait main();\n"
  },
  {
    "path": "scripts/check-redirects.mjs",
    "content": "/*─────────────────────────────────────────────────────────────────────────────╗\n│                                  IMPORTANT:                                  │\n│  Run this script from the root of the docs, not from the scripts directory!  │\n╞══════════════════════════════════════════════════════════════════════════════╡\n│  The script can check:                                                       │\n│  1. Uniqueness of redirect sources                                           │\n│  2. Existence of redirect destination files                                  │\n│  3. Redirects against the previous TON Documentation URLs                    │\n│  4. Redirects against the upstream docs.json structure                       │\n│                                                                              │\n│  By default, it checks all, but to only check either specify `unique`,       │\n│  `exist`, `previous` or `upstream` as a command-line argument, respectively. │\n│                                                                              │\n│  For example, this command will run the 1st check only:                      │\n│  $ node scripts/check-redirects.mjs previous                                 │\n╚─────────────────────────────────────────────────────────────────────────────*/\n\n// Node.js\nimport { existsSync, statSync, mkdtempSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { tmpdir } from 'node:os';\nimport { spawnSync } from 'node:child_process';\n\n// Common utils\nimport {\n  ansiYellow,\n  composeSuccess,\n  composeWarning,\n  composeError,\n  composeErrorList,\n  prefixWithSlash,\n  getConfig,\n  getNavLinksSet,\n  getRedirects,\n} from './common.mjs';\n\n/**\n * Types\n * @typedef {import('./common.mjs').DocsConfig} DocsConfig\n * @typedef {import('./common.mjs').Sidebars} Sidebars\n * @typedef {import('./common.mjs').SidebarItem} SidebarItem\n * @typedef {import('./common.mjs').CheckResult} CheckResult\n */\n\n/**\n * Check that all sources in the redirects array are unique,\n * don't point to themselves, and don't override the existing structure paths\n *\n * @param config {Readonly<DocsConfig>} Local docs.json configuration\n * @return {CheckResult}\n */\nconst checkUnique = (config) => {\n  const redirects = getRedirects(config);\n  const redirectSources = redirects.map((it) => it.source);\n  const duplicates = redirectSources.filter((source, index) => redirectSources.indexOf(source) !== index);\n  /** @type string[] */\n  const errors = [];\n  if (duplicates.length !== 0) {\n    errors.push(\n      composeErrorList(\n        'Found duplicate sources in the redirects array:',\n        duplicates,\n        'Redirect sources in docs.json must be unique!',\n      ),\n    );\n  }\n  /** @param src {string} */\n  const fmt = (src) => prefixWithSlash(src).replace(/#.*$/, '').replace(/\\?.*$/, '');\n  const loops = redirects.filter((it) => fmt(it.source) == fmt(it.destination)).map((it) => it.source);\n  if (loops.length !== 0) {\n    errors.push(\n      composeErrorList(\n        'Found sources that lead to themselves, i.e., circular references:',\n        loops,\n        'Redirect sources in docs.json must not self-reference in destinations!',\n      ),\n    );\n  }\n  const navLinks = getNavLinksSet(config);\n  const navOverrides = redirectSources.filter((it) => navLinks.has(fmt(it)));\n  if (navOverrides.length !== 0) {\n    errors.push(\n      composeErrorList(\n        'Found sources that override pages in the docs.json structure:',\n        navOverrides,\n        'Redirect sources in docs.json must not replace existing paths!',\n      ),\n    );\n  }\n  // If there are any errors\n  if (errors.length !== 0) {\n    return {\n      ok: false,\n      error: errors.join('\\n...and '),\n    };\n  }\n  // Otherwise\n  return { ok: true };\n};\n\n/**\n * Check that all destinations in the redirects array point to existing files\n *\n * @param config {Readonly<DocsConfig>} Local docs.json configuration\n * @return {CheckResult}\n */\nconst checkExist = (config) => {\n  // All redirects\n  const redirects = getRedirects(config);\n\n  // Tracking found special destinations\n  const specialDestinationsExist = {\n    todos: false,\n    issues: false,\n    olderDocs: false,\n    otherGithubLinks: false,\n    wikiLinks: false,\n    eolWildcards: false,\n    otherExternalLinks: false,\n  };\n\n  /**\n   * @param path {string}\n   * @returns boolean\n   */\n  const pathIsSpecial = (path) => {\n    // Links\n    if (path.startsWith('http')) {\n      if (path.includes('github.com/ton-org/docs/issues')) {\n        specialDestinationsExist.issues = true;\n      } else if (path.includes('github.com/')) {\n        specialDestinationsExist.otherGithubLinks = true;\n      } else if (path.includes('en.wikipedia.org/')) {\n        specialDestinationsExist.wikiLinks = true;\n      } else if (path.includes('old-docs.ton.org/')) {\n        specialDestinationsExist.olderDocs = true;\n      } else {\n        specialDestinationsExist.otherExternalLinks = true;\n      }\n      return true;\n    }\n    // TODOs\n    if (path.startsWith('TODO')) {\n      specialDestinationsExist.todos = true;\n      return true;\n    }\n    // End-of-line wildcard redirects\n    if (path.endsWith('/:slug*')) {\n      specialDestinationsExist.eolWildcards = true;\n      return true;\n    }\n    // Otherwise\n    return false;\n  };\n\n  /**\n   * @param path {string}\n   * @returns {{ files: 'one'; path: string } | { files: 'many'; paths: string[] } | { files: 'none' }}\n   */\n  const pathFindFiles = (path) => {\n    const cleanedPath = path.replace(/^\\/+/, '').replace(/#.*$/, '').replace(/\\?.*$/, '');\n    const existingFiles = [\n      cleanedPath === '' ? `index.mdx` : `${cleanedPath}/index.mdx`,\n      `${cleanedPath}.mdx`,\n      `${cleanedPath}`,\n    ].filter((it) => existsSync(it) && statSync(it).isFile());\n\n    if (existingFiles.length === 0) {\n      return { files: 'none' };\n    }\n    if (existingFiles.length === 1) {\n      return { files: 'one', path: existingFiles[0] };\n    }\n    return { files: 'many', paths: existingFiles };\n  };\n\n  /**\n   * Recursively look for the destination up to N times deep.\n   * After that, the search function should forcibly terminate\n   * and produce an error with a complete trace.\n   *\n   * This is tied to the limitations of the documentation framework.\n   * DO NOT INCREASE without prior testing. Or ever.\n   */\n  const maxRecursionLevelPerRedirect = 3;\n\n  /**\n   * @param path {string}\n   * @param attemptsLeft {number}\n   * @param trace {string[]}\n   * @returns {{ ok: boolean; trace: string[] }}\n   */\n  const pathFindWithTrace = (path, attemptsLeft, trace) => {\n    if (attemptsLeft > 3) {\n      return {\n        ok: false,\n        trace: trace.concat(`Cannot have redirects more than 3 levels deep, received: ${attemptsLeft}`),\n      };\n    }\n    if (attemptsLeft <= 0) {\n      return { ok: false, trace: trace.concat(`Recursed too deep already, skipping: ${path}`) };\n    }\n    if (pathIsSpecial(path)) {\n      return { ok: true, trace: trace.concat(`The destination is special, skipping: ${path}`) };\n    }\n    const foundFiles = pathFindFiles(path);\n    if (foundFiles.files === 'one') {\n      return { ok: true, trace: trace.concat(`Found a file under the destination: ${path} → ${foundFiles.path}`) };\n    }\n    if (foundFiles.files === 'many') {\n      return {\n        ok: false,\n        trace: trace.concat(\n          `Multiple files found under the same destination: ${path} → ${foundFiles.paths.join(', ')}`,\n        ),\n      };\n    }\n    // None, need to look in redirect sources or bail.\n    const redirectSource = redirects.find((it) => it.source === path.replace(/#.*$/, ''));\n    if (!redirectSource) {\n      return {\n        ok: false,\n        trace: trace.concat(`No file nor a deeper redirect found for this destination: ${path}`),\n      };\n    }\n    // Otherwise, perform the next iteration with the new destination path.\n    return pathFindWithTrace(redirectSource.destination, attemptsLeft - 1, trace.concat(path));\n  };\n\n  // Main part\n  const uniqDests = [...new Set(redirects.map((it) => it.destination))];\n  const processedDests = uniqDests.map((it) => pathFindWithTrace(it, maxRecursionLevelPerRedirect, []));\n  const invalidatedTraces = processedDests\n    .filter((it) => {\n      if (process.env.DEBUG && process.env.DEBUG === 'true') {\n        console.log(it);\n      }\n      // Trace must be non-zero\n      return !it.ok && it.trace.length !== 0;\n    })\n    .map((it) => it.trace);\n  if (specialDestinationsExist.issues) {\n    console.log(composeWarning('Found GitHub docs repo issue destinations!'));\n  }\n  if (specialDestinationsExist.todos) {\n    console.log(composeWarning('Found TODO-prefixed destinations!'));\n  }\n  if (specialDestinationsExist.olderDocs) {\n    console.log(composeWarning('Found destinations that point to old-docs.ton.org!'));\n  }\n  // NOTE: this and other special destinations are not currently needed, but their checks must be required in the future.\n  // if (specialDestinationsExist.otherExternalLinks) {\n  //   console.log(composeWarning('Found third-party URLs outside of GitHub or English Wikipedia!'));\n  // }\n  if (invalidatedTraces.length !== 0) {\n    return {\n      ok: false,\n      error: composeErrorList(\n        'Unreachable or nonexistent redirect destinations found:',\n        invalidatedTraces.map((it) => {\n          if (it.length === 1) {\n            return it.join('');\n          }\n          return it.slice(0, -1).join('\\n  → ') + '\\n  → ' + it.slice(-1).join('');\n        }),\n        'Some redirect destinations in docs.json do not exist or are unreachable!',\n      ),\n    };\n  }\n  // Otherwise\n  return { ok: true };\n};\n\n/**\n * Check redirects against the previous TON Documentation URLs.\n * Ensures that old routes point to new files or even anchors.\n *\n * @param td {string} Temporary directory path\n * @param config {Readonly<DocsConfig>} Parsed docs.json configuration\n * @return {Promise<CheckResult>}\n */\nconst checkPrevious = async (td, config) => {\n  // 1. Clone previous TON Docs in a temporary directory\n  //    in order to obtain the sidebars.js module\n  const tonDocsPath = join(td, 'ton-docs');\n  const cloneRes = spawnSync('git', ['clone', '--depth=1', 'https://github.com/ton-community/ton-docs', tonDocsPath], {\n    encoding: 'utf8',\n    timeout: 1_000 * 60 * 10,\n  });\n  if (cloneRes.status != 0) {\n    return {\n      ok: false,\n      error: `${cloneRes.error ?? cloneRes.stdout}`,\n    };\n  }\n\n  // 2. Process sidebars.js and extract all URLs\n  const sidebarsPath = join(tonDocsPath, 'sidebars.js');\n  if (!existsSync(sidebarsPath)) {\n    return {\n      ok: false,\n      error: composeError(`sidebars.js was not found in ${tonDocsPath}`),\n    };\n  }\n  /** @type Readonly<Sidebars> */\n  const sidebarsModule = Object.freeze((await import(sidebarsPath)).default);\n  const sidebarsKeys = Object.keys(sidebarsModule);\n  /** @type string[] */\n  const prevLinks = [];\n  sidebarsKeys.forEach((key) => {\n    const sidebar = sidebarsModule[key];\n    /** @param sb {SidebarItem} */\n    const processItem = (sb) => {\n      if (typeof sb === 'string') {\n        prevLinks.push(prefixWithSlash(sb));\n        return;\n      }\n      switch (sb.type) {\n        case 'doc':\n        case 'ref':\n          prevLinks.push(prefixWithSlash(sb.id));\n          break;\n        case 'link':\n          if (sb.href.startsWith('/') || !sb.href.startsWith('http')) {\n            prevLinks.push(prefixWithSlash(sb.href));\n          }\n          break;\n        case 'category':\n          if (sb.link) {\n            if (sb.link.type === 'doc') {\n              prevLinks.push(prefixWithSlash(sb.link.id));\n            } else if (sb.link.type === 'generated-index' && sb.link.slug) {\n              prevLinks.push(prefixWithSlash(sb.link.slug));\n            }\n          }\n          sb.items.forEach(processItem);\n          break;\n        case 'autogenerated':\n        case 'html':\n        default:\n          break;\n      }\n    };\n    sidebar.forEach(processItem);\n  });\n\n  // 3. Process docs.json and compare its structure and redirects to old links\n  const currLinks = getNavLinksSet(config);\n  const prevOnlyLinks = prevLinks.filter((it) => !currLinks.has(it));\n  if (prevOnlyLinks.length === 0) {\n    return { ok: true };\n  }\n\n  const redirectSources = getRedirects(config).map((it) => it.source);\n  const missingSources = prevOnlyLinks.filter(\n    (it) =>\n      [it, it.replace(/\\/index$/, ''), it.replace(/\\/README$/, '')].some((variant) =>\n        redirectSources.includes(variant),\n      ) === false,\n  );\n  if (missingSources.length !== 0) {\n    return {\n      ok: false,\n      error: composeErrorList(\n        'Missing pages or redirects for the following URLs:',\n        missingSources,\n        'Some URLS in the previous TON Documentation do not have corresponding pages or redirect sources in the local docs.json!',\n      ),\n    };\n  }\n\n  // Otherwise\n  return { ok: true };\n};\n\n/**\n * Check redirects against the upstream docs.json structure.\n * Ensures that changes made to docs.json in the PR\n * provide necessary redirects in case local links\n * deviated from the links on the main branch.\n *\n * @param localConfig {Readonly<DocsConfig>} Local docs.json configuration\n * @return {Promise<CheckResult>}\n */\nconst checkUpstream = async (localConfig) => {\n  const response = await fetch('https://raw.githubusercontent.com/ton-org/docs/refs/heads/main/docs.json');\n\n  /** @type {DocsConfig} */\n  const upstreamConfig = Object.freeze(await response.json());\n  const upstreamNavLinks = getNavLinksSet(upstreamConfig);\n  const localNavLinks = getNavLinksSet(localConfig);\n\n  const upstreamOnlyLinks = [...upstreamNavLinks].filter((it) => !localNavLinks.has(it));\n  if (upstreamOnlyLinks.length === 0) {\n    return { ok: true };\n  }\n\n  const redirectSources = getRedirects(localConfig).map((it) => it.source);\n  const eolWildcards = redirectSources.filter((it) => it.endsWith('/:slug*')).map((it) => it.replace(/\\/:slug\\*$/, ''));\n  const missingSources = upstreamOnlyLinks.filter(\n    (it) =>\n      !redirectSources.includes(it) &&\n      !redirectSources.includes(it.replace(/\\/index$/, '')) &&\n      !eolWildcards.some((w) => it.startsWith(w)),\n  );\n  if (missingSources.length !== 0) {\n    return {\n      ok: false,\n      error: composeErrorList(\n        'Missing pages or redirects for the following upstream URLs:',\n        missingSources,\n        [\n          'Local docs.json does not have corresponding pages or redirect sources for some URLs in the upstream docs.json!',\n          `${ansiYellow('How to fix:')} if you did not rename, move, or delete any pages from docs.json, merge the latest main branch into your branch. Otherwise, add necessary redirects pointing to existing pages.`,\n        ].join('\\n'),\n      ),\n    };\n  }\n\n  // Otherwise\n  return { ok: true };\n};\n\nconst main = async () => {\n  const config = getConfig();\n  console.log(); // intentional break\n\n  // Creating the temporary directory\n  const td = mkdtempSync(join(tmpdir(), 'td'));\n\n  // Running either one check or all checks\n  const rawArgs = process.argv.slice(2);\n  const argUnique = rawArgs.includes('unique'); // all sources are unique\n  const argExist = rawArgs.includes('exist'); // all destinations exist\n  const argPrevious = rawArgs.includes('previous'); // sources cover previous TON Docs\n  const argUpstream = rawArgs.includes('upstream'); // sources cover upstream docs.json structure\n  const args = [argUnique, argExist, argPrevious, argUpstream];\n  const shouldRunAll = args.every((it) => it) || args.every((it) => !it);\n  let errored = false;\n\n  /**\n   * @param res {CheckResult}\n   * @param rawSuccessMsg {string}\n   */\n  const handleCheckResult = (res, rawSuccessMsg) => {\n    if (!res.ok) {\n      errored = true;\n      console.log(res.error);\n    } else {\n      console.log(composeSuccess(rawSuccessMsg));\n    }\n    if (shouldRunAll) {\n      console.log(); // intentional break\n    }\n  };\n\n  if (shouldRunAll || argUnique) {\n    console.log('🏁 Checking the uniqueness of redirect sources in docs.json...');\n    handleCheckResult(checkUnique(config), 'All sources are unique.');\n  }\n\n  if (shouldRunAll || argExist) {\n    console.log('🏁 Checking the existence of redirect destinations in docs.json...');\n    handleCheckResult(checkExist(config), 'All non-TODO, local destinations exist.');\n  }\n\n  if (shouldRunAll || argPrevious) {\n    console.log('🏁 Checking redirects against the previous TON Documentation...');\n    handleCheckResult(await checkPrevious(td, config), 'Full coverage.');\n  }\n\n  if (shouldRunAll || argUpstream) {\n    console.log('🏁 Checking redirects against the upstream docs.json structure...');\n    handleCheckResult(await checkUpstream(config), 'Full coverage.');\n  }\n\n  // Removing the temporary directory\n  rmSync(td, { recursive: true });\n\n  // In case of errors, exit with code 1\n  if (errored) {\n    process.exit(1);\n  }\n};\n\nawait main();\n"
  },
  {
    "path": "scripts/common.mjs",
    "content": "// Node.js\nimport { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\n\n// Remark\nimport { remark } from 'remark';\nimport { visitParents } from 'unist-util-visit-parents';\n\n/**\n * Mintlify\n * @typedef {import('../node_modules/@mintlify/validation').DocsConfig} DocsConfig\n */\n\n/**\n * Docusaurus\n * @typedef {import('./docusaurus-sidebars-types.d.ts').SidebarsConfig} Sidebars\n * @typedef {import('./docusaurus-sidebars-types.d.ts').SidebarItemConfig} SidebarItem\n * @typedef {import('./docusaurus-sidebars-types.d.ts').SidebarItemDoc} ItemDoc\n * @typedef {import('./docusaurus-sidebars-types.d.ts').SidebarItemLink} ItemLink\n * @typedef {import('./docusaurus-sidebars-types.d.ts').SidebarItemCategoryBase} ItemCat\n */\n\n/**\n * Custom\n * @typedef {{ok: true} | {ok: false; error: string}} CheckResult\n */\n\n/** @param src {string} */\nexport function ansiRed(src) {\n  return `\\x1b[31m${src}\\x1b[0m`;\n}\n\n/** @param src {string} */\nexport function ansiBoldRed(src) {\n  return `\\x1b[1;31m${src}\\x1b[0m`;\n}\n\n/** @param src {string} */\nexport function ansiGreen(src) {\n  return `\\x1b[32m${src}\\x1b[0m`;\n}\n\n/** @param src {string} */\nexport function ansiBoldGreen(src) {\n  return `\\x1b[1;32m${src}\\x1b[0m`;\n}\n\n/** @param src {string} */\nexport function ansiYellow(src) {\n  return `\\x1b[33m${src}\\x1b[0m`;\n}\n\n/** @param src {string} */\nexport function ansiBoldYellow(src) {\n  return `\\x1b[1;33m${src}\\x1b[0m`;\n}\n\n/** @param src {string} */\nexport function ansiBold(src) {\n  return `\\x1b[1m${src}\\x1b[0m`;\n}\n\n/**\n * Forms a string with the following contents:\n *\n * ```\n * brief:\n * - list[0]\n * - list[1]\n * - ...\n * - list[n - 1]\n *\n * Error: msg\n * ```\n *\n * @param brief {string} Brief description of list items\n * @param list {string[]} List of inline error messages\n * @param msg {string} Complete description of the error message\n */\nexport function composeErrorList(brief, list, msg) {\n  return [ansiRed(brief), '- ' + list.join('\\n- '), `\\n${ansiRed('Error:')} ${msg}`].join('\\n');\n}\n\n/** @param msg {string} */\nexport function composeError(msg) {\n  return `${ansiRed('Error:')} ${msg}`;\n}\n\n/**\n * Forms a string with the following contents:\n *\n * ```\n * Warning: msg\n * - list[0]\n * - list[1]\n * - ...\n * - list[n - 1]\n * ```\n *\n * @param msg {string} Complete description of the warning message\n * @param list {string[]} List of inline warning messages\n */\nexport function composeWarningList(msg, list) {\n  return [`${ansiYellow('Warning:')} ${msg}`, '- ' + list.join('\\n- ')].join('\\n');\n}\n\n/** @param msg {string} */\nexport function composeWarning(msg) {\n  return `${ansiYellow('Warning:')} ${msg}`;\n}\n\n/** @param msg {string} */\nexport function composeSuccess(msg) {\n  return `${ansiGreen('Success:')} ${msg}`;\n}\n\n/** @param src {string} */\nexport function prefixWithSlash(src) {\n  return '/' + src.replace(/^\\/+/, '');\n}\n\n/**\n * Creates the Remark parser with same settings as in `remarkConfig` inside `package.json`.\n */\nexport async function initMdxParser() {\n  const remarkConfig = (await import(join('..', '.remarkrc.mjs'))).default;\n  return remark().use(remarkConfig);\n}\n\n/**\n * Checks whether the .mdx page has (uses) a `<Stub>` React component\n * by parsing the contents of the `filepath` with the MDX `parser`\n * and exploring the resulting tree.\n *\n * @param parser {*} initialized Remark parser with MDX support enabled\n * @param filepath {string} relative path to the MDX file\n * @returns {boolean}\n */\nexport function hasStub(parser, filepath) {\n  if (!filepath.endsWith('mdx')) {\n    return false;\n  }\n  const file = readFileSync(filepath, { encoding: 'utf8' });\n  const parsed = parser.parse(file);\n  let res = false;\n  visitParents(parsed, 'mdxJsxFlowElement', (node) => {\n    if (node.name === 'Stub') {\n      res = true;\n    }\n  });\n  return res;\n}\n\n/**\n * Recursively finds files with a target extension `ext` starting from a given directory `dir`.\n * Ignores common and extension-specific irrelevant files — see the code for details.\n *\n * @param [ext='mdx'] {string} extension of the file without a leading dot; defaults to mdx\n * @param [dir='.'] {string} directory to start with, defaults to `.` (present directory, assuming the root of the repo)\n * @returns {string[]} file paths relative to `dir` or an empty array if there is none, `dir` does not exist or `ext` is empty\n */\nexport function findUnignoredFiles(ext = 'mdx', dir = '.') {\n  if (ext === '' || !existsSync(dir) || !statSync(dir).isDirectory()) {\n    return [];\n  }\n\n  /**\n   * `dir`-relative paths to common ignores.\n   * @type {{ files: string[]; dirs: string[] }}\n   */\n  const commonIgnoreMap = Object.freeze({\n    files: ['LICENSE-code', 'LICENSE-docs', 'package-lock.json'].map((it) => join(dir, it)),\n    dirs: ['.git', '.github', '.idea', '.vscode', '__MACOSX', 'node_modules', '__pycache__', 'stats'].map((it) =>\n      join(dir, it),\n    ),\n  });\n\n  /**\n   * `dir`-relative paths to extension-specific ignores.\n   * @type {{[k: string]: { files: string[]; dirs: string[] }}}\n   */\n  const extIgnoreMap = Object.freeze({\n    mdx: {\n      files: ['index.mdx', 'contribute/style-guide-extended.mdx'].map((it) => join(dir, it)),\n      dirs: [\n        // Snippets and page parts\n        'snippets',\n        'scripts',\n        'resources',\n        // Pages covered in OpenAPI specs rather than in docs.json\n        'ecosystem/api/toncenter/v2',\n        'ecosystem/api/toncenter/v3',\n        'ecosystem/api/toncenter/smc-index',\n      ].map((it) => join(dir, it)),\n    },\n  });\n\n  /** @type string[] */\n  let results = [];\n\n  /** @param subDir {string} */\n  const recurse = (subDir) => {\n    // Collects files and dirs one level deep, excluding common ignore targets\n    const intermediates = readdirSync(subDir, { withFileTypes: true, encoding: 'utf8', recursive: false }).filter(\n      (it) => {\n        const relPath = join(it.parentPath, it.name);\n        if (it.isFile()) {\n          return commonIgnoreMap.files.includes(relPath) === false;\n        }\n        if (it.isDirectory()) {\n          return commonIgnoreMap.dirs.includes(relPath) === false;\n        }\n        // Otherwise\n        return false;\n      },\n    );\n    // Processes collected items and filters out extension-specific ignore targets,\n    // recursively descending in directories and pushing files into `results` array\n    // if they match the target `ext` and are not ignored.\n    intermediates.forEach((it) => {\n      const relPath = join(it.parentPath, it.name);\n      if (it.isFile() && relPath.toLowerCase().endsWith(ext)) {\n        // Ignore extension-specific targets\n        if (extIgnoreMap.hasOwnProperty(ext) && extIgnoreMap[ext].files.includes(relPath)) {\n          return;\n        }\n        results.push(relPath);\n        return;\n      }\n      if (it.isDirectory()) {\n        // Ignore extension-specific targets\n        if (extIgnoreMap.hasOwnProperty(ext) && extIgnoreMap[ext].dirs.includes(relPath)) {\n          return;\n        }\n        recurse(relPath);\n        return;\n      }\n      // Otherwise\n      return;\n    });\n  };\n  recurse(dir);\n  return results;\n}\n\n/**\n * Get docs.json contents as an object.\n *\n * @returns {Readonly<DocsConfig>}\n */\nexport function getConfig() {\n  return Object.freeze(JSON.parse(readFileSync('./docs.json', 'utf8')));\n}\n\n/**\n * Get navigation links from the docs.json configuration.\n * Notice that each link is prefixed by a single slash /\n * regardless if it was present originally.\n *\n * @param config {DocsConfig}\n * @returns {string[]}\n */\nexport function getNavLinks(config) {\n  /** @type {string[]} */\n  const links = [];\n  /** @param page {any} */\n  const processPage = (page) => {\n    switch (typeof page) {\n      case 'string': {\n        links.push(prefixWithSlash(page));\n        break;\n      }\n      case 'object': {\n        if (page?.pages) {\n          page['pages'].forEach(processPage);\n        }\n        break;\n      }\n      default:\n        break;\n    }\n  };\n  // @ts-ignore\n  config.navigation?.pages.forEach(processPage);\n  return links;\n}\n\n/**\n * Get navigation links from the docs.json configuration as a Set.\n * Notice that each link is prefixed by a single slash /\n * regardless if it was present originally.\n *\n * @param config {DocsConfig}\n * @returns {ReadonlySet<string>}\n */\nexport function getNavLinksSet(config) {\n  return Object.freeze(new Set(getNavLinks(config)));\n}\n\n/**\n * Get redirect objects from the docs.json configuration.\n *\n * @typedef {{\n *   source: string;\n *   destination: string;\n *   permanent?: boolean | undefined\n * }} Redirect\n * @param config {DocsConfig}\n * @returns {Redirect[]}\n */\nexport function getRedirects(config) {\n  if (!config.redirects) {\n    return [];\n  }\n  return config.redirects;\n}\n\n/**\n * Get redirect objects from the docs.json configuration as a Set.\n *\n * @param config {DocsConfig}\n * @returns {ReadonlySet<Redirect>}\n */\nexport function getRedirectsSet(config) {\n  return Object.freeze(new Set(getRedirects(config)));\n}\n"
  },
  {
    "path": "scripts/docusaurus-sidebars-types.d.ts",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of: https://github.com/facebook/docusaurus\n */\n\ntype Optional<T extends object, K extends keyof T = keyof T> = Omit<T, K> &\n  Partial<Pick<T, K>>;\n\ntype Expand<T extends { [x: string]: unknown }> = { [P in keyof T]: T[P] };\n\nexport type SidebarItemBase = {\n  key?: string;\n  className?: string;\n  customProps?: { [key: string]: unknown };\n};\n\nexport type SidebarItemDoc = SidebarItemBase & {\n  type: \"doc\" | \"ref\";\n  label?: string;\n  id: string;\n  /**\n   * This is an internal marker set during the sidebar normalization process.\n   * Docs with labels defined in the config need to be translated with JSON.\n   * Otherwise, it's preferable to translate the MDX doc title or front matter.\n   */\n  translatable?: true;\n};\n\nexport type SidebarItemHtml = SidebarItemBase & {\n  type: \"html\";\n  value: string;\n  defaultStyle?: boolean;\n};\n\nexport type SidebarItemLink = SidebarItemBase & {\n  type: \"link\";\n  href: string;\n  label: string;\n  autoAddBaseUrl?: boolean;\n  description?: string;\n};\n\nexport type SidebarItemAutogenerated = SidebarItemBase & {\n  type: \"autogenerated\";\n  dirName: string;\n};\n\ntype SidebarItemCategoryBase = SidebarItemBase & {\n  type: \"category\";\n  label: string;\n  collapsed: boolean;\n  collapsible: boolean;\n  description?: string;\n};\n\nexport type SidebarItemCategoryLinkDoc = { type: \"doc\"; id: string };\n\nexport type SidebarItemCategoryLinkGeneratedIndexConfig = {\n  type: \"generated-index\";\n  slug?: string;\n  title?: string;\n  description?: string;\n  image?: string;\n  keywords?: string | readonly string[];\n};\nexport type SidebarItemCategoryLinkGeneratedIndex = {\n  type: \"generated-index\";\n  slug: string;\n  permalink: string;\n  title?: string;\n  description?: string;\n  image?: string;\n  keywords?: string | readonly string[];\n};\n\nexport type SidebarItemCategoryLinkConfig =\n  | SidebarItemCategoryLinkDoc\n  | SidebarItemCategoryLinkGeneratedIndexConfig;\n\nexport type SidebarItemCategoryLink =\n  | SidebarItemCategoryLinkDoc\n  | SidebarItemCategoryLinkGeneratedIndex;\n\n// The user-given configuration in sidebars.js, before normalization\nexport type SidebarItemCategoryConfig = Expand<\n  Optional<SidebarItemCategoryBase, \"collapsed\" | \"collapsible\"> & {\n    // items: SidebarCategoriesShorthand | SidebarItemConfig[];\n    items: SidebarItemConfig[];\n    link?: SidebarItemCategoryLinkConfig;\n  }\n>;\n\nexport type SidebarCategoriesShorthand = {\n  [sidebarCategory: string]: SidebarCategoriesShorthand | SidebarItemConfig[];\n};\n\nexport type SidebarItemConfig =\n  | Omit<SidebarItemDoc, \"translatable\">\n  | SidebarItemHtml\n  | SidebarItemLink\n  | SidebarItemAutogenerated\n  | SidebarItemCategoryConfig\n  | string\n  | SidebarCategoriesShorthand;\n\n// export type SidebarConfig = SidebarCategoriesShorthand | SidebarItemConfig[];\nexport type SidebarConfig = SidebarItemConfig[];\n\nexport type SidebarsConfig = {\n  [sidebarId: string]: SidebarConfig;\n};\n"
  },
  {
    "path": "scripts/stats.py",
    "content": "#!/usr/bin/env python3\n\"\"\"\nDocs stats tool\n\n- Reads navigation from docs.json (only visible pages)\n- Filters stubs by explicit <Stub .../> tag only\n- Counts words/images and prints a concise summary\n- Optional: history (last commit per UTC day, committer date) and simple charts\n\nUsage:\n  python3 scripts/stats.py            # latest\n  python3 scripts/stats.py latest     # same as above\n  python3 scripts/stats.py history    # build stats/history.{jsonl,csv}\n  python3 scripts/stats.py charts     # render simple charts from history.csv\n  python3 scripts/stats.py all        # latest + history + charts\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport csv\nimport json\nimport re\nimport sys\nimport subprocess\nfrom datetime import datetime, timezone\nfrom pathlib import Path\nfrom typing import Dict, List, Optional, Tuple\n\nREPO_ROOT = Path(__file__).resolve().parents[1]\nDOCS_JSON_PATH = REPO_ROOT / \"docs.json\"\nSTATS_DIR = REPO_ROOT / \"stats\"\nCHART_DIR = STATS_DIR / \"charts\"\nHISTORY_CSV = STATS_DIR / \"history.csv\"\nEXCLUDE_UTC_DAYS = {\n    \"2025-09-02\",  # temporary nav anomaly\n}\n\n\n# -------- navigation --------\ndef read_json(path: Path) -> dict:\n    return json.loads(path.read_text(\"utf-8\"))\n\n\ndef nav_slugs(docs: dict) -> List[str]:\n    pages = docs.get(\"navigation\", {}).get(\"pages\", [])\n    out: List[str] = []\n\n    def visit(node):\n        if isinstance(node, str):\n            out.append(node)\n        elif isinstance(node, dict):\n            if isinstance(node.get(\"pages\"), list):\n                for ch in node[\"pages\"]:\n                    visit(ch)\n            if isinstance(node.get(\"page\"), str):\n                out.append(node[\"page\"])\n\n    for n in pages:\n        visit(n)\n    seen = set()\n    uniq = []\n    for s in out:\n        if s not in seen:\n            seen.add(s)\n            uniq.append(s)\n    return uniq\n\n\ndef resolve_file(slug: str) -> Optional[str]:\n    for rel in (\n        f\"{slug}.mdx\",\n        f\"{slug}.md\",\n        str(Path(slug) / \"index.mdx\"),\n        str(Path(slug) / \"index.md\"),\n    ):\n        if (REPO_ROOT / rel).exists():\n            return rel\n    return None\n\n\n# -------- content helpers --------\ndef strip_frontmatter(s: str) -> str:\n    if s.startswith(\"---\"):\n        end = s.find(\"\\n---\", 3)\n        if end != -1:\n            end = s.find(\"\\n\", end + 4)\n            return s[end + 1 :] if end != -1 else s\n    return s\n\n\ndef strip_imports(s: str) -> str:\n    return re.sub(r\"^\\s*(import|export)\\s[^\\n]*$\", \" \", s, flags=re.M)\n\n\ndef split_fences(s: str) -> Tuple[str, str]:\n    \"\"\"Split content into prose (no fenced blocks) and fenced code text.\"\"\"\n    prose_lines: List[str] = []\n    code_lines: List[str] = []\n    in_fence = False\n    fence = re.compile(r\"^\\s*(```|~~~)\")\n    for line in s.splitlines():\n        if fence.match(line):\n            in_fence = not in_fence\n            continue\n        if in_fence:\n            code_lines.append(line)\n        else:\n            prose_lines.append(line)\n    return \"\\n\".join(prose_lines), \"\\n\".join(code_lines)\n\n\ndef extract_counts(s: str) -> Tuple[int, int, int]:\n    \"\"\"Return prose_words, code_block_lines, code_block_words.\n\n    Inline code policy: count words inside inline code spans, but if a span\n    contains more than 20 words, treat it as prose (drop backticks and keep\n    the content in the prose stream) rather than as special inline code.\n\n    - prose_words: words after removing fenced code and markup, plus words from\n      small inline code spans (≤ 20 words). Large spans (> 20 words) are kept in prose.\n    - code_block_lines: non-empty lines inside fenced blocks (``` or ~~~)\n    \"\"\"\n    s = strip_frontmatter(s)\n    s = strip_imports(s)\n    prose, code_blocks = split_fences(s)\n    # inline code (outside fences)\n    inline_small_words = 0\n    pattern = re.compile(r\"`([^`]+)`\")\n\n    def repl(m: re.Match) -> str:\n        nonlocal inline_small_words\n        content = m.group(1)\n        wc = len(re.findall(r\"\\w+\", content))\n        if wc > 20:\n            # treat as prose: drop backticks, keep content\n            return f\" {content} \"\n        inline_small_words += wc\n        # remove small inline span from prose; we'll add its words separately\n        return \" \"\n\n    prose = pattern.sub(repl, prose)\n    # drop images/links/tags from prose\n    prose = re.sub(r\"!\\[[^\\]]*\\]\\([^\\)]+\\)\", \" \", prose)\n    prose = re.sub(r\"\\[([^\\]]+)\\]\\([^\\)]+\\)\", r\"\\1\", prose)\n    prose = re.sub(r\"<[^>]+>\", \" \", prose)\n    prose_words = len(re.findall(r\"\\w+\", prose)) + inline_small_words\n    # count non-empty lines and words in fenced blocks\n    code_block_lines = sum(1 for ln in code_blocks.splitlines() if ln.strip())\n    code_block_words = len(re.findall(r\"\\w+\", code_blocks))\n    return prose_words, code_block_lines, code_block_words\n\n\ndef count_words(s: str) -> int:\n    return len(re.findall(r\"\\w+\", s, flags=re.UNICODE))\n\n\ndef count_images(src: str) -> int:\n    return (\n        len(re.findall(r\"!\\[[^\\]]*\\]\\([^\\)]+\\)\", src))\n        + len(re.findall(r\"<img\\b[^>]*>\", src, flags=re.I))\n        + len(re.findall(r\"<Image\\b[^>]*?/?>\", src, flags=re.I))\n    )\n\n\ndef is_stub(content: str) -> bool:\n    # Deterministic: page is a stub iff it contains <Stub .../>\n    return re.search(r\"<\\s*Stub\\b\", content, flags=re.I) is not None\n\n\n# -------- stats core --------\ndef summarize(words: List[int]) -> Dict[str, int]:\n    if not words:\n        return dict(min=0, p25=0, median=0, p75=0, max=0, average=0)\n    xs = sorted(words)\n    n = len(xs)\n\n    def pick(q: int) -> int:\n        k = max(0, min(n - 1, int((q / 100.0) * n + 0.5) - 1))\n        return xs[k]\n\n    return dict(\n        min=xs[0],\n        p25=pick(25),\n        median=pick(50),\n        p75=pick(75),\n        max=xs[-1],\n        average=round(sum(xs) / n),\n    )\n\n\ndef write_json(path: Path, obj: dict) -> None:\n    path.parent.mkdir(parents=True, exist_ok=True)\n    path.write_text(\n        json.dumps(obj, ensure_ascii=False, indent=2) + \"\\n\", encoding=\"utf-8\"\n    )\n\n\ndef run_latest() -> None:\n    docs = read_json(DOCS_JSON_PATH)\n    slugs = nav_slugs(docs)\n    pages_all: List[Dict] = []\n    stubs: List[Dict] = []\n    warnings: List[str] = []\n\n    for slug in slugs:\n        rel = resolve_file(slug)\n        if not rel:\n            warnings.append(f\"Unresolved slug: {slug}\")\n            continue\n        content = (REPO_ROOT / rel).read_text(\"utf-8\")\n        prose_words, code_block_lines, code_block_words = extract_counts(content)\n        row = {\n            \"slug\": slug,\n            \"path\": rel,\n            \"stub\": is_stub(content),\n            \"words\": prose_words,\n            \"images\": count_images(content),\n            \"codeBlockLines\": code_block_lines,\n            \"codeBlockWords\": code_block_words,\n        }\n        pages_all.append(row)\n        if row[\"stub\"]:\n            stubs.append(row)\n\n    included = [p for p in pages_all if not p[\"stub\"]]\n    totals = {\n        \"pages\": len(included),\n        \"words\": sum(p[\"words\"] for p in included),\n        \"images\": sum(p[\"images\"] for p in included),\n        \"codeBlockLines\": sum(p.get(\"codeBlockLines\", 0) for p in included),\n        \"codeBlockWords\": sum(p.get(\"codeBlockWords\", 0) for p in included),\n    }\n    dist = summarize([p[\"words\"] for p in included])\n\n    write_json(\n        STATS_DIR / \"latest.json\",\n        {\n            \"generatedAt\": datetime.now(timezone.utc).isoformat(),\n            \"totals\": totals,\n            \"distribution\": dist,\n        },\n    )\n    write_json(STATS_DIR / \"pages-latest.json\", included)\n    if stubs:\n        write_json(STATS_DIR / \"stubs-latest.json\", stubs)\n    if warnings:\n        write_json(STATS_DIR / \"warnings-latest.json\", warnings)\n\n    print(\"Docs stats (latest)\")\n    print(f\"Pages:  {totals['pages']}\")\n    print(f\"Words:  {totals['words']}\")\n    print(f\"Images: {totals['images']}\")\n    print(f\"Code block lines:  {totals['codeBlockLines']}\")\n    print(f\"Code block words:  {totals['codeBlockWords']}\")\n    print(\n        f\"Distribution: min={dist['min']} p25={dist['p25']} median={dist['median']} p75={dist['p75']} max={dist['max']} avg={dist['average']}\"\n    )\n\n\ndef git(cmd: List[str]) -> str:\n    return subprocess.check_output([\"git\", *cmd], cwd=str(REPO_ROOT)).decode(\n        \"utf-8\", errors=\"replace\"\n    )\n\n\ndef day_commits() -> List[Tuple[str, str]]:\n    lines = [\n        l\n        for l in git(\n            [\"log\", \"--date=iso-strict\", \"--pretty=format:%H%x09%cI\"]\n        ).splitlines()\n        if l.strip()\n    ]\n    seen = set()\n    out: List[Tuple[str, str]] = []\n    for ln in lines:\n        h, iso = ln.split(\"\\t\", 1)\n        try:\n            d = (\n                datetime.fromisoformat(iso.replace(\"Z\", \"+00:00\"))\n                .astimezone(timezone.utc)\n                .strftime(\"%Y-%m-%d\")\n            )\n        except Exception:\n            d = iso[:10]\n        if d not in seen:\n            seen.add(d)\n            out.append((d, h))\n    out.reverse()\n    return out\n\n\ndef _git_show_silent(sha: str, rel: str) -> Optional[str]:\n    try:\n        cp = subprocess.run(\n            [\"git\", \"show\", f\"{sha}:{rel}\"],\n            cwd=str(REPO_ROOT),\n            stdout=subprocess.PIPE,\n            stderr=subprocess.DEVNULL,\n            check=True,\n        )\n        return cp.stdout.decode(\"utf-8\", errors=\"replace\")\n    except subprocess.CalledProcessError:\n        return None\n\n\ndef resolve_at_commit(slug: str, sha: str) -> Optional[Tuple[str, str]]:\n    for rel in (\n        f\"{slug}.mdx\",\n        f\"{slug}.md\",\n        str(Path(slug) / \"index.mdx\"),\n        str(Path(slug) / \"index.md\"),\n    ):\n        content = _git_show_silent(sha, rel)\n        if content is not None:\n            return rel, content\n    return None\n\n\ndef compute_snapshot(docs_json_str: str, sha: str) -> Tuple[Dict, Dict, List[Dict]]:\n    docs = json.loads(docs_json_str)\n    slugs = nav_slugs(docs)\n    pages: List[Dict] = []\n    stubs: List[Dict] = []\n    for slug in slugs:\n        hit = resolve_at_commit(slug, sha)\n        if not hit:\n            continue\n        rel, content = hit\n        prose_words, code_block_lines, code_block_words = extract_counts(content)\n        row = {\n            \"slug\": slug,\n            \"path\": rel,\n            \"stub\": is_stub(content),\n            \"words\": prose_words,\n            \"images\": count_images(content),\n            \"codeBlockLines\": code_block_lines,\n            \"codeBlockWords\": code_block_words,\n        }\n        if not row[\"stub\"]:\n            pages.append(row)\n        else:\n            stubs.append(row)\n    totals = {\n        \"pages\": len(pages),\n        \"words\": sum(p[\"words\"] for p in pages),\n        \"images\": sum(p[\"images\"] for p in pages),\n        \"codeBlockLines\": sum(p.get(\"codeBlockLines\", 0) for p in pages),\n        \"codeBlockWords\": sum(p.get(\"codeBlockWords\", 0) for p in pages),\n    }\n    dist = summarize([p[\"words\"] for p in pages])\n    return totals, dist, stubs\n\n\ndef run_history() -> None:\n    STATS_DIR.mkdir(parents=True, exist_ok=True)\n    (STATS_DIR / \"history.jsonl\").write_text(\"\", encoding=\"utf-8\")\n    (STATS_DIR / \"history.csv\").write_text(\n        \"date,commit,pages,words,images,min,p25,median,p75,max,avg\\n\", encoding=\"utf-8\"\n    )\n    for day, sha in day_commits():\n        if day in EXCLUDE_UTC_DAYS:\n            continue\n        docs_str = _git_show_silent(sha, \"docs.json\")\n        if docs_str is None:\n            continue\n        totals, dist, _ = compute_snapshot(docs_str, sha)\n        with (STATS_DIR / \"history.jsonl\").open(\"a\", encoding=\"utf-8\") as jf:\n            jf.write(\n                json.dumps(\n                    {\"date\": day, \"commit\": sha, \"totals\": totals, \"distribution\": dist}\n                )\n                + \"\\n\"\n            )\n        with (STATS_DIR / \"history.csv\").open(\"a\", encoding=\"utf-8\") as cf:\n            cf.write(\n                f\"{day},{sha},{totals['pages']},{totals['words']},{totals['images']},{dist['min']},{dist['p25']},{dist['median']},{dist['p75']},{dist['max']},{dist['average']}\\n\"\n            )\n        print(f\"{day} {sha[:7]} pages={totals['pages']} words={totals['words']}\")\n    print(\"History written to stats/history.jsonl and stats/history.csv\")\n\n\ndef run_charts() -> None:\n    if not HISTORY_CSV.exists():\n        print(\"stats/history.csv not found; run: python3 scripts/stats.py history\")\n        return\n    try:\n        import matplotlib\n\n        matplotlib.use(\"Agg\")\n        import matplotlib.pyplot as plt\n        import matplotlib.dates as mdates\n    except Exception as e:\n        print(\"[charts] matplotlib not available:\", e)\n        return\n    rows = []\n    with HISTORY_CSV.open(\"r\", encoding=\"utf-8\") as f:\n        r = csv.DictReader(f)\n        for d in r:\n            rows.append(\n                {\n                    \"date\": datetime.strptime(d[\"date\"], \"%Y-%m-%d\"),\n                    \"pages\": int(d[\"pages\"]),\n                    \"words\": int(d[\"words\"]),\n                }\n            )\n    if not rows:\n        print(\"history.csv empty\")\n        return\n\n    def plot(field: str, title: str, color: str, out: Path):\n        x = [r[\"date\"] for r in rows]\n        y = [r[field] for r in rows]\n        fig, ax = plt.subplots(figsize=(10, 3), dpi=140)\n        ax.plot(x, y, color=color, linewidth=2)\n        ax.set_title(title)\n        locator = mdates.AutoDateLocator()\n        ax.xaxis.set_major_locator(locator)\n        ax.xaxis.set_major_formatter(mdates.ConciseDateFormatter(locator))\n        ax.grid(True, color=\"#e5e7eb\")\n        fig.tight_layout()\n        out.parent.mkdir(parents=True, exist_ok=True)\n        fig.savefig(out, bbox_inches=\"tight\")\n        plt.close(fig)\n\n    plot(\"words\", \"Total Words Over Time\", \"#3b82f6\", CHART_DIR / \"total_words.png\")\n    plot(\"pages\", \"Total Pages Over Time\", \"#10b981\", CHART_DIR / \"total_pages.png\")\n    print(\"Charts written: stats/charts/total_words.png, total_pages.png\")\n\n\ndef main():\n    if not DOCS_JSON_PATH.exists():\n        print(\"docs.json not found\", file=sys.stderr)\n        sys.exit(1)\n    ap = argparse.ArgumentParser(description=\"Docs stats (clean)\")\n    ap.add_argument(\n        \"cmd\",\n        nargs=\"?\",\n        choices=[\"latest\", \"history\", \"charts\", \"all\"],\n        default=\"latest\",\n    )\n    args = ap.parse_args()\n    if args.cmd in (\"latest\", \"all\"):\n        run_latest()\n    if args.cmd in (\"history\", \"all\"):\n        run_history()\n    if args.cmd in (\"charts\", \"all\"):\n        run_charts()\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "snippets/aside.jsx",
    "content": "/**\n * Astro-compatible Aside component, which is called Callout by the Mintlify.\n * Unlike its Astro's counterpart, this component supports custom icons from Font Awesome and Lucide sets.\n *\n * @param {{\n *   type: 'note' | 'tip' | 'caution' | 'danger',\n *   title: string,\n *   icon: string,\n *   iconType: 'regular' | 'solid' | 'light' | 'thin' | 'sharp-solid' | 'duotone' | 'brands',\n *   children: any\n * }} props\n */\nexport const Aside = ({ type = \"note\", title = \"\", icon = \"\", iconType = \"regular\", children }) => {\n  const asideVariants = [\"note\", \"tip\", \"caution\", \"danger\"];\n  const asideComponents = {\n    note: {\n      outerStyle: \"border-sky-500/20 bg-sky-50/50 dark:border-sky-500/30 dark:bg-sky-500/10\",\n      innerStyle: \"text-sky-900 dark:text-sky-200\",\n      calloutType: \"note\",\n      icon: (\n        <svg\n          width=\"14\"\n          height=\"14\"\n          viewBox=\"0 0 14 14\"\n          fill=\"currentColor\"\n          xmlns=\"http://www.w3.org/2000/svg\"\n          className=\"w-4 h-4 text-sky-500\"\n          aria-label=\"Note\"\n        >\n          <path\n            fill-rule=\"evenodd\"\n            clip-rule=\"evenodd\"\n            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\"\n          ></path>\n        </svg>\n      ),\n    },\n    tip: {\n      outerStyle: \"border-emerald-500/20 bg-emerald-50/50 dark:border-emerald-500/30 dark:bg-emerald-500/10\",\n      innerStyle: \"text-emerald-900 dark:text-emerald-200\",\n      calloutType: \"tip\",\n      icon: (\n        <svg\n          width=\"11\"\n          height=\"14\"\n          viewBox=\"0 0 11 14\"\n          fill=\"currentColor\"\n          xmlns=\"http://www.w3.org/2000/svg\"\n          className=\"text-emerald-600 dark:text-emerald-400/80 w-3.5 h-auto\"\n          aria-label=\"Tip\"\n        >\n          <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>\n        </svg>\n      ),\n    },\n    caution: {\n      outerStyle: \"border-amber-500/20 bg-amber-50/50 dark:border-amber-500/30 dark:bg-amber-500/10\",\n      innerStyle: \"text-amber-900 dark:text-amber-200\",\n      calloutType: \"warning\",\n      icon: (\n        <svg\n          className=\"flex-none w-5 h-5 text-amber-400 dark:text-amber-300/80\"\n          fill=\"none\"\n          viewBox=\"0 0 24 24\"\n          stroke=\"currentColor\"\n          stroke-width=\"2\"\n          aria-label=\"Warning\"\n        >\n          <path\n            stroke-linecap=\"round\"\n            stroke-linejoin=\"round\"\n            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\"\n          ></path>\n        </svg>\n      ),\n    },\n    danger: {\n      outerStyle: \"border-red-500/20 bg-red-50/50 dark:border-red-500/30 dark:bg-red-500/10\",\n      innerStyle: \"text-red-900 dark:text-red-200\",\n      calloutType: \"danger\",\n      icon: (\n        <svg\n          xmlns=\"http://www.w3.org/2000/svg\"\n          viewBox=\"0 0 512 512\"\n          fill=\"currentColor\"\n          className=\"text-red-600 dark:text-red-400/80 w-4 h-4\"\n          aria-label=\"Danger\"\n        >\n          <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>\n        </svg>\n      ),\n    },\n  };\n  let variant = type;\n  let gotInvalidVariant = false;\n  if (!asideVariants.includes(type)) {\n    gotInvalidVariant = true;\n    variant = \"danger\";\n  }\n  const iconVariants = [\"regular\", \"solid\", \"light\", \"thin\", \"sharp-solid\", \"duotone\", \"brands\"];\n  if (!iconVariants.includes(iconType)) {\n    iconType = \"regular\";\n  }\n\n  return (\n    <>\n      <div\n        className={`callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border ${asideComponents[variant].outerStyle}`}\n        data-callout-type={asideComponents[variant].calloutType}\n      >\n        <div className=\"mt-0.5 w-4\" data-component-part=\"callout-icon\">\n          {/* @ts-ignore */}\n          {icon === \"\" ? asideComponents[variant].icon : <Icon icon={icon} iconType={iconType} size={14} />}\n        </div>\n        <div\n          className={`text-sm prose min-w-0 w-full ${asideComponents[variant].innerStyle}`}\n          data-component-part=\"callout-content\"\n        >\n          {gotInvalidVariant ? (\n            <p>\n              <span className=\"font-bold\">\n                Invalid <code>type</code> passed!\n              </span>\n              <br />\n              <span className=\"font-bold\">Received: </span>\n              {type}\n              <br />\n              <span className=\"font-bold\">Expected one of: </span>\n              {asideVariants.join(\", \")}\n            </p>\n          ) : (\n            <>\n              {title && <p className=\"font-bold\">{title}</p>}\n              {children}\n            </>\n          )}\n        </div>\n      </div>\n    </>\n  );\n};\n"
  },
  {
    "path": "snippets/catchain-visualizer.jsx",
    "content": "const React =\n  typeof globalThis !== \"undefined\" && globalThis.React\n    ? globalThis.React\n    : (() => {\n        throw new Error(\n          \"React global missing. CatchainVisualizer must run inside a React-powered environment.\"\n        );\n      })();\nexport const CatchainVisualizer = () => {\n  const MESSAGE_COLORS = {\n    Submit: \"#6366f1\",\n    Approve: \"#22c55e\",\n    Vote: \"#0ea5e9\",\n    VoteFor: \"#06b6d4\",\n    Precommit: \"#f59e0b\",\n    Commit: \"#3b82f6\",\n    DepRequest: \"#475569\",\n  };\n\n  const MESSAGE_LABELS = {\n    Submit: \"Submit\",\n    Approve: \"Approve\",\n    Vote: \"Vote\",\n    VoteFor: \"VoteFor\",\n    Precommit: \"PreCommit\",\n    Commit: \"Commit\",\n    DepRequest: \"Dep req\",\n  };\n  const MESSAGE_DESCRIPTIONS = {\n    Submit: \"Proposer shares its round candidate with peers.\",\n    Approve: \"Validator approves a seen proposal so others can vote.\",\n    Vote: \"Validator votes for a proposal once approvals reach quorum.\",\n    VoteFor:\n      \"Coordinator guidance for slow attempts; points voting to a candidate.\",\n    Precommit:\n      \"Validator precommits after quorum votes to lock on a candidate.\",\n    Commit: \"Validator finalizes a candidate after quorum precommits.\",\n    DepRequest:\n      \"Catchain-level dependency request for missing messages; peers will resend the requested blocks.\",\n  };\n\n  const LAYOUT = {\n    centerX: 230,\n    centerY: 200,\n    nodeRing: 150,\n    backdropRadius: 170,\n    svgWidth: 520,\n    svgHeight: 380,\n    nodeRadius: 30,\n    ringRadius: 34,\n    proposerTimerRadius: 40,\n  };\n\n  const LOG_LIMIT = 14;\n  const PRIORITY_MOD = 1000;\n  const PRIORITY_LAG_FACTOR = 18;\n  const APPROVAL_JITTER_MIN = 25;\n  const APPROVAL_JITTER_MAX = 120;\n  const NULL_PRIORITY = 9999;\n  const VOTEFOR_RETRY_MS = 400;\n  const PROPOSER_SELF_APPROVE_EXTRA_MS = 120;\n  const CANVAS_ARROW_MARKER = { width: 6, height: 6, refX: 5, refY: 3 };\n  const LOGO_TEXT_OFFSET = 24;\n  const LAGGING_DROP_PROBABILITY = 0.5;\n  const VOTEFOR_INITIAL_DELAY_MS = 500;\n  const DEP_REQUEST_RETRY_MS = 300;\n  const DEFAULT_MAX_DEPS = 4;\n  const SCROLLBAR_CSS = `\n    .catchain-scroll {\n      scrollbar-width: thin;\n      scrollbar-color: #94a3b8 #e2e8f0;\n    }\n    .catchain-scroll::-webkit-scrollbar {\n      width: 10px;\n    }\n    .catchain-scroll::-webkit-scrollbar-track {\n      background: #e2e8f0;\n      border-radius: 9999px;\n    }\n    .catchain-scroll::-webkit-scrollbar-thumb {\n      background: #94a3b8;\n      border-radius: 9999px;\n      border: 2px solid #e2e8f0;\n    }\n    .catchain-scroll::-webkit-scrollbar-thumb:hover {\n      background: #64748b;\n    }\n    .committed-scroll {\n      scrollbar-width: thin;\n      scrollbar-color: #94a3b8 #e2e8f0;\n    }\n    .committed-scroll::-webkit-scrollbar {\n      height: 10px;\n    }\n    .committed-scroll::-webkit-scrollbar-track {\n      background: #e2e8f0;\n      border-radius: 9999px;\n    }\n    .committed-scroll::-webkit-scrollbar-thumb {\n      background: #94a3b8;\n      border-radius: 9999px;\n      border: 2px solid #e2e8f0;\n    }\n    .committed-scroll::-webkit-scrollbar-thumb:hover {\n      background: #64748b;\n    }\n  `;\n\n  function randomBetween(min, max) {\n    return min + Math.random() * (max - min);\n  }\n\n  function clamp(value, min, max) {\n    return Math.min(Math.max(value, min), max);\n  }\n\n  function createPositions(count) {\n    const cx = LAYOUT.centerX;\n    const cy = LAYOUT.centerY;\n    const r = LAYOUT.nodeRing;\n    const result = [];\n    for (let i = 0; i < count; i += 1) {\n      const angle = (Math.PI * 2 * i) / count - Math.PI / 2;\n      result.push({\n        x: cx + r * Math.cos(angle),\n        y: cy + r * Math.sin(angle),\n      });\n    }\n    return result;\n  }\n\n  function createNode(index, pos) {\n    return {\n      id: `V${index + 1}`,\n      label: `S${index + 1}`,\n      pos,\n      approved: new Set(),\n      voted: new Set(),\n      precommitted: new Set(),\n      receivedEvents: {},\n      committedTo: null,\n      voteTarget: null,\n      crashed: false,\n      pendingActions: [],\n      flushScheduled: false,\n      votedThisAttempt: false,\n      precommittedThisAttempt: false,\n      lastVotedFor: null,\n      lastPrecommitFor: null,\n      lockedCandidate: null,\n      lockedAtAttempt: 0,\n      status: \"good\",\n      catchainStore: new Map(),\n      pendingCatchain: new Map(),\n      missingRequests: new Set(),\n      lastCatchainHeight: 0,\n    };\n  }\n\n  function makeCandidate(round, attempt, proposerIndex, proposerId) {\n    const short = `${round}.${attempt}`;\n    return {\n      id: `R${round}-P${proposerIndex + 1}`,\n      short,\n      round,\n      attempt,\n      proposerIndex,\n      proposerId,\n      approvals: new Set(),\n      votes: new Set(),\n      precommits: new Set(),\n      commits: new Set(),\n      createdAt: null,\n      priority: (proposerIndex + round - 1) % PRIORITY_MOD,\n      submitted: false,\n      submitAt: null,\n      submitDelay: 0,\n    };\n  }\n\n  function logEvent(model, text) {\n    model.log.unshift({ t: model.time, text });\n    if (model.log.length > LOG_LIMIT) {\n      model.log = model.log.slice(0, LOG_LIMIT);\n    }\n  }\n\n  function scheduleTask(model, delayMs, fn, label = \"\") {\n    model.tasks.push({\n      runAt: model.time + delayMs,\n      fn,\n      label,\n    });\n  }\n\n  function getNode(model, nodeId) {\n    return model.nodes.find((n) => n.id === nodeId);\n  }\n\n  function createCatchainEnvelope(model, from, actions, deps = []) {\n    const nextHeight = (model.catchainHeights[from] || 0) + 1;\n    model.catchainHeights[from] = nextHeight;\n    const senderNode = getNode(model, from);\n    const prevId = senderNode?.lastCatchainId || null;\n\n    const idSet = new Set();\n    const senderSet = new Set();\n    let depList = [];\n    const baseDeps = Array.from(new Set(deps || []));\n\n    const senderFromId = (depId) => {\n      if (!depId) return null;\n      const m = /^([^-/]+)-h/.exec(depId);\n      return m ? m[1] : depId;\n    };\n\n    const pushDep = (depId, depSender) => {\n      if (!depId) return;\n      const senderKey = depSender || senderFromId(depId) || depId;\n      if (senderKey === from || idSet.has(depId) || senderSet.has(senderKey))\n        return;\n      idSet.add(depId);\n      senderSet.add(senderKey);\n      depList.push(depId);\n    };\n\n    if (baseDeps.length > 0 && senderNode) {\n      baseDeps.forEach((depId) => {\n        const env = senderNode.catchainStore.get(depId);\n        pushDep(depId, env?.sender);\n      });\n    }\n\n    if (depList.length === 0 && senderNode) {\n      const candidates = Array.from(senderNode.frontier.values()).filter(\n        (entry) => entry && entry.sender !== from\n      );\n      candidates.sort((a, b) => (b.height || 0) - (a.height || 0));\n      for (const c of candidates) {\n        if (depList.length >= model.config.maxDeps) break;\n        pushDep(c.id, c.sender);\n      }\n    }\n\n    depList = Array.from(new Set(depList)).slice(0, model.config.maxDeps);\n\n    return {\n      id: `${from}-h${nextHeight}`,\n      sender: from,\n      height: nextHeight,\n      prev: prevId,\n      deps: depList,\n      actions,\n    };\n  }\n\n  function sendCatchainEnvelope(model, envelope, options = {}) {\n    const { from, to, delay = 0, includeSelf = false } = options;\n    const sender = getNode(model, from);\n    model.nodes.forEach((node) => {\n      if (to && node.id !== to) return;\n      if (!includeSelf && node.id === from) return;\n      if (\n        sender &&\n        sender.status === \"lagging\" &&\n        Math.random() < LAGGING_DROP_PROBABILITY\n      ) {\n        return;\n      }\n      const latency = randomBetween(\n        model.config.latency[0],\n        model.config.latency[1]\n      );\n      const sendAt = model.time + delay;\n      const primary = envelope.actions?.[0]?.type || \"Catchain\";\n      model.messages.push({\n        id: `${envelope.id}-${from}-${node.id}-${Math.random()\n          .toString(16)\n          .slice(2, 6)}`,\n        transport: \"Catchain\",\n        envelope,\n        actions: envelope.actions || [],\n        primary,\n        from,\n        to: node.id,\n        sendTime: sendAt,\n        recvTime: sendAt + latency,\n      });\n    });\n  }\n\n  function sendDepRequest(model, from, to, missingIds) {\n    if (!missingIds || missingIds.length === 0) return;\n    const sender = getNode(model, from);\n    if (\n      sender &&\n      sender.status === \"lagging\" &&\n      Math.random() < LAGGING_DROP_PROBABILITY\n    ) {\n      return;\n    }\n    const latency = randomBetween(\n      model.config.latency[0],\n      model.config.latency[1]\n    );\n    const sendAt = model.time;\n    model.messages.push({\n      id: `REQ-${from}-${to}-${Math.random().toString(16).slice(2, 6)}`,\n      transport: \"DepRequest\",\n      missingIds,\n      primary: \"DepRequest\",\n      from,\n      to,\n      sendTime: sendAt,\n      recvTime: sendAt + latency,\n      actions: [],\n    });\n  }\n\n  function requestMissingDeps(\n    model,\n    node,\n    missingIds,\n    preferredPeer,\n    force = false\n  ) {\n    const uniqueIds = Array.from(new Set(missingIds || []));\n    const outstanding = uniqueIds.filter(\n      (id) => force || !node.missingRequests.has(id)\n    );\n    if (outstanding.length === 0) return;\n    outstanding.forEach((id) => node.missingRequests.add(id));\n    const preferred =\n      preferredPeer && preferredPeer !== node.id\n        ? getNode(model, preferredPeer)\n        : null;\n    const target =\n      preferred && preferred.status !== \"crashed\"\n        ? preferred\n        : model.nodes.find((n) => n.id !== node.id && n.status !== \"crashed\");\n    if (!target) return;\n    logEvent(\n      model,\n      `${node.label} requested ${outstanding.length} dep(s) from ${target.label}`\n    );\n    sendDepRequest(model, node.id, target.id, outstanding);\n  }\n\n  function tryDeliverPendingCatchain(model, node) {\n    let progressed = true;\n    while (progressed) {\n      progressed = false;\n      node.pendingCatchain.forEach((entry, mid) => {\n        const remaining = [...entry.missing].filter(\n          (dep) => !node.catchainStore.has(dep)\n        );\n        if (remaining.length === 0) {\n          node.pendingCatchain.delete(mid);\n          deliverCatchainEnvelope(model, node, entry.envelope, entry.from);\n          progressed = true;\n        } else {\n          entry.missing = new Set(remaining);\n        }\n      });\n    }\n  }\n\n  function deliverCatchainEnvelope(model, node, envelope, originalFrom) {\n    if (!node || node.status === \"crashed\") return;\n    if (node.catchainStore.has(envelope.id)) return;\n    const depsAndPrev = Array.from(\n      new Set([\n        ...(envelope.prev ? [envelope.prev] : []),\n        ...(envelope.deps || []),\n      ])\n    );\n    const missing = depsAndPrev.filter((dep) => !node.catchainStore.has(dep));\n    if (missing.length > 0) {\n      logEvent(\n        model,\n        `${node.label} missing ${missing.length} dep(s) for ${\n          envelope.id\n        }: ${missing.join(\", \")}`\n      );\n      node.pendingCatchain.set(envelope.id, {\n        envelope,\n        missing: new Set(missing),\n        from: originalFrom,\n      });\n      requestMissingDeps(model, node, missing, originalFrom);\n      scheduleTask(\n        model,\n        DEP_REQUEST_RETRY_MS,\n        () => {\n          const pending = node.pendingCatchain.get(envelope.id);\n          if (!pending) return;\n          requestMissingDeps(\n            model,\n            node,\n            [...pending.missing],\n            originalFrom,\n            true\n          );\n        },\n        \"dep-retry\"\n      );\n      return;\n    }\n    const depSenders = new Set();\n    for (const depId of envelope.deps || []) {\n      const depEnv = node.catchainStore.get(depId);\n      if (depEnv) {\n        if (depSenders.has(depEnv.sender)) {\n          logEvent(\n            model,\n            `${node.label} rejected ${envelope.id} (duplicate deps from ${depEnv.sender})`\n          );\n          return;\n        }\n        depSenders.add(depEnv.sender);\n      }\n    }\n    node.catchainStore.set(envelope.id, envelope);\n    node.missingRequests.delete(envelope.id);\n    node.lastCatchainHeight = Math.max(\n      node.lastCatchainHeight || 0,\n      envelope.height || 0\n    );\n    node.lastCatchainId = envelope.id;\n    node.frontier.set(envelope.sender, {\n      id: envelope.id,\n      sender: envelope.sender,\n      height: envelope.height || 0,\n    });\n    (envelope.actions || []).forEach((action) =>\n      handleAction(model, node, action, envelope.sender)\n    );\n    tryDeliverPendingCatchain(model, node);\n  }\n\n  function handleDepRequest(model, node, message) {\n    if (!message.missingIds || message.missingIds.length === 0) return;\n    console.log(message.missingIds);\n    message.missingIds.forEach((id) => {\n      const stored = node.catchainStore.get(id);\n      if (stored) {\n        sendCatchainEnvelope(model, stored, {\n          from: node.id,\n          to: message.from,\n          includeSelf: false,\n          delay: DEP_REQUEST_RETRY_MS / 10,\n        });\n      }\n    });\n  }\n\n  function chooseVoteTarget(model, node) {\n    const eligible = Object.values(model.candidates).filter((c) => {\n      const state = c.approvals.size >= model.config.quorum;\n      // this node has seen this\n      const hasCurrentSeen = !node.receivedEvents[c.id]\n        ? false\n        : node.receivedEvents[c.id].approved >= model.config.quorum;\n\n      return state && hasCurrentSeen;\n    });\n\n    if (eligible.length === 0) return null;\n\n    if (model.isSlow) {\n      if (!node.voteTarget) return null;\n      const target = model.candidates[node.voteTarget];\n      return target && target.approvals.size >= model.config.quorum\n        ? target\n        : null;\n    }\n\n    // fast attempt\n    if (node.lockedCandidate) {\n      const locked = model.candidates[node.lockedCandidate];\n      if (locked && locked.approvals.size >= model.config.quorum) return locked;\n    }\n    if (node.lastVotedFor) {\n      const prev = model.candidates[node.lastVotedFor];\n      if (prev && prev.approvals.size >= model.config.quorum) return prev;\n    }\n\n    return eligible.reduce((best, cand) => {\n      if (!best) return cand;\n      return cand.priority < best.priority ? cand : best;\n    }, null);\n  }\n\n  function broadcastBlock(model, options) {\n    const { from, actions, delay = 0, includeSelf = false } = options;\n    if (!actions || actions.length === 0) return;\n    const sender = getNode(model, from);\n    if (!sender || sender.status === \"crashed\") return;\n    const envelope = createCatchainEnvelope(model, from, actions);\n    deliverCatchainEnvelope(model, sender, envelope, from);\n    sendCatchainEnvelope(model, envelope, { from, delay, includeSelf });\n  }\n\n  function addEvent(node, candidateId, eventType) {\n    if (!node.receivedEvents[candidateId]) {\n      node.receivedEvents[candidateId] = {\n        approved: 0,\n        voted: 0,\n        precommitted: 0,\n        commited: 0,\n      };\n    }\n\n    switch (eventType) {\n      case \"approve\": {\n        node.receivedEvents[candidateId].approved += 1;\n        break;\n      }\n      case \"vote\": {\n        node.receivedEvents[candidateId].voted += 1;\n        break;\n      }\n      case \"precommit\": {\n        node.receivedEvents[candidateId].precommitted += 1;\n        break;\n      }\n      case \"commit\": {\n        node.receivedEvents[candidateId].commited += 1;\n        break;\n      }\n    }\n  }\n\n  function enqueueAction(model, node, action, delay = 0, includeSelf = false) {\n    scheduleTask(\n      model,\n      delay,\n      () => {\n        if (node.status === \"crashed\") return;\n        if (action.type === \"Submit\") {\n          const cand = model.candidates[action.candidateId];\n          if (cand && !cand.createdAt) {\n            cand.createdAt = model.time;\n          }\n          if (cand) {\n            cand.submitted = true;\n          }\n        }\n        broadcastBlock(model, {\n          from: node.id,\n          actions: [action],\n          includeSelf,\n        });\n      },\n      \"flush-block\"\n    );\n  }\n\n  function issueApproval(model, node, candidateId, opts = {}) {\n    const candidate = model.candidates[candidateId];\n    if (\n      !candidate ||\n      node.status === \"crashed\" ||\n      node.approved.has(candidateId)\n    )\n      return;\n    node.approved.add(candidateId);\n    // event for this view\n    addEvent(node, candidateId, \"approve\");\n    candidate.approvals.add(node.id);\n    if (!candidate.createdAt && candidate.approvals.size === 1) {\n      candidate.createdAt = model.time;\n    }\n    logEvent(\n      model,\n      `${node.label} approved ${candidate.short} (approvals ${candidate.approvals.size}/${model.config.quorum})`\n    );\n    enqueueAction(\n      model,\n      node,\n      { type: \"Approve\", candidateId },\n      opts.delay || 0\n    );\n    tryVote(model, candidateId);\n  }\n\n  function issueVote(model, node, candidateId) {\n    const candidate = model.candidates[candidateId];\n    if (!candidate || node.status === \"crashed\" || node.votedThisAttempt)\n      return;\n    if (candidate.approvals.size < model.config.quorum) return;\n    node.votedThisAttempt = true;\n    node.lastVotedFor = candidateId;\n    node.voted.add(candidateId);\n    addEvent(node, candidateId, \"vote\");\n    candidate.votes.add(node.id);\n    logEvent(\n      model,\n      `${node.label} voted ${candidate.short} (votes ${candidate.votes.size}/${model.config.quorum})`\n    );\n    enqueueAction(model, node, { type: \"Vote\", candidateId });\n    tryPrecommit(model, node, candidateId);\n  }\n\n  function issuePrecommit(model, node, candidateId) {\n    const candidate = model.candidates[candidateId];\n    if (!candidate || node.status === \"crashed\" || node.precommittedThisAttempt)\n      return;\n    if (candidate.votes.size < model.config.quorum) return;\n    if (node.lastVotedFor !== candidateId) return;\n    node.precommittedThisAttempt = true;\n    node.lastPrecommitFor = candidateId;\n    node.lockedCandidate = candidateId;\n    node.lockedAtAttempt = model.attempt;\n    node.precommitted.add(candidateId);\n    addEvent(node, candidateId, \"precommit\");\n    candidate.precommits.add(node.id);\n    logEvent(\n      model,\n      `${node.label} precommitted ${candidate.short} (precommits ${candidate.precommits.size}/${model.config.quorum})`\n    );\n    enqueueAction(model, node, { type: \"Precommit\", candidateId });\n    tryCommit(model, node, candidateId);\n  }\n\n  function issueCommit(model, node, candidateId) {\n    const candidate = model.candidates[candidateId];\n    if (\n      !candidate ||\n      node.status === \"crashed\" ||\n      node.committedTo === candidateId\n    )\n      return;\n    if (!node.precommittedThisAttempt || node.lastPrecommitFor !== candidateId)\n      return;\n    node.committedTo = candidateId;\n    candidate.commits.add(node.id);\n    addEvent(node, candidateId, \"commit\");\n    logEvent(\n      model,\n      `${node.label} committed ${candidate.short} (commits ${candidate.commits.size}/${model.config.quorum})`\n    );\n    enqueueAction(model, node, { type: \"Commit\", candidateId });\n    if (\n      !model.committedCandidate &&\n      candidate.commits.size >= model.config.quorum\n    ) {\n      model.committedCandidate = candidateId;\n      model.committedHistory = [\n        ...(model.committedHistory || []),\n        {\n          id: candidateId,\n          short: candidate.short,\n          round: model.round,\n          attempt: model.attempt,\n          proposerId: candidate.proposerId,\n          committedAt: model.time,\n        },\n      ];\n      model.nextRoundAt = model.time + model.config.roundGap;\n      logEvent(\n        model,\n        `✔️ Round ${model.round} locked on ${candidate.short}, starting next round soon`\n      );\n    }\n  }\n\n  function tryVote(model) {\n    model.nodes.forEach((node) => {\n      if (node.votedThisAttempt) return;\n      const target = chooseVoteTarget(model, node);\n      if (!target) return;\n      scheduleTask(\n        model,\n        model.config.simDelay,\n        () => issueVote(model, node, target.id),\n        \"vote\"\n      );\n    });\n  }\n\n  function tryPrecommit(model, node, candidateId) {\n    const candidate = model.candidates[candidateId];\n    if (!candidate || candidate.votes.size < model.config.quorum) return;\n\n    // check that this node have seen quorum for votes\n    if (\n      !node.receivedEvents[candidateId] ||\n      node.receivedEvents[candidateId].voted < model.config.quorum\n    ) {\n      return;\n    }\n\n    scheduleTask(\n      model,\n      model.config.simDelay,\n      () => issuePrecommit(model, node, candidateId),\n      \"precommit\"\n    );\n  }\n\n  function tryCommit(model, node, candidateId) {\n    const candidate = model.candidates[candidateId];\n    if (!candidate || candidate.precommits.size < model.config.quorum) return;\n\n    // check that this node have seen quorum for precommits so we can vote\n    if (\n      !node.receivedEvents[candidateId] ||\n      node.receivedEvents[candidateId].precommitted < model.config.quorum\n    ) {\n      return;\n    }\n\n    scheduleTask(\n      model,\n      model.config.simDelay,\n      () => issueCommit(model, node, candidateId),\n      \"commit\"\n    );\n  }\n\n  // TODO: it's for validation, not for actual delay\n  function calcApprovalDelay(model, node, candidate, isSlow) {\n    const base = isSlow ? model.config.DeltaInfinity : model.config.Delta;\n    const priorityLag =\n      (candidate.proposerIndex + node.label.length) * PRIORITY_LAG_FACTOR;\n    const jitter = randomBetween(APPROVAL_JITTER_MIN, APPROVAL_JITTER_MAX);\n    return base + priorityLag + jitter;\n  }\n\n  function getSimDelay() {\n    // TODO: check proposer delay, ensure it with async scheduling\n    return randomBetween(APPROVAL_JITTER_MIN, APPROVAL_JITTER_MAX);\n  }\n\n  function pickCoordinator(model, attempt) {\n    const idx = attempt % model.nodes.length;\n    return model.nodes[idx];\n  }\n\n  function getNodePriority(round, idx, total, C) {\n    const start = (round - 1 + total) % total;\n    let adj = idx;\n    if (adj < start) adj += total;\n    const prio = adj - start;\n    return prio < C ? prio : -1;\n  }\n\n  function ensureNullCandidate(model) {\n    if (model.nullCandidateId) return;\n    const id = `R${model.round}-NULL`;\n    const candidate = {\n      id,\n      short: `${model.round}.⊥`,\n      round: model.round,\n      attempt: model.attempt,\n      proposerIndex: -1,\n      proposerId: \"NULL\",\n      approvals: new Set(),\n      votes: new Set(),\n      precommits: new Set(),\n      commits: new Set(),\n      createdAt: model.time,\n      priority: NULL_PRIORITY,\n      submitted: false,\n      submitAt: null,\n      submitDelay: 0,\n    };\n    model.candidates[id] = candidate;\n    model.nullCandidateId = id;\n    model.nodes.forEach((node) => {\n      scheduleTask(\n        model,\n        model.config.DeltaInfinity,\n        () => issueApproval(model, node, id),\n        \"null-approve\"\n      );\n    });\n  }\n\n  function sendVoteFor(model) {\n    if (!model.isSlow) return;\n    const coord = pickCoordinator(model, model.attempt);\n    const candidates = Object.values(model.candidates).filter(\n      (c) => !!c.createdAt\n    );\n    if (candidates.length === 0) {\n      scheduleTask(\n        model,\n        VOTEFOR_RETRY_MS,\n        () => sendVoteFor(model),\n        \"voteFor-retry\"\n      );\n      return;\n    }\n    const eligible = candidates.filter(\n      (c) => c.approvals.size >= model.config.quorum\n    );\n    if (eligible.length === 0) return;\n    const choice = eligible[Math.floor(Math.random() * eligible.length)];\n    model.voteForTarget = choice.id;\n    logEvent(\n      model,\n      `${coord.label} suggests ${choice.short} for slow attempt via VoteFor`\n    );\n    enqueueAction(model, coord, { type: \"VoteFor\", candidateId: choice.id });\n  }\n\n  function handleAction(model, node, action, fromId) {\n    let candidate = model.candidates[action.candidateId];\n    switch (action.type) {\n      case \"Submit\": {\n        if (!candidate) {\n          const existing = Object.values(model.candidates).find(\n            (c) =>\n              c.proposerId === (action.proposerId || fromId) &&\n              c.round === (action.round || model.round)\n          );\n          if (existing) {\n            candidate = existing;\n          } else {\n            candidate = makeCandidate(\n              action.round || model.round,\n              action.attempt || model.attempt,\n              action.proposerIndex ?? 0,\n              action.proposerId || fromId\n            );\n            model.candidates[action.candidateId] = candidate;\n          }\n        }\n        if (!candidate.createdAt) candidate.createdAt = model.time;\n        // const delay = calcApprovalDelay(model, node, candidate, model.isSlow);\n        if (node.id === candidate.proposerId) {\n          scheduleTask(\n            model,\n            // TODO: fix this const\n            500,\n            () => issueApproval(model, node, candidate.id),\n            \"proposer-self-approve\"\n          );\n        } else if (!model.isSlow) {\n          scheduleTask(\n            model,\n            getSimDelay(),\n            () => issueApproval(model, node, candidate.id),\n            \"auto-approve\"\n          );\n        }\n        break;\n      }\n      case \"VoteFor\": {\n        node.voteTarget = action.candidateId;\n        if (candidate && !node.approved.has(candidate.id)) {\n          const delay = calcApprovalDelay(model, node, candidate, true);\n          scheduleTask(\n            model,\n            delay,\n            () => issueApproval(model, node, candidate.id),\n            \"voteFor-approve\"\n          );\n        }\n        tryVote(model);\n        break;\n      }\n      case \"Approve\": {\n        if (candidate && !candidate.approvals.has(fromId)) {\n          candidate.approvals.add(fromId);\n        }\n\n        addEvent(node, candidate.id, \"approve\");\n        tryVote(model);\n        break;\n      }\n      case \"Vote\": {\n        if (candidate && !candidate.votes.has(fromId)) {\n          candidate.votes.add(fromId);\n          if (candidate.votes.size >= model.config.quorum) {\n            model.nodes.forEach((n) => {\n              if (\n                n.lockedCandidate &&\n                n.lockedCandidate !== candidate.id &&\n                model.attempt > n.lockedAtAttempt\n              ) {\n                // TODO: add quorum check, any vote arrival in a later attempt clears your lock,\n                n.lockedCandidate = null;\n                n.lockedAtAttempt = 0;\n              }\n            });\n          }\n        }\n\n        addEvent(node, candidate.id, \"vote\");\n        tryPrecommit(model, node, candidate.id);\n        break;\n      }\n      case \"Precommit\": {\n        if (candidate && !candidate.precommits.has(fromId)) {\n          candidate.precommits.add(fromId);\n        }\n\n        addEvent(node, candidate.id, \"precommit\");\n        tryCommit(model, node, candidate.id);\n        break;\n      }\n      case \"Commit\": {\n        // TODO: fix next round individual start\n        addEvent(node, candidate.id, \"commit\");\n\n        if (candidate && node.committedTo !== candidate.id) {\n          node.committedTo = candidate.id;\n          candidate.commits.add(node.id);\n          if (\n            !model.committedCandidate &&\n            candidate.commits.size >= model.config.quorum\n          ) {\n            if (\n              !node.receivedEvents[candidate.id] ||\n              node.receivedEvents[candidate.id] < model.config.quorum\n            ) {\n              break;\n            }\n\n            model.committedCandidate = candidate.id;\n            model.nextRoundAt = model.time + model.config.roundGap;\n            logEvent(\n              model,\n              `✔️ Round ${model.round} locked on ${candidate.short}, starting next round soon`\n            );\n          }\n        }\n        break;\n      }\n      default:\n        break;\n    }\n  }\n\n  function handleMessage(model, message) {\n    const node = getNode(model, message.to);\n    if (!node || node.status === \"crashed\") return;\n    if (node.status === \"lagging\" && Math.random() < LAGGING_DROP_PROBABILITY)\n      return;\n    if (message.transport === \"Catchain\") {\n      deliverCatchainEnvelope(model, node, message.envelope, message.from);\n    } else if (message.transport === \"DepRequest\") {\n      handleDepRequest(model, node, message);\n    }\n  }\n\n  function deliverMessages(model) {\n    const ready = [];\n    const pending = [];\n    model.messages.forEach((msg) => {\n      if (msg.recvTime <= model.time) {\n        ready.push(msg);\n      } else {\n        pending.push(msg);\n      }\n    });\n    model.messages = pending;\n    ready.forEach((msg) => handleMessage(model, msg));\n  }\n\n  function runTasks(model) {\n    const ready = [];\n    const future = [];\n    model.tasks.forEach((task) => {\n      if (task.runAt <= model.time) {\n        ready.push(task);\n      } else {\n        future.push(task);\n      }\n    });\n    model.tasks = future;\n    ready.forEach((task) => {\n      try {\n        task.fn();\n      } catch (err) {\n        logEvent(model, `Task error: ${err?.message || err}`);\n      }\n    });\n  }\n\n  function startAttempt(model, options = {}) {\n    const forced = options.forceSlow === true;\n    model.attempt = options.attempt || model.attempt + 1;\n    model.isSlow = forced || model.attempt > model.config.Y;\n    model.attemptStartedAt = model.time;\n    model.messages = [];\n    model.tasks = [];\n    model.voteForTarget = null;\n    model.currentProposers = [];\n    model.nodes.forEach((node) => {\n      node.voted = new Set();\n      node.precommitted = new Set();\n      node.votedThisAttempt = false;\n      node.precommittedThisAttempt = false;\n      node.lastVotedFor = null;\n      node.lastPrecommitFor = null;\n      node.voteTarget = null;\n    });\n    Object.values(model.candidates).forEach((cand) => {\n      cand.votes = new Set();\n      cand.precommits = new Set();\n    });\n\n    const proposerSet = [];\n    for (let i = 0; i < model.nodes.length; i += 1) {\n      const prio = getNodePriority(\n        model.round,\n        i,\n        model.nodes.length,\n        model.config.C\n      );\n      if (prio >= 0) {\n        proposerSet.push({\n          node: model.nodes[i],\n          priority: prio,\n          proposerIndex: i,\n        });\n      }\n    }\n    proposerSet.sort((a, b) => a.priority - b.priority);\n\n    proposerSet.forEach(({ node: proposer, priority, proposerIndex }) => {\n      let cand = Object.values(model.candidates).find(\n        (c) => c.proposerId === proposer.id && c.round === model.round\n      );\n      if (!cand) {\n        cand = makeCandidate(\n          model.round,\n          model.attempt,\n          proposerIndex,\n          proposer.id\n        );\n        cand.priority = priority;\n        model.candidates[cand.id] = cand;\n      } else {\n        cand.priority = priority;\n      }\n      const submitDelay = Math.max(0, priority * model.config.Delta);\n      const submitAt = model.time + submitDelay;\n      model.currentProposers.push({\n        nodeId: proposer.id,\n        candidateId: cand.id,\n        submitAt,\n        submitDelay,\n      });\n      if (cand.submitted) {\n        cand.submitAt = null;\n        cand.submitDelay = 0;\n        return;\n      }\n      cand.submitAt = submitAt;\n      cand.submitDelay = submitDelay;\n      enqueueAction(\n        model,\n        proposer,\n        {\n          type: \"Submit\",\n          candidateId: cand.id,\n          round: model.round,\n          attempt: model.attempt,\n          proposerId: proposer.id,\n          proposerIndex,\n          priority,\n        },\n        submitDelay\n      );\n      scheduleTask(\n        model,\n        submitDelay + PROPOSER_SELF_APPROVE_EXTRA_MS,\n        () => issueApproval(model, proposer, cand.id),\n        \"proposer-instant-approve\"\n      );\n    });\n\n    const best = proposerSet.find(() => true);\n    model.activeCandidateId = best\n      ? Object.values(model.candidates).find(\n          (c) => c.proposerId === best.node.id && c.round === model.round\n        )?.id || \"\"\n      : \"\";\n\n    logEvent(\n      model,\n      `▶️ Round ${model.round}, attempt ${model.attempt} (${\n        model.isSlow ? \"slow\" : \"fast\"\n      }), proposer window size ${model.config.C}`\n    );\n    if (model.isSlow) {\n      scheduleTask(\n        model,\n        VOTEFOR_INITIAL_DELAY_MS,\n        () => sendVoteFor(model),\n        \"voteFor\"\n      );\n    }\n    ensureNullCandidate(model);\n    scheduleTask(model, model.config.K, () => {\n      if (!model.committedCandidate) {\n        logEvent(model, `⏱️ Attempt ${model.attempt} timed out, moving on`);\n        startAttempt(model, { attempt: model.attempt + 1 });\n      }\n    });\n    tryVote(model);\n  }\n\n  function startRound(model, resetRoundNumber = false) {\n    if (!resetRoundNumber) {\n      model.round += 1;\n    }\n    model.attempt = 0;\n    model.candidates = {};\n    model.messages = [];\n    model.tasks = [];\n    model.committedCandidate = null;\n    model.nextRoundAt = null;\n    model.nullCandidateId = null;\n    model.currentProposers = [];\n    model.catchainHeights = {};\n    model.nodes.forEach((node) => {\n      model.catchainHeights[node.id] = 0;\n    });\n    model.nodes.forEach((node) => {\n      node.approved = new Set();\n      node.voted = new Set();\n      node.precommitted = new Set();\n      node.committedTo = null;\n      node.voteTarget = null;\n      node.pendingActions = [];\n      node.flushScheduled = false;\n      node.votedThisAttempt = false;\n      node.precommittedThisAttempt = false;\n      node.lastVotedFor = null;\n      node.lastPrecommitFor = null;\n      node.lockedCandidate = null;\n      node.catchainStore = new Map();\n      node.pendingCatchain = new Map();\n      node.missingRequests = new Set();\n      node.lastCatchainHeight = 0;\n      node.lastCatchainId = null;\n      node.frontier = new Map();\n    });\n    startAttempt(model, { attempt: 1 });\n  }\n\n  function createModel(config) {\n    const positions = createPositions(config.numNodes);\n    const nodes = positions.map((pos, idx) => createNode(idx, pos));\n    const heights = {};\n    nodes.forEach((n) => {\n      heights[n.id] = 0;\n    });\n    const model = {\n      config,\n      time: 0,\n      nodes,\n      messages: [],\n      tasks: [],\n      candidates: {},\n      activeCandidateId: \"\",\n      attempt: 0,\n      round: 1,\n      attemptStartedAt: 0,\n      isSlow: false,\n      committedCandidate: null,\n      nextRoundAt: null,\n      log: [],\n      committedHistory: [],\n      voteForTarget: null,\n      nullCandidateId: null,\n      currentProposers: [],\n      catchainHeights: heights,\n    };\n    startRound(model, true);\n    return model;\n  }\n\n  function stepModel(model, dt) {\n    model.time += dt;\n    runTasks(model);\n    deliverMessages(model);\n    if (model.nextRoundAt && model.time >= model.nextRoundAt) {\n      startRound(model);\n    }\n    return model;\n  }\n\n  const { useEffect, useRef, useState } = React;\n  const DEFAULT_CONFIG = {\n    numNodes: 5,\n    latency: [80, 150],\n    K: 8000, // 8 seconds per attempt\n    roundGap: 200,\n    Delta: 2000, // Δ_i = 2(i-1) seconds -> base 2s\n    DeltaInfinity: 4000, // 2*C seconds with C=2\n    Y: 3, // fast attempts\n    C: 2, // round candidates\n    simDelay: 70, // local processing/animation delay for follow-up actions\n    frameMs: 90,\n    quorum: 4,\n    maxDeps: DEFAULT_MAX_DEPS,\n  };\n  const CONFIG_FIELDS = [\n    {\n      key: \"K\",\n      label: \"K (ms)\",\n      description: \"Attempt duration; 8000ms means 8 seconds per attempt.\",\n    },\n    {\n      key: \"Delta\",\n      label: \"Delta (ms)\",\n      description: \"Base Δ_i delay; 2000ms equals 2s for first step.\",\n    },\n    {\n      key: \"DeltaInfinity\",\n      label: \"DeltaInfinity (ms)\",\n      description: \"Upper delay bound for slow attempts; 2*C seconds.\",\n    },\n    {\n      key: \"Y\",\n      label: \"Y\",\n      description: \"Fast attempts before switching to slow attempts.\",\n    },\n    {\n      key: \"C\",\n      label: \"C\",\n      description: \"Number of round candidates in rotation.\",\n    },\n    {\n      key: \"maxDeps\",\n      label: \"maxDeps\",\n      description: \"Catchain: max dependency links per block (one per sender).\",\n    },\n  ];\n  const [config, setConfig] = useState(() => ({ ...DEFAULT_CONFIG }));\n  const [configDraft, setConfigDraft] = useState(() => ({\n    K: `${DEFAULT_CONFIG.K}`,\n    Delta: `${DEFAULT_CONFIG.Delta}`,\n    DeltaInfinity: `${DEFAULT_CONFIG.DeltaInfinity}`,\n    Y: `${DEFAULT_CONFIG.Y}`,\n    C: `${DEFAULT_CONFIG.C}`,\n    maxDeps: `${DEFAULT_CONFIG.maxDeps}`,\n  }));\n  const [configModalOpen, setConfigModalOpen] = useState(false);\n  const [eventLogOpen, setEventLogOpen] = useState(false);\n\n  const modelRef = useRef(null);\n  const [tick, setTick] = useState(0);\n  const [running, setRunning] = useState(true);\n  const [speed, setSpeed] = useState(0.05);\n  const [selectedNodeId, setSelectedNodeId] = useState(null);\n  const [selectedMessage, setSelectedMessage] = useState(null);\n  const [selectedCandidateId, setSelectedCandidateId] = useState(null);\n  const [hoveredEventType, setHoveredEventType] = useState(null);\n  const [eventTooltipPos, setEventTooltipPos] = useState({\n    x: 0,\n    y: 0,\n    placement: \"bottom\",\n  });\n\n  if (!modelRef.current) {\n    modelRef.current = createModel(config);\n  }\n\n  useEffect(() => {\n    const id = setInterval(() => {\n      if (!running) return;\n      stepModel(modelRef.current, config.frameMs * speed);\n      setTick((t) => t + 1);\n    }, config.frameMs);\n    return () => clearInterval(id);\n  }, [config.frameMs, running, speed]);\n\n  useEffect(() => {\n    if (typeof window === \"undefined\") return undefined;\n    const handleKeyDown = (event) => {\n      const tagName = (event.target?.tagName || \"\").toUpperCase();\n      const isTyping =\n        tagName === \"INPUT\" ||\n        tagName === \"TEXTAREA\" ||\n        tagName === \"SELECT\" ||\n        tagName === \"BUTTON\" ||\n        event.target?.isContentEditable;\n\n      if ((event.key === \" \" || event.key === \"Spacebar\") && !isTyping) {\n        event.preventDefault();\n        setRunning((prev) => !prev);\n        return;\n      }\n\n      if (event.key === \"Escape\") {\n        if (selectedMessage) {\n          setSelectedMessage(null);\n        } else if (selectedCandidateId) {\n          setSelectedCandidateId(null);\n        } else if (selectedNodeId) {\n          setSelectedNodeId(null);\n        } else if (configModalOpen) {\n          setConfigModalOpen(false);\n        } else if (eventLogOpen) {\n          setEventLogOpen(false);\n        }\n      }\n    };\n    window.addEventListener(\"keydown\", handleKeyDown);\n    return () => window.removeEventListener(\"keydown\", handleKeyDown);\n  }, [\n    configModalOpen,\n    eventLogOpen,\n    selectedCandidateId,\n    selectedMessage,\n    selectedNodeId,\n  ]);\n\n  const model = modelRef.current;\n  const activeCandidate = model.activeCandidateId\n    ? model.candidates[model.activeCandidateId]\n    : null;\n  const candidates = Object.values(model.candidates)\n    .filter((c) =>\n      c.proposerId === \"NULL\" ? c.approvals.size > 0 : !!c.createdAt\n    )\n    .sort((a, b) => (b.createdAt || 0) - (a.createdAt || 0));\n  const elapsedAttempt = Math.max(\n    0,\n    model.time - (model.attemptStartedAt || 0)\n  );\n  const attemptProgress = clamp(elapsedAttempt / (model.config.K || 1), 0, 1);\n  const attemptRemaining = Math.max(0, (model.config.K || 0) - elapsedAttempt);\n  const proposerTimerRadius =\n    LAYOUT.proposerTimerRadius || LAYOUT.ringRadius + 6;\n  const proposerTimerCircumference = 2 * Math.PI * proposerTimerRadius;\n  const proposerTimersByNode = {};\n  (model.currentProposers || []).forEach((entry) => {\n    proposerTimersByNode[entry.nodeId] = entry;\n  });\n\n  const rebuildModel = (nextConfig) => {\n    modelRef.current = createModel(nextConfig);\n    setTick((t) => t + 1);\n    setSelectedNodeId(null);\n    setSelectedMessage(null);\n    setSelectedCandidateId(null);\n    setEventLogOpen(false);\n  };\n\n  const reset = () => {\n    rebuildModel(config);\n  };\n\n  const openConfigModal = () => {\n    setConfigDraft({\n      K: `${config.K}`,\n      Delta: `${config.Delta}`,\n      DeltaInfinity: `${config.DeltaInfinity}`,\n      Y: `${config.Y}`,\n      C: `${config.C}`,\n      maxDeps: `${config.maxDeps}`,\n    });\n    setSelectedNodeId(null);\n    setSelectedMessage(null);\n    setSelectedCandidateId(null);\n    setConfigModalOpen(true);\n  };\n\n  const submitConfig = (e) => {\n    e.preventDefault();\n    const toNumber = (val, fallback) => {\n      if (val === \"\") return fallback;\n      const parsed = Number(val);\n      return Number.isFinite(parsed) ? parsed : fallback;\n    };\n    const updatedConfig = {\n      ...config,\n      K: toNumber(configDraft.K, config.K),\n      Delta: toNumber(configDraft.Delta, config.Delta),\n      DeltaInfinity: toNumber(configDraft.DeltaInfinity, config.DeltaInfinity),\n      Y: toNumber(configDraft.Y, config.Y),\n      C: toNumber(configDraft.C, config.C),\n      maxDeps: toNumber(configDraft.maxDeps, config.maxDeps),\n    };\n    setConfig(updatedConfig);\n    rebuildModel(updatedConfig);\n    setConfigModalOpen(false);\n  };\n\n  const showEventTooltip = (evt, key) => {\n    if (!MESSAGE_DESCRIPTIONS[key]) {\n      setHoveredEventType(null);\n      return;\n    }\n    const rect = evt.currentTarget.getBoundingClientRect();\n    const viewportWidth =\n      typeof window !== \"undefined\" ? window.innerWidth : LAYOUT.svgWidth;\n    const viewportHeight =\n      typeof window !== \"undefined\" ? window.innerHeight : LAYOUT.svgHeight;\n    const tooltipWidth = 240;\n    const tooltipHeight = 90;\n    const gap = 12;\n    const preferAbove = rect.bottom + tooltipHeight > viewportHeight - gap;\n    const left = clamp(\n      rect.left + rect.width / 2,\n      tooltipWidth / 2 + gap,\n      viewportWidth - tooltipWidth / 2 - gap\n    );\n    const rawTop = preferAbove\n      ? rect.top - tooltipHeight - gap\n      : rect.bottom + gap;\n    const top = Math.max(gap, rawTop);\n    setEventTooltipPos({\n      x: left,\n      y: top,\n      placement: preferAbove ? \"top\" : \"bottom\",\n    });\n    setHoveredEventType(key);\n  };\n\n  const hideEventTooltip = () => {\n    setHoveredEventType(null);\n  };\n\n  return (\n    <div className=\"rounded-2xl border border-slate-200 bg-white shadow-sm p-4 md:p-6\">\n      <style>{SCROLLBAR_CSS}</style>\n      <div className=\"flex flex-col md:flex-row md:items-center md:justify-between gap-3 mb-2\">\n        <div className=\"flex items-center gap-2\">\n          <button\n            className=\"inline-flex items-center gap-2 rounded-lg bg-sky-600 text-white px-3 py-2 text-sm font-medium shadow-sm hover:bg-sky-700\"\n            onClick={openConfigModal}\n          >\n            Adjust simulation config\n          </button>\n          <button\n            className=\"inline-flex items-center gap-2 rounded-lg bg-sky-600 text-white px-3 py-2 text-sm font-medium shadow-sm hover:bg-sky-700\"\n            onClick={() => setEventLogOpen(true)}\n          >\n            <span role=\"img\" aria-label=\"log\">\n              📖\n            </span>\n            Event log\n          </button>\n        </div>\n        <div className=\"flex items-center gap-3\">\n          <button\n            className=\"inline-flex items-center gap-2 rounded-lg bg-sky-600 text-white px-3 py-2 text-sm font-medium shadow-sm hover:bg-sky-700\"\n            onClick={() => setRunning((v) => !v)}\n          >\n            <span>{running ? \"Pause (Space)\" : \"Resume (Space)\"}</span>\n          </button>\n          <button\n            className=\"inline-flex items-center gap-2 rounded-lg bg-sky-600 text-white px-3 py-2 text-sm font-medium shadow-sm hover:bg-sky-700\"\n            onClick={reset}\n          >\n            Restart round\n          </button>\n        </div>\n      </div>\n      <p className=\"text-xs text-slate-600 mb-4\">\n        Shortcuts: Space to pause/resume the simulation, Esc to close any open\n        pop-up.\n      </p>\n\n      <div className=\"grid gap-4 lg:grid-cols-3\">\n        <div className=\"lg:col-span-2 rounded-xl border border-slate-100 bg-slate-50 px-2 py-3\">\n          <svg\n            viewBox={`0 0 ${LAYOUT.svgWidth} ${LAYOUT.svgHeight}`}\n            className=\"w-full h-[360px]\"\n          >\n            <defs>\n              <marker\n                id=\"arrow-head\"\n                markerWidth={CANVAS_ARROW_MARKER.width}\n                markerHeight={CANVAS_ARROW_MARKER.height}\n                refX={CANVAS_ARROW_MARKER.refX}\n                refY={CANVAS_ARROW_MARKER.refY}\n                orient=\"auto\"\n                markerUnits=\"strokeWidth\"\n              >\n                <path d=\"M0,0 L0,6 L6,3 z\" fill=\"#1e293b\" />\n              </marker>\n            </defs>\n            <circle\n              cx={LAYOUT.centerX}\n              cy={LAYOUT.centerY}\n              r={LAYOUT.backdropRadius}\n              fill=\"#f8fafc\"\n              stroke=\"#e2e8f0\"\n              strokeWidth=\"2\"\n            />\n            {model.nodes.map((node) => {\n              const committed =\n                node.committedTo === model.committedCandidate &&\n                model.committedCandidate;\n              const precommitted =\n                !committed &&\n                activeCandidate &&\n                node.precommitted.has(activeCandidate.id)\n                  ? true\n                  : false;\n              const approved =\n                !committed &&\n                activeCandidate &&\n                node.approved.has(activeCandidate.id);\n              const proposerTimer = proposerTimersByNode[node.id];\n              let proposerProgress = 0;\n              if (proposerTimer) {\n                const remaining = Math.max(\n                  0,\n                  (proposerTimer.submitAt || 0) - model.time\n                );\n                const total = proposerTimer.submitDelay || 1;\n                proposerProgress = clamp(\n                  1 - remaining / Math.max(total, 1),\n                  0,\n                  1\n                );\n                if (model.candidates[proposerTimer.candidateId]?.submitted) {\n                  proposerProgress = 1;\n                }\n              }\n              const ring = committed\n                ? \"#3b82f6\"\n                : precommitted\n                ? \"#f59e0b\"\n                : approved\n                ? \"#22c55e\"\n                : node.status === \"lagging\"\n                ? \"#eab308\"\n                : node.status === \"crashed\"\n                ? \"#ef4444\"\n                : \"#94a3b8\";\n              return (\n                <g\n                  key={node.id}\n                  transform={`translate(${node.pos.x}, ${node.pos.y})`}\n                  onClick={() => setSelectedNodeId(node.id)}\n                  className=\"cursor-pointer\"\n                >\n                  <circle\n                    r={LAYOUT.nodeRadius}\n                    fill={\n                      node.status === \"crashed\"\n                        ? \"#fee2e2\"\n                        : node.status === \"lagging\"\n                        ? \"#fef3c7\"\n                        : \"#e5e7eb\"\n                    }\n                    stroke=\"#94a3b8\"\n                    strokeWidth=\"3\"\n                  />\n                  {proposerTimer && (\n                    <circle\n                      r={proposerTimerRadius}\n                      fill=\"none\"\n                      stroke=\"#4a5358ff\"\n                      strokeWidth=\"7\"\n                      strokeLinecap=\"round\"\n                      strokeDasharray={`${proposerTimerCircumference} ${proposerTimerCircumference}`}\n                      strokeDashoffset={\n                        proposerTimerCircumference * (1 - proposerProgress)\n                      }\n                      transform=\"rotate(-90)\"\n                    />\n                  )}\n                  <circle\n                    r={LAYOUT.ringRadius}\n                    fill=\"none\"\n                    stroke={ring}\n                    strokeWidth=\"4\"\n                  />\n                  <text\n                    textAnchor=\"middle\"\n                    dominantBaseline=\"middle\"\n                    className=\"font-medium\"\n                    fill=\"#374151\"\n                  >\n                    {node.label}\n                  </text>\n                  {node.committedTo && (\n                    <text\n                      y={LOGO_TEXT_OFFSET}\n                      textAnchor=\"middle\"\n                      className=\"text-[9px] font-medium\"\n                      fill=\"#374151\"\n                    >\n                      {node.committedTo}\n                    </text>\n                  )}\n                </g>\n              );\n            })}\n\n            {model.messages.map((msg) => {\n              const fromNode = getNode(model, msg.from);\n              const toNode = getNode(model, msg.to);\n              if (!fromNode || !toNode) return null;\n              const duration = msg.recvTime - msg.sendTime || 1;\n              const progress = clamp(\n                (model.time - msg.sendTime) / duration,\n                0,\n                1\n              );\n              const isRequest = msg.transport === \"DepRequest\";\n              const x =\n                fromNode.pos.x + (toNode.pos.x - fromNode.pos.x) * progress;\n              const y =\n                fromNode.pos.y + (toNode.pos.y - fromNode.pos.y) * progress;\n              const primary = msg.primary || msg.type;\n              const color = isRequest\n                ? MESSAGE_COLORS.DepRequest || \"#475569\"\n                : MESSAGE_COLORS[primary] || \"#0ea5e9\";\n              const label = isRequest\n                ? \"Req\"\n                : msg.actions && msg.actions.length > 1\n                ? `${MESSAGE_LABELS[primary] || primary}+${\n                    msg.actions.length - 1\n                  }`\n                : MESSAGE_LABELS[primary] || primary;\n              return (\n                <g\n                  key={msg.id}\n                  className=\"cursor-pointer\"\n                  onClick={() => {\n                    setSelectedMessage(msg);\n                    setSelectedNodeId(null);\n                  }}\n                >\n                  <line\n                    x1={fromNode.pos.x}\n                    y1={fromNode.pos.y}\n                    x2={toNode.pos.x}\n                    y2={toNode.pos.y}\n                    stroke=\"#cbd5e1\"\n                    strokeDasharray={isRequest ? \"2 4\" : \"4 6\"}\n                  />\n                  <circle\n                    cx={x}\n                    cy={y}\n                    r={isRequest ? \"7\" : \"6\"}\n                    fill={color}\n                    stroke=\"#6b7280\"\n                    strokeWidth=\"1.5\"\n                  />\n                  <text\n                    x={x}\n                    y={y - 10}\n                    textAnchor=\"middle\"\n                    className=\"text-[9px] font-medium\"\n                    fill=\"#4b5563\"\n                  >\n                    {label}\n                  </text>\n                </g>\n              );\n            })}\n          </svg>\n        </div>\n\n        <div className=\"rounded-xl border border-slate-100 bg-white p-3 shadow-inner\">\n          <div className=\"flex flex-col gap-2 text-sm\">\n            <div className=\"flex items-center justify-between\">\n              <span className=\"font-semibold text-slate-800\">Round</span>\n              <span className=\"text-slate-700\">#{model.round}</span>\n            </div>\n            <div className=\"flex items-center justify-between\">\n              <span className=\"font-semibold text-slate-800\">Attempt</span>\n              <span className=\"text-slate-700\">\n                {model.attempt} ({model.isSlow ? \"slow\" : \"fast\"})\n              </span>\n            </div>\n            <div className=\"flex items-center justify-between\">\n              <span className=\"font-semibold text-slate-800\">Proposer</span>\n              <span className=\"text-slate-700\">\n                {activeCandidate\n                  ? `S${activeCandidate.proposerIndex + 1}`\n                  : \"—\"}\n              </span>\n            </div>\n            <div className=\"flex items-center justify-between\">\n              <span className=\"font-semibold text-slate-800\">Coordinator</span>\n              <span className=\"text-slate-700\">\n                {model.isSlow\n                  ? pickCoordinator(model, model.attempt).label\n                  : \"N/A (fast)\"}\n              </span>\n            </div>\n            <div className=\"flex items-center justify-between\">\n              <span className=\"font-semibold text-slate-800\">\n                VoteFor target\n              </span>\n              <span className=\"text-slate-700\">\n                {model.voteForTarget || \"—\"}\n              </span>\n            </div>\n            <div className=\"flex items-center justify-between\">\n              <span className=\"font-semibold text-slate-800\">Committed</span>\n              <span className=\"text-slate-700\">\n                {model.committedCandidate || \"—\"}\n              </span>\n            </div>\n          </div>\n\n          <div className=\"mt-3 rounded-lg border border-slate-100 bg-slate-50 p-2 flex flex-col overflow-hidden h-40\">\n            <p className=\"text-xs font-semibold text-slate-700 mb-1\">\n              Candidates\n            </p>\n            <div\n              className=\"flex-1 min-h-0 overflow-y-scroll pr-1 catchain-scroll\"\n              style={{ scrollbarGutter: \"stable\" }}\n            >\n              <div className=\"flex flex-col gap-2\">\n                {candidates.slice(0, 4).map((cand) => (\n                  <div\n                    key={cand.id}\n                    className=\"rounded-md bg-white border border-slate-200 p-2 cursor-pointer hover:border-slate-300\"\n                    onClick={() => {\n                      setSelectedCandidateId(cand.id);\n                      setSelectedMessage(null);\n                      setSelectedNodeId(null);\n                    }}\n                  >\n                    <div className=\"flex items-center justify-between text-sm font-semibold text-slate-800\">\n                      <span>{cand.id}</span>\n                      <span className=\"text-xs text-slate-600\">\n                        #{cand.short}\n                      </span>\n                    </div>\n                    <div className=\"mt-1 grid grid-cols-4 gap-2 text-[11px] text-slate-700\">\n                      <div>\n                        <span className=\"font-semibold text-green-600\">\n                          {cand.approvals.size}\n                        </span>{\" \"}\n                        Approve\n                      </div>\n                      <div>\n                        <span className=\"font-semibold text-cyan-600\">\n                          {cand.votes.size}\n                        </span>{\" \"}\n                        Vote\n                      </div>\n                      <div>\n                        <span className=\"font-semibold text-amber-600\">\n                          {cand.precommits.size}\n                        </span>{\" \"}\n                        PreCommit\n                      </div>\n                      <div>\n                        <span className=\"font-semibold text-blue-600\">\n                          {cand.commits.size}\n                        </span>{\" \"}\n                        Commit\n                      </div>\n                    </div>\n                  </div>\n                ))}\n              </div>\n            </div>\n          </div>\n\n          <div className=\"mt-3\">\n            <p className=\"text-xs font-semibold text-slate-700 mb-1\">\n              Committed chain\n            </p>\n            <div\n              className=\"overflow-x-auto committed-scroll border border-slate-200 rounded-xl bg-white shadow-inner\"\n              style={{ scrollbarGutter: \"stable both-edges\" }}\n            >\n              <div className=\"flex items-center gap-3 py-3 px-3 min-h-[120px]\">\n                {model.committedHistory.length === 0 ? (\n                  <p className=\"text-[11px] text-slate-500 px-2 py-1\">\n                    No committed candidates yet.\n                  </p>\n                ) : (\n                  model.committedHistory.map((entry, idx) => {\n                    const proposer = entry.proposerId\n                      ? model.nodes.find((n) => n.id === entry.proposerId)\n                      : null;\n                    const isLast =\n                      idx === (model.committedHistory || []).length - 1;\n                    return (\n                      <div\n                        key={`${entry.id}-${idx}`}\n                        className=\"flex items-center gap-3\"\n                      >\n                        <div className=\"min-w-[150px] rounded-xl border border-slate-200 bg-slate-50 px-3 py-3 shadow-sm shadow-slate-200\">\n                          <div className=\"text-xs font-semibold text-slate-700\">\n                            #{idx + 1} · {entry.short}\n                          </div>\n                          <div className=\"text-[11px] text-slate-600\">\n                            Round {entry.round}, attempt {entry.attempt}\n                          </div>\n                          <div className=\"text-[11px] text-slate-600\">\n                            Proposer{\" \"}\n                            {proposer ? proposer.label : entry.proposerId}\n                          </div>\n                          <div className=\"text-[11px] text-slate-500\">\n                            t+{Math.round(entry.committedAt)}ms\n                          </div>\n                        </div>\n                        {!isLast && (\n                          <span className=\"text-slate-400 text-lg select-none\">\n                            →\n                          </span>\n                        )}\n                      </div>\n                    );\n                  })\n                )}\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n\n      <div className=\"mt-4 flex flex-col gap-3\">\n        <div>\n          <div className=\"flex items-center justify-between text-sm font-semibold text-slate-800\">\n            <span>Attempt timer</span>\n            <span className=\"text-slate-700\">\n              {attemptRemaining > 0\n                ? `${(attemptRemaining / 1000).toFixed(1)}s left`\n                : \"next attempt soon\"}\n            </span>\n          </div>\n          <div className=\"mt-2 h-2 rounded-full bg-slate-200 overflow-hidden\">\n            <div\n              className=\"h-full bg-sky-500 transition-[width]\"\n              style={{ width: `${Math.min(100, attemptProgress * 100)}%` }}\n            />\n          </div>\n        </div>\n\n        <div\n          className=\"flex items-center gap-3 relative z-50\"\n          style={{ pointerEvents: \"auto\" }}\n        >\n          <span className=\"text-sm font-semibold text-slate-800\">Speed</span>\n          <input\n            type=\"range\"\n            min=\"0.00005\"\n            max=\"0.25\"\n            step=\"0.0005\"\n            value={speed}\n            onChange={(e) => setSpeed(parseFloat(e.target.value))}\n            className=\"flex-1\"\n            style={{ position: \"relative\", zIndex: 60, pointerEvents: \"auto\" }}\n          />\n          <span className=\"text-sm text-slate-700\">\n            {(speed * 4).toFixed(2)}x\n          </span>\n        </div>\n      </div>\n      <div className=\"mt-4 rounded-xl border border-slate-100 bg-slate-50 p-3\">\n        <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between sm:flex-wrap\">\n          <div className=\"flex items-center gap-2 text-sm font-semibold text-slate-800\">\n            <span>Event types</span>\n          </div>\n          <div className=\"flex flex-wrap gap-2 text-[12px] text-slate-700\">\n            {Object.entries(MESSAGE_COLORS).map(([key, color]) => (\n              <button\n                key={key}\n                type=\"button\"\n                className=\"inline-flex items-center gap-2 rounded-full border border-slate-200 bg-white px-2.5 py-1.5 text-xs font-medium text-slate-800 shadow-sm hover:border-slate-300 focus:outline-none focus:ring-2 focus:ring-sky-200\"\n                onMouseEnter={(e) => showEventTooltip(e, key)}\n                onMouseLeave={hideEventTooltip}\n                onFocus={(e) => showEventTooltip(e, key)}\n                onBlur={hideEventTooltip}\n              >\n                <span\n                  className=\"inline-flex items-center justify-center h-5 w-5 rounded-full text-[11px] font-semibold text-white\"\n                  style={{ background: color }}\n                >\n                  i\n                </span>\n                {MESSAGE_LABELS[key] || key}\n              </button>\n            ))}\n          </div>\n        </div>\n      </div>\n      {hoveredEventType && (\n        <div\n          className=\"pointer-events-none fixed z-40\"\n          style={{\n            left: eventTooltipPos.x,\n            top: eventTooltipPos.y,\n            transform: \"translateX(-50%)\",\n          }}\n        >\n          <div className=\"min-w-[190px] max-w-[260px] rounded-md bg-slate-900 px-3 py-2 text-white text-[12px] shadow-lg ring-1 ring-slate-800/70\">\n            <div className=\"flex items-center gap-2 mb-1\">\n              <span\n                className=\"inline-flex h-3.5 w-3.5 rounded-full\"\n                style={{ background: MESSAGE_COLORS[hoveredEventType] }}\n              />\n              <span className=\"font-semibold\">\n                {MESSAGE_LABELS[hoveredEventType] || hoveredEventType}\n              </span>\n            </div>\n            <div className=\"whitespace-pre-line leading-snug text-slate-100\">\n              {MESSAGE_DESCRIPTIONS[hoveredEventType]}\n            </div>\n          </div>\n        </div>\n      )}\n      {configModalOpen && (\n        <div className=\"fixed inset-0 bg-slate-900/40 flex items-center justify-center z-50\">\n          <div className=\"bg-white rounded-xl shadow-xl border border-slate-200 w-[440px] max-w-full p-5 space-y-4\">\n            <div className=\"flex items-start justify-between\">\n              <div className=\"space-y-1\">\n                <p className=\"text-base font-semibold text-slate-800 leading-snug\">\n                  Simulation config\n                </p>\n                <br />\n                <p className=\"text-sm text-slate-600 leading-snug\">\n                  Update timing parameters; applying will restart the emulation.\n                </p>\n              </div>\n              <button\n                className=\"text-slate-500 hover:text-slate-800\"\n                onClick={() => setConfigModalOpen(false)}\n                type=\"button\"\n              >\n                ✕\n              </button>\n            </div>\n            <form className=\"space-y-3\" onSubmit={submitConfig}>\n              {CONFIG_FIELDS.map((field) => (\n                <label key={field.key} className=\"block text-sm text-slate-700\">\n                  <div className=\"flex items-center justify-between\">\n                    <span className=\"font-semibold text-slate-800\">\n                      {field.label}\n                    </span>\n                    <input\n                      type=\"number\"\n                      name={field.key}\n                      value={configDraft[field.key]}\n                      onChange={(e) =>\n                        setConfigDraft((prev) => ({\n                          ...prev,\n                          [field.key]: e.target.value,\n                        }))\n                      }\n                      className=\"ml-3 w-36 rounded-md border border-slate-200 bg-white text-slate-900 px-3 py-2 text-sm focus:border-sky-300 focus:outline-none focus:ring-2 focus:ring-sky-200\"\n                    />\n                  </div>\n                  <p className=\"mt-1 text-xs text-slate-600\">\n                    {field.description}\n                  </p>\n                </label>\n              ))}\n              <div className=\"flex items-center justify-end gap-2 pt-2\">\n                <button\n                  type=\"button\"\n                  className=\"inline-flex items-center gap-2 rounded-lg border px-3 py-2 text-sm font-medium shadow-sm hover:bg-slate-50\"\n                  onClick={() => setConfigModalOpen(false)}\n                >\n                  Cancel\n                </button>\n                <button\n                  type=\"submit\"\n                  className=\"inline-flex items-center gap-2 rounded-lg border border-sky-200 bg-sky-50 px-3 py-2 text-sm font-medium text-sky-800 shadow-sm hover:bg-sky-100\"\n                >\n                  Apply config\n                </button>\n              </div>\n            </form>\n          </div>\n        </div>\n      )}\n      {eventLogOpen && (\n        <div className=\"fixed inset-0 bg-slate-900/40 flex items-center justify-center z-50\">\n          <div className=\"bg-white rounded-xl shadow-xl border border-slate-200 w-[460px] max-w-full p-5 space-y-4\">\n            <div className=\"flex items-start justify-between\">\n              <div className=\"space-y-1\">\n                <p className=\"text-base font-semibold text-slate-800 leading-snug\">\n                  Event log\n                </p>\n                <br />\n                <p className=\"text-sm text-slate-600 leading-snug\">\n                  Latest simulation events (newest first).\n                </p>\n              </div>\n              <button\n                className=\"text-slate-500 hover:text-slate-800\"\n                onClick={() => setEventLogOpen(false)}\n                type=\"button\"\n              >\n                ✕\n              </button>\n            </div>\n            <div className=\"h-64 overflow-auto rounded-md border border-slate-200 bg-slate-50 p-3 text-[12px] text-slate-800\">\n              {model.log.length === 0 ? (\n                <p className=\"text-slate-500\">Simulation warming up…</p>\n              ) : (\n                <div className=\"flex flex-col gap-1\">\n                  {model.log.map((item, idx) => (\n                    <div\n                      key={`${item.t}-${idx}`}\n                      className=\"leading-tight py-[1px] border-b border-slate-200 last:border-b-0\"\n                    >\n                      <span className=\"text-slate-500 mr-1\">\n                        t+{Math.round(item.t)}ms\n                      </span>\n                      {item.text}\n                    </div>\n                  ))}\n                </div>\n              )}\n            </div>\n            <div className=\"flex justify-end\">\n              <button\n                className=\"inline-flex items-center gap-2 rounded-lg border px-3 py-2 text-sm font-medium shadow-sm hover:bg-slate-50\"\n                onClick={() => setEventLogOpen(false)}\n              >\n                Close\n              </button>\n            </div>\n          </div>\n        </div>\n      )}\n      {selectedNodeId && (\n        <div className=\"fixed inset-0 bg-slate-900/40 flex items-center justify-center z-50\">\n          <div className=\"bg-white rounded-xl shadow-xl border border-slate-200 w-[380px] max-w-full p-5 space-y-4\">\n            {(() => {\n              const node = model.nodes.find((n) => n.id === selectedNodeId);\n              if (!node) return null;\n              const setStatus = (status) => {\n                node.status = status;\n                if (status === \"crashed\") {\n                  node.pendingActions = [];\n                  node.flushScheduled = false;\n                }\n                setTick((t) => t + 1);\n              };\n              return (\n                <>\n                  <div className=\"flex items-start justify-between mb-4\">\n                    <div>\n                      <p className=\"text-base font-semibold text-slate-800\">\n                        {node.label}\n                        <span className=\"ml-2 text-sm font-normal\">\n                          Status:{\" \"}\n                          <span\n                            className={\n                              node.status === \"crashed\"\n                                ? \"text-red-600\"\n                                : node.status === \"lagging\"\n                                ? \"text-amber-600\"\n                                : \"text-emerald-600\"\n                            }\n                          >\n                            {node.status}\n                          </span>\n                        </span>\n                      </p>\n                    </div>\n                    <button\n                      className=\"text-slate-500 hover:text-slate-800\"\n                      onClick={() => setSelectedNodeId(null)}\n                    >\n                      ✕\n                    </button>\n                  </div>\n                  <dl className=\"text-sm text-slate-700 grid grid-cols-2 gap-x-6 gap-y-2 mb-4\">\n                    <dt className=\"font-semibold text-slate-800\">Committed</dt>\n                    <dd>{node.committedTo || \"—\"}</dd>\n                    <dt className=\"font-semibold text-slate-800\">Locked</dt>\n                    <dd>{node.lockedCandidate || \"—\"}</dd>\n                    <dt className=\"font-semibold text-slate-800\">\n                      Vote target\n                    </dt>\n                    <dd>{node.voteTarget || \"—\"}</dd>\n                    <dt className=\"font-semibold text-slate-800\">Approvals</dt>\n                    <dd>{node.approved.size}</dd>\n                    <dt className=\"font-semibold text-slate-800\">Votes</dt>\n                    <dd>{node.voted.size}</dd>\n                    <dt className=\"font-semibold text-slate-800\">Precommits</dt>\n                    <dd>{node.precommitted.size}</dd>\n                    <dt className=\"font-semibold text-slate-800\">\n                      Pending deps\n                    </dt>\n                    <dd>{node.pendingCatchain.size}</dd>\n                  </dl>\n                  <div className=\"flex flex-col gap-2\">\n                    <button\n                      className=\"rounded-lg border px-3 py-2 text-sm font-medium shadow-sm bg-emerald-50 border-emerald-200 text-emerald-800 hover:bg-emerald-100\"\n                      onClick={() => setStatus(\"good\")}\n                    >\n                      Make good\n                    </button>\n                    <button\n                      className=\"rounded-lg border px-3 py-2 text-sm font-medium shadow-sm bg-red-50 border-red-200 text-red-800 hover:bg-red-100\"\n                      onClick={() => setStatus(\"crashed\")}\n                    >\n                      Crash\n                    </button>\n                    <button\n                      className=\"rounded-lg border px-3 py-2 text-sm font-medium shadow-sm bg-amber-50 border-amber-200 text-amber-800 hover:bg-amber-100\"\n                      onClick={() => setStatus(\"lagging\")}\n                    >\n                      Lagging (50% drop)\n                    </button>\n                  </div>\n                </>\n              );\n            })()}\n          </div>\n        </div>\n      )}\n      {selectedMessage && (\n        <div className=\"fixed inset-0 bg-slate-900/40 flex items-center justify-center z-50\">\n          <div className=\"bg-white rounded-xl shadow-xl border border-slate-200 w-[380px] max-w-full p-5 space-y-4\">\n            {(() => {\n              const fromNode = getNode(model, selectedMessage.from);\n              const toNode = getNode(model, selectedMessage.to);\n              const envelope = selectedMessage.envelope;\n              const actions = selectedMessage.actions || [];\n              return (\n                <>\n                  <div className=\"flex items-start justify-between mb-3\">\n                    <div>\n                      <p className=\"text-base font-semibold text-slate-800\">\n                        Message\n                        <span className=\"ml-2 text-sm font-normal text-slate-600 align-middle\">\n                          {selectedMessage.id}\n                        </span>\n                      </p>\n                      <br />\n                      <p className=\"text-sm text-slate-700 font-semibold\">\n                        Type:{\" \"}\n                        <span className=\"font-normal\">\n                          {selectedMessage.primary || selectedMessage.transport}\n                        </span>\n                      </p>\n                    </div>\n                    <button\n                      className=\"text-slate-500 hover:text-slate-800\"\n                      onClick={() => setSelectedMessage(null)}\n                    >\n                      ✕\n                    </button>\n                  </div>\n                  <dl className=\"text-sm text-slate-700\">\n                    <div className=\"flex items-center justify-between py-1\">\n                      <dt className=\"font-semibold text-slate-800\">From</dt>\n                      <dd className=\"text-right\">\n                        {fromNode ? fromNode.label : selectedMessage.from}\n                      </dd>\n                    </div>\n                    <div className=\"flex items-center justify-between py-1\">\n                      <dt className=\"font-semibold text-slate-800\">To</dt>\n                      <dd className=\"text-right\">\n                        {toNode ? toNode.label : selectedMessage.to}\n                      </dd>\n                    </div>\n                    <div className=\"flex items-center justify-between py-1\">\n                      <dt className=\"font-semibold text-slate-800\">\n                        Send → Receive\n                      </dt>\n                      <dd className=\"text-right\">\n                        {Math.round(selectedMessage.sendTime)} →{\" \"}\n                        {Math.round(selectedMessage.recvTime)} ms\n                      </dd>\n                    </div>\n                  </dl>\n                  {selectedMessage.transport === \"Catchain\" && envelope && (\n                    <div className=\"text-sm text-slate-800\">\n                      <p className=\"font-semibold mb-1\">Catchain info</p>\n                      <div className=\"text-slate-700\">\n                        <span className=\"font-semibold\">Message</span>:{\" \"}\n                        {envelope.id} (h{envelope.height || 0})\n                      </div>\n                      <div className=\"text-slate-700\">\n                        <span className=\"font-semibold\">Sender</span>:{\" \"}\n                        {envelope.sender}\n                      </div>\n                      <div className=\"text-slate-700\">\n                        <span className=\"font-semibold\">Prev</span>:{\" \"}\n                        {envelope.prev || \"None\"}\n                      </div>\n                      <div className=\"text-slate-700\">\n                        <span className=\"font-semibold\">Deps</span>:{\" \"}\n                        {(envelope.deps || []).length === 0\n                          ? \"None\"\n                          : (envelope.deps || []).join(\", \")}\n                      </div>\n                    </div>\n                  )}\n                  {selectedMessage.transport === \"DepRequest\" && (\n                    <div className=\"text-sm text-slate-800\">\n                      <p className=\"font-semibold mb-1\">Requested deps</p>\n                      <div className=\"text-slate-700\">\n                        {(selectedMessage.missingIds || []).length === 0\n                          ? \"None listed\"\n                          : (selectedMessage.missingIds || []).join(\", \")}\n                      </div>\n                    </div>\n                  )}\n                  <div className=\"text-sm text-slate-800\">\n                    <p className=\"font-semibold mb-1\">Actions</p>\n                    {actions.length === 0 ? (\n                      <p className=\"text-slate-600\">—</p>\n                    ) : (\n                      <ul className=\"list-disc pl-4 space-y-1\">\n                        {actions.map((act, idx) => (\n                          <li\n                            key={`${act.type}-${idx}`}\n                            className=\"text-slate-700\"\n                          >\n                            {act.type}{\" \"}\n                            {act.candidateId ? `→ ${act.candidateId}` : \"\"}\n                          </li>\n                        ))}\n                      </ul>\n                    )}\n                  </div>\n                  <div className=\"flex items-center justify-between pt-2\">\n                    <button\n                      className=\"rounded-lg border px-3 py-2 text-sm font-medium shadow-sm bg-red-50 border-red-200 text-red-800 hover:bg-red-100\"\n                      onClick={() => {\n                        model.messages = model.messages.filter(\n                          (m) => m !== selectedMessage\n                        );\n                        setSelectedMessage(null);\n                        setTick((t) => t + 1);\n                      }}\n                    >\n                      Drop message\n                    </button>\n                    <button\n                      className=\"text-slate-500 hover:text-slate-800 text-sm\"\n                      onClick={() => setSelectedMessage(null)}\n                    >\n                      Close\n                    </button>\n                  </div>\n                </>\n              );\n            })()}\n          </div>\n        </div>\n      )}\n      {selectedCandidateId && (\n        <div className=\"fixed inset-0 bg-slate-900/40 flex items-center justify-center z-50\">\n          <div className=\"bg-white rounded-xl shadow-xl border border-slate-200 w-[340px] max-w-full p-4 space-y-3 max-h-[90vh] overflow-auto\">\n            {(() => {\n              const cand = model.candidates[selectedCandidateId];\n              if (!cand) return null;\n              const proposer = cand.proposerId\n                ? model.nodes.find((n) => n.id === cand.proposerId)\n                : null;\n              return (\n                <>\n                  <div className=\"flex items-start justify-between mb-2\">\n                    <div>\n                      <p className=\"text-base font-semibold text-slate-800\">\n                        Candidate{\" \"}\n                        <span className=\"font-normal text-slate-600\">\n                          {cand.id}\n                        </span>\n                      </p>\n                      <p className=\"text-sm text-slate-700\">\n                        Round {cand.round}, attempt {cand.attempt}\n                      </p>\n                    </div>\n                    <button\n                      className=\"text-slate-500 hover:text-slate-800\"\n                      onClick={() => setSelectedCandidateId(null)}\n                    >\n                      ✕\n                    </button>\n                  </div>\n                  <dl className=\"text-sm text-slate-700\">\n                    <div className=\"flex items-center justify-between py-1\">\n                      <dt className=\"font-semibold text-slate-800 pr-4\">\n                        Proposer\n                      </dt>\n                      <dd className=\"text-right\">\n                        {proposer ? proposer.label : cand.proposerId}\n                      </dd>\n                    </div>\n                    <div className=\"flex items-center justify-between py-1\">\n                      <dt className=\"font-semibold text-slate-800 pr-4\">\n                        Priority\n                      </dt>\n                      <dd className=\"text-right\">{cand.priority}</dd>\n                    </div>\n                    <div className=\"flex items-center justify-between py-1\">\n                      <dt className=\"font-semibold text-slate-800 pr-4\">\n                        Approvals\n                      </dt>\n                      <dd className=\"text-right\">{cand.approvals.size}</dd>\n                    </div>\n                    <div className=\"flex items-center justify-between py-1\">\n                      <dt className=\"font-semibold text-slate-800 pr-4\">\n                        Votes\n                      </dt>\n                      <dd className=\"text-right\">{cand.votes.size}</dd>\n                    </div>\n                    <div className=\"flex items-center justify-between py-1\">\n                      <dt className=\"font-semibold text-slate-800 pr-4\">\n                        Precommits\n                      </dt>\n                      <dd className=\"text-right\">{cand.precommits.size}</dd>\n                    </div>\n                    <div className=\"flex items-center justify-between py-1\">\n                      <dt className=\"font-semibold text-slate-800 pr-4\">\n                        Commits\n                      </dt>\n                      <dd className=\"text-right\">{cand.commits.size}</dd>\n                    </div>\n                  </dl>\n                  <div className=\"text-sm text-slate-800\">\n                    <p className=\"font-semibold mb-1\">\n                      Per-node approvals seen\n                    </p>\n                    <div className=\"grid grid-cols-2 gap-2 max-h-32 overflow-auto border border-slate-100 rounded p-2 bg-slate-50\">\n                      {model.nodes.map((n) => (\n                        <div\n                          key={n.id}\n                          className=\"flex items-center justify-between text-xs\"\n                        >\n                          <span className=\"text-slate-700\">{n.label}</span>\n                          <span className=\"text-slate-900\">\n                            {n.receivedEvents[cand.id]?.approved || 0}\n                          </span>\n                        </div>\n                      ))}\n                    </div>\n                  </div>\n                  <div className=\"text-sm text-slate-800\">\n                    <p className=\"font-semibold mb-1\">Per-node votes seen</p>\n                    <div className=\"grid grid-cols-2 gap-2 max-h-32 overflow-auto border border-slate-100 rounded p-2 bg-slate-50\">\n                      {model.nodes.map((n) => (\n                        <div\n                          key={n.id}\n                          className=\"flex items-center justify-between text-xs\"\n                        >\n                          <span className=\"text-slate-700\">{n.label}</span>\n                          <span className=\"text-slate-900\">\n                            {n.receivedEvents[cand.id]?.voted || 0}\n                          </span>\n                        </div>\n                      ))}\n                    </div>\n                  </div>\n                  <div className=\"text-sm text-slate-800\">\n                    <p className=\"font-semibold mb-1\">\n                      Per-node precommits seen\n                    </p>\n                    <div className=\"grid grid-cols-2 gap-2 max-h-32 overflow-auto border border-slate-100 rounded p-2 bg-slate-50\">\n                      {model.nodes.map((n) => (\n                        <div\n                          key={n.id}\n                          className=\"flex items-center justify-between text-xs\"\n                        >\n                          <span className=\"text-slate-700\">{n.label}</span>\n                          <span className=\"text-slate-900\">\n                            {n.receivedEvents[cand.id]?.precommitted || 0}\n                          </span>\n                        </div>\n                      ))}\n                    </div>\n                  </div>\n                  <div className=\"text-sm text-slate-800\">\n                    <p className=\"font-semibold mb-1\">Per-node commits seen</p>\n                    <div className=\"grid grid-cols-2 gap-2 max-h-32 overflow-auto border border-slate-100 rounded p-2 bg-slate-50\">\n                      {model.nodes.map((n) => (\n                        <div\n                          key={n.id}\n                          className=\"flex items-center justify-between text-xs\"\n                        >\n                          <span className=\"text-slate-700\">{n.label}</span>\n                          <span className=\"text-slate-900\">\n                            {n.receivedEvents[cand.id]?.commited || 0}\n                          </span>\n                        </div>\n                      ))}\n                    </div>\n                  </div>\n                </>\n              );\n            })()}\n          </div>\n        </div>\n      )}\n    </div>\n  );\n};\n"
  },
  {
    "path": "snippets/feePlayground.jsx",
    "content": "export const FeePlayground = () => {\n  const nano = 10 ** -9;\n  const bit16 = 2 ** 16;\n  const LocalNote = ({ title, children }) => (\n    <div className=\"my-3 px-4 py-3 rounded-2xl border border-sky-500/20 bg-sky-50/50 dark:border-sky-500/30 dark:bg-sky-500/10\">\n      {title && (\n        <div className=\"text-xs font-semibold text-sky-900 dark:text-sky-200 mb-1\">\n          {title}\n        </div>\n      )}\n      <div className=\"text-xs text-sky-900 dark:text-sky-200\">\n        {children}\n      </div>\n    </div>\n  );\n\n  const compute = (form) => {\n    const presets = {\n      // #25 - Messages prices (basechain)\n      basechain: {\n        lump_price: 400000,\n        bit_price: 26214400,\n        cell_price: 2621440000,\n        first_frac: 21845,\n        next_frac: 21845,\n      },\n      // #24 - Masterchain messages prices\n      masterchain: {\n        lump_price: 10000000,\n        bit_price: 655360000,\n        cell_price: 65536000000,\n        first_frac: 21845,\n        next_frac: 21845,\n      },\n    };\n    const storagePrices = {\n      basechain: { bit_ps: 1, cell_ps: 500 },\n      masterchain: { bit_ps: 1000, cell_ps: 500000 },\n    };\n\n    const net = form.network.value === 'masterchain' ? 'masterchain' : 'basechain';\n    const { lump_price: lumpPrice, bit_price: bitPrice, cell_price: cellPrice, first_frac: firstFrac } = presets[net];\n\n    const importBits = Number(form.import_bits.value || 0);\n    const importCells = Number(form.import_cells.value || 0);\n    const fwdBits = Number(form.fwd_bits.value || 0);\n    const fwdCells = Number(form.fwd_cells.value || 0);\n\n    const gasFeesTon = Number(form.gas_fees_ton.value || 0);\n\n    // Account storage parameters\n    const accountBits = Number(form.account_bits.value || 0);\n    const accountCells = Number(form.account_cells.value || 0);\n    const { bit_ps, cell_ps } = storagePrices[net];\n\n    const timeDelta = Number(form.time_delta.value || 69);\n\n    // Compute storage fee from account params (nanotons)\n    const storageFeeNano = Math.ceil(((accountBits * bit_ps + accountCells * cell_ps) * timeDelta) / bit16);\n    const storageFeesTon = storageFeeNano * nano;\n    // storage fee is displayed in the results area only\n\n    const fwdFee = lumpPrice + Math.ceil((bitPrice * fwdBits + cellPrice * fwdCells) / bit16);\n    const totalFwdFees = fwdFee;\n    const totalActionFees = +((fwdFee * firstFrac) / bit16).toFixed(9);\n    const importFee = lumpPrice + Math.ceil((bitPrice * importBits + cellPrice * importCells) / bit16);\n    const totalFeeTon = gasFeesTon + storageFeesTon + importFee * nano + totalFwdFees * nano;\n\n    const setOut = (key, value) => {\n      const el = form.querySelector(`[data-out=\"${key}\"]`);\n      if (el) el.textContent = value;\n    };\n\n    setOut('total', totalFeeTon.toFixed(9));\n    setOut('action', (totalActionFees * nano).toFixed(9));\n    setOut('fwd', (totalFwdFees * nano).toFixed(9));\n    setOut('import', (importFee * nano).toFixed(9));\n    setOut('gas', gasFeesTon.toFixed(9));\n    setOut('storage', storageFeesTon.toFixed(9));\n  };\n\n  const init = (node) => {\n    if (node) compute(node);\n  };\n\n  return (\n    <form ref={init} onInput={(e) => compute(e.currentTarget)} className=\"not-prose my-4 p-4 border rounded-xl dark:border-white/20 border-black/10\">\n      <div className=\"flex items-center justify-between gap-3 mb-3\">\n        <div className=\"text-xs\">Network</div>\n        <div>\n          <select name=\"network\" defaultValue=\"basechain\" className=\"border rounded-md px-2 py-1 bg-transparent text-sm\">\n            <option value=\"basechain\">Basechain</option>\n            <option value=\"masterchain\">Masterchain</option>\n          </select>\n        </div>\n      </div>\n\n      <div className=\"grid grid-cols-1 md:grid-cols-2 gap-3\">\n        <div className=\"space-y-2\">\n          <h4 className=\"font-semibold text-sm\">Import Payload</h4>\n          <label className=\"block text-xs\">import bits\n            <input name=\"import_bits\" defaultValue={528} className=\"mt-1 w-full border rounded-md px-2 py-1 bg-transparent\" type=\"number\" />\n          </label>\n          <label className=\"block text-xs\">import cells\n            <input name=\"import_cells\" defaultValue={1} className=\"mt-1 w-full border rounded-md px-2 py-1 bg-transparent\" type=\"number\" />\n          </label>\n        </div>\n\n        <div className=\"space-y-2\">\n          <h4 className=\"font-semibold text-sm\">Forward Payload</h4>\n          <label className=\"block text-xs\">fwd bits\n            <input name=\"fwd_bits\" defaultValue={0} className=\"mt-1 w-full border rounded-md px-2 py-1 bg-transparent\" type=\"number\" />\n          </label>\n          <label className=\"block text-xs\">fwd cells\n            <input name=\"fwd_cells\" defaultValue={0} className=\"mt-1 w-full border rounded-md px-2 py-1 bg-transparent\" type=\"number\" />\n          </label>\n        </div>\n      </div>\n\n      <div className=\"mt-4\">\n        <h4 className=\"font-semibold text-sm\">Account storage</h4>\n        <div className=\"grid grid-cols-1 md:grid-cols-3 gap-3\">\n          <label className=\"block text-xs\">bits\n            <input name=\"account_bits\" defaultValue={1323} className=\"mt-1 w-full border rounded-md px-2 py-1 bg-transparent\" type=\"number\" />\n          </label>\n          <label className=\"block text-xs\">cells\n            <input name=\"account_cells\" defaultValue={3} className=\"mt-1 w-full border rounded-md px-2 py-1 bg-transparent\" type=\"number\" />\n          </label>\n          <label className=\"block text-xs\">time delta from Prev. tx (sec)\n            <input name=\"time_delta\" defaultValue=\"69\" className=\"mt-1 w-full border rounded-md px-2 py-1 bg-transparent\" type=\"number\" step=\"0.00001\" />\n          </label>\n        </div>\n        <LocalNote title=\"Where to get payload sizes?\">\n          You can find import, forward and storage parameters in the Executor logs (txtracer/retracer) for a specific transaction.\n        </LocalNote>\n      </div>\n\n      <div className=\"mt-4\">\n        <h4 className=\"font-semibold text-sm\">Compute fee</h4>\n        <LocalNote title=\"Why enter gas manually?\">\n          The compute (gas) cost cannot be predicted by a static formula. <br />\n          Measure it in tests or read it from the executor logs / explorer, then enter the gas fee here.\n        </LocalNote>\n        <div className=\"grid grid-cols-1 gap-3\">\n          <label className=\"block text-xs\">Gas fee (TON)\n            <input name=\"gas_fees_ton\" defaultValue=\"0.0011976\" step=\"0.000000001\" className=\"mt-1 w-full border rounded-md px-2 py-1 bg-transparent\" type=\"number\" />\n          </label>\n        </div>\n      </div>\n\n      <div className=\"mt-4 text-sm grid grid-cols-1 md:grid-cols-2 gap-2\">\n        <div className=\"space-y-1\">\n          <div>Fwd. fee: <strong><span data-out=\"fwd\"></span> TON</strong></div>\n          <div>Gas fee: <strong><span data-out=\"gas\"></span> TON</strong></div>\n          <div>Storage fee: <strong><span data-out=\"storage\"></span> TON</strong></div>\n          <div>Action fee: <strong><span data-out=\"action\"></span> TON</strong></div>\n        </div>\n        <div className=\"space-y-1\">\n          <div>Import fee: <strong><span data-out=\"import\"></span> TON</strong></div>\n          <div>Total fee: <strong><span data-out=\"total\"></span> TON</strong></div>\n        </div>\n      </div>\n    </form>\n  );\n};\n\n"
  },
  {
    "path": "snippets/fence-table.jsx",
    "content": "export const FenceTable = ({children}) => {\n    return <pre style={{\n        'font-family': 'monospace',\n        'white-space': 'pre',\n        'overflow-x': 'auto',\n        'font-size': '14px',\n    }}>\n    {children}\n  </pre>;\n}\n"
  },
  {
    "path": "snippets/filetree.jsx",
    "content": "/**\n * @typedef {(\n *   {name: string, note?: string}\n * )} FileTreeItemCommon\n *\n * @typedef {(\n *   | '...'\n *   | '…'\n *   | string\n *   | FileTreeItemCommon & {kind: 'file'}\n *   | FileTreeItemCommon & {kind: 'folder', open?: boolean, items?: FileTreeItem[] }\n * )} FileTreeItem\n *\n * @param {{ items: FileTreeItem[], defaultOpen?: boolean }} props\n */\nexport const FileTree = ({ items = [], defaultOpen = true }) => {\n  /**\n   * @param {FileTreeItem} item\n   * @param {import(\"react\").Key | null | undefined} index\n   */\n  const renderItem = (item, index) => {\n    // Handle ellipsis items\n    if (item === \"...\" || item === \"…\") {\n      // @ts-ignore\n      return <Tree.File key={index} name=\"…\" />;\n    }\n\n    // Handle file items (both string and file objects)\n    if (typeof item === \"string\" || item.kind === \"file\") {\n      const fileName = typeof item === \"string\" ? item : item.name;\n      const note = typeof item === \"string\" ? null : item.note;\n      const displayName = note ? `${fileName} — ${note}` : fileName;\n\n      // @ts-ignore\n      return <Tree.File key={index} name={displayName} />;\n    }\n\n    // Handle folder objects\n    if (item.kind === \"folder\") {\n      const isOpen = item.open ?? defaultOpen;\n      const displayName = item.note ? `${item.name} — ${item.note}` : item.name;\n\n      return (\n        // @ts-ignore\n        <Tree.Folder key={index} name={displayName} defaultOpen={isOpen}>\n          {item?.items?.map((nestedItem, nestedIndex) => renderItem(nestedItem, nestedIndex))}\n          {/* @ts-ignore */}\n        </Tree.Folder>\n      );\n    }\n\n    throw new Error(\n      [\n        `In the FileTree component, found: ${item}.`,\n        `Expected either of: ..., …, string, { kind: \"file\", ... }, or { kind: \"folder\", ... }`,\n      ].join(' '),\n    );\n  };\n\n  // @ts-ignore\n  return <Tree>{items.map((item, index) => renderItem(item, index))}</Tree>;\n};\n"
  },
  {
    "path": "snippets/image.jsx",
    "content": "/**\n * @param {{\n *   src: string,\n *   darkSrc?: string,\n *   alt?: string,\n *   darkAlt?: string,\n *   href?: string,\n *   target?: '_self' | '_blank' | '_parent' | '_top' | '_unfencedTop',\n *   height?: string | number,\n *   width?: string | number,\n *   noZoom?: string | boolean,\n *   center?: string | boolean,\n * }} props\n */\nexport const Image = ({\n  src,\n  darkSrc,\n  alt = '',\n  darkAlt,\n  href,\n  target,\n  height = 342,\n  width = 608,\n  noZoom = false,\n  center = false,\n}) => {\n  const isSVG = src.match(/\\.svg(?:[#?].*?)?$/i) !== null;\n  const shouldInvert = isSVG && !darkSrc;\n  const shouldCreateLink = href !== undefined;\n  const minPx = 9;\n  const maxPx = 608;\n  const expectedPx = `a number or a string with a number that is greater than ${minPx - 1} and less than or equal to ${maxPx}`;\n\n  /**\n   * @param title {string}\n   * @param received {string | number}\n   * @param expected {string | number}\n   */\n  const createInvalidPropCallout = (title, received, expected) => {\n    return (\n      // @ts-ignore\n      <Danger>\n        <span className=\"font-bold\">\n          Invalid <code>{title.toString()}</code> passed!\n        </span>\n        <br />\n        <span className=\"font-bold\">Received: </span>\n        {received.toString()}\n        <br />\n        <span className=\"font-bold\">Expected: </span>\n        {expected.toString()}\n        {/* @ts-ignore */}\n      </Danger>\n    );\n  };\n\n  /** @param value {string | number} */\n  const checkValidDimensionValue = (value) => {\n    switch (typeof value) {\n      case \"string\":\n      case \"number\":\n        const num = Number(value);\n        return Number.isSafeInteger(num) && num >= minPx && num <= maxPx;\n      default:\n        return false;\n    }\n  };\n\n  // Collect error callouts\n  let callouts = [];\n\n  // Invalid image height (in pixels)\n  if (height && !checkValidDimensionValue(height)) {\n    callouts.push(createInvalidPropCallout(\"height\", height, expectedPx));\n  }\n\n  // Invalid image width (in pixels)\n  if (width && !checkValidDimensionValue(width)) {\n    callouts.push(createInvalidPropCallout(\"width\", width, expectedPx));\n  }\n\n  // Display all errors\n  if (callouts.length !== 0) {\n    return callouts;\n  }\n\n  // Resulting pixel dimensions\n  const heightPx = Number(height);\n  const widthPx = Number(width);\n\n  // Typecast string | boolean values to boolean-only\n  const shouldCenter = center === \"true\" || center === true ? true : false;\n  const shouldNotZoom = noZoom === \"true\" || noZoom === true ? true : false;\n\n  // Resulting images\n  const images = (\n    <>\n      <img\n        className=\"block dark:hidden\"\n        src={src}\n        alt={alt}\n        {...(height && { height: heightPx })}\n        {...(width && { width: widthPx })}\n        // @ts-ignore\n        {...((shouldCreateLink || shouldInvert || shouldNotZoom) && { noZoom: \"true\" })}\n      />\n      <img\n        className={`hidden dark:block ${shouldInvert ? \"invert\" : \"\"}`}\n        src={darkSrc ?? src}\n        alt={darkAlt ?? alt}\n        {...(height && { height: heightPx })}\n        {...(width && { width: widthPx })}\n        // @ts-ignore\n        {...((shouldCreateLink || shouldInvert || shouldNotZoom) && { noZoom: \"true\" })}\n      />\n    </>\n  );\n\n  // Is a clickable link\n  if (shouldCreateLink) {\n    // Centered horizontally\n    if (shouldCenter) {\n      return (\n        <div style={{ display: \"flex\", justifyContent: \"center\" }}>\n          <a href={href} target={target ?? \"_self\"}>\n            {images}\n          </a>\n        </div>\n      );\n    }\n\n    return (\n      <a href={href} target={target ?? \"_self\"}>\n        {images}\n      </a>\n    );\n  }\n\n  // Not a link, centered horizontally\n  if (shouldCenter) {\n    return <div style={{ display: \"flex\", justifyContent: \"center\" }}>{images}</div>;\n  }\n\n  // Not a link, placed as is\n  return images;\n};\n"
  },
  {
    "path": "snippets/stub.jsx",
    "content": "export const Stub = ({ issue }) => {\n    // Obviously neither imports not variables in Mintlify snippets do not work :)\n    // Copy-paste of aside.jsx\n    const Aside = ({ type = \"note\", title = \"\", icon = \"\", iconType = \"regular\", children }) => {\n        const asideVariants = [\"note\", \"tip\", \"caution\", \"danger\"];\n        const asideComponents = {\n            note: {\n                outerStyle: \"border-sky-500/20 bg-sky-50/50 dark:border-sky-500/30 dark:bg-sky-500/10\",\n                innerStyle: \"text-sky-900 dark:text-sky-200\",\n                calloutType: \"note\",\n                icon: (\n                    <svg\n                        width=\"14\"\n                        height=\"14\"\n                        viewBox=\"0 0 14 14\"\n                        fill=\"currentColor\"\n                        xmlns=\"http://www.w3.org/2000/svg\"\n                        className=\"w-4 h-4 text-sky-500\"\n                        aria-label=\"Note\"\n                    >\n                        <path\n                            fill-rule=\"evenodd\"\n                            clip-rule=\"evenodd\"\n                            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\"\n                        ></path>\n                    </svg>\n                ),\n            },\n            tip: {\n                outerStyle: \"border-emerald-500/20 bg-emerald-50/50 dark:border-emerald-500/30 dark:bg-emerald-500/10\",\n                innerStyle: \"text-emerald-900 dark:text-emerald-200\",\n                calloutType: \"tip\",\n                icon: (\n                    <svg\n                        width=\"11\"\n                        height=\"14\"\n                        viewBox=\"0 0 11 14\"\n                        fill=\"currentColor\"\n                        xmlns=\"http://www.w3.org/2000/svg\"\n                        className=\"text-emerald-600 dark:text-emerald-400/80 w-3.5 h-auto\"\n                        aria-label=\"Tip\"\n                    >\n                        <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>\n                    </svg>\n                ),\n            },\n            caution: {\n                outerStyle: \"border-amber-500/20 bg-amber-50/50 dark:border-amber-500/30 dark:bg-amber-500/10\",\n                innerStyle: \"text-amber-900 dark:text-amber-200\",\n                calloutType: \"warning\",\n                icon: (\n                    <svg\n                        className=\"flex-none w-5 h-5 text-amber-400 dark:text-amber-300/80\"\n                        fill=\"none\"\n                        viewBox=\"0 0 24 24\"\n                        stroke=\"currentColor\"\n                        stroke-width=\"2\"\n                        aria-label=\"Warning\"\n                    >\n                        <path\n                            stroke-linecap=\"round\"\n                            stroke-linejoin=\"round\"\n                            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\"\n                        ></path>\n                    </svg>\n                ),\n            },\n            danger: {\n                outerStyle: \"border-red-500/20 bg-red-50/50 dark:border-red-500/30 dark:bg-red-500/10\",\n                innerStyle: \"text-red-900 dark:text-red-200\",\n                calloutType: \"danger\",\n                icon: (\n                    <svg\n                        xmlns=\"http://www.w3.org/2000/svg\"\n                        viewBox=\"0 0 512 512\"\n                        fill=\"currentColor\"\n                        className=\"text-red-600 dark:text-red-400/80 w-4 h-4\"\n                        aria-label=\"Danger\"\n                    >\n                        <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>\n                    </svg>\n                ),\n            },\n        };\n        let variant = type;\n        let gotInvalidVariant = false;\n        if (!asideVariants.includes(type)) {\n            gotInvalidVariant = true;\n            variant = \"danger\";\n        }\n        const iconVariants = [\"regular\", \"solid\", \"light\", \"thin\", \"sharp-solid\", \"duotone\", \"brands\"];\n        if (!iconVariants.includes(iconType)) {\n            iconType = \"regular\";\n        }\n    \n        return (\n            <>\n                <div\n                    className={`callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border ${asideComponents[variant].outerStyle}`}\n                    data-callout-type={asideComponents[variant].calloutType}\n                >\n                    <div className=\"mt-0.5 w-4\" data-component-part=\"callout-icon\">\n                        {/* @ts-ignore */}\n                        {icon === \"\" ? asideComponents[variant].icon : <Icon icon={icon} iconType={iconType} size={14} />}\n                    </div>\n                    <div\n                        className={`text-sm prose min-w-0 w-full ${asideComponents[variant].innerStyle}`}\n                        data-component-part=\"callout-content\"\n                    >\n                        {gotInvalidVariant ? (\n                            <p>\n                                <span className=\"font-bold\">\n                                    Invalid <code>type</code> passed!\n                                </span>\n                                <br />\n                                <span className=\"font-bold\">Received: </span>\n                                {type}\n                                <br />\n                                <span className=\"font-bold\">Expected one of: </span>\n                                {asideVariants.join(\", \")}\n                            </p>\n                        ) : (\n                            <>\n                                {title && <p className=\"font-bold\">{title}</p>}\n                                {children}\n                            </>\n                        )}\n                    </div>\n                </div>\n            </>\n        );\n    };\n    \n    const issueEl = issue\n        ? (\n            <>\n                You can track progress on this page in <a href={`https://github.com/ton-org/docs/issues/${issue}`}>issue #{issue}</a>.\n            </>\n        )\n        : null;\n\n    return (\n        <Aside>\n            This page is a placeholder. {issueEl}\n        </Aside>\n    );\n};\n"
  },
  {
    "path": "snippets/tvm-instruction-table.jsx",
    "content": "const React =\n    typeof globalThis !== \"undefined\" && globalThis.React\n      ? globalThis.React\n      : (() => {\n          throw new Error(\n            \"React global missing. TvmInstructionTable must run inside a React-powered environment.\"\n          );\n        })();\n\nexport const TvmInstructionTable = () => {\n  const { useCallback, useEffect, useMemo, useRef, useState } = React;\n\n  const PERSIST_KEY = \"tvm-instruction-table::filters\";\n\n  const SPEC_URL = \"/resources/tvm/cp0.txt\";\n\n  const CATEGORY_MAP = {\n    stack_basic: \"Stack basics\",\n    stack_complex: \"Stack (complex)\",\n    arithm_basic: \"Arithmetic (basic)\",\n    arithm_div: \"Arithmetic (division)\",\n    arithm_logical: \"Arithmetic (logical)\",\n    arithm_quiet: \"Arithmetic (quiet)\",\n    cell_build: \"Cell builders\",\n    cell_parse: \"Cell parsers\",\n    codepage: \"Codepage management\",\n    compare_int: \"Comparisons (integers)\",\n    compare_other: \"Comparisons (other)\",\n    const_data: \"Constants (data)\",\n    const_int: \"Constants (integers)\",\n    cont_basic: \"Continuations (basic)\",\n    cont_conditional: \"Continuations (conditional)\",\n    cont_create: \"Continuations (creation)\",\n    cont_dict: \"Continuations (dictionary)\",\n    cont_loops: \"Continuations (loops)\",\n    cont_registers: \"Continuations (registers)\",\n    cont_stack: \"Continuations (stack)\",\n    dict_delete: \"Dictionaries (delete)\",\n    dict_get: \"Dictionaries (lookup)\",\n    dict_mayberef: \"Dictionaries (maybe ref)\",\n    dict_min: \"Dictionaries (min/max)\",\n    dict_next: \"Dictionaries (iteration)\",\n    dict_prefix: \"Dictionaries (prefix)\",\n    dict_serial: \"Dictionaries (serialization)\",\n    dict_set: \"Dictionaries (store)\",\n    dict_set_builder: \"Dictionaries (builder)\",\n    dict_special: \"Dictionaries (special)\",\n    dict_sub: \"Dictionaries (sub-dictionaries)\",\n    app_actions: \"Actions\",\n    app_addr: \"Addresses\",\n    app_config: \"Blockchain configuration\",\n    app_crypto: \"Cryptography\",\n    app_currency: \"Currency\",\n    app_gas: \"Gas & fees\",\n    app_global: \"Global variables\",\n    app_misc: \"Misc\",\n    app_rnd: \"Randomness\",\n    app_gaslimits: \"Gas limits\",\n    app_storage: \"Contract storage\",\n    exceptions: \"Exceptions & control\",\n    debug: \"Debugging\",\n    tuple: \"Tuples\",\n  };\n\n  const CATEGORY_GROUPS = [\n    {\n      key: \"stack\",\n      label: \"Stack\",\n      patterns: [/^stack_/],\n    },\n    {\n      key: \"continuations\",\n      label: \"Continuations & Control Flow\",\n      patterns: [/^cont_/, /^codepage$/],\n    },\n    {\n      key: \"arithmetic\",\n      label: \"Arithmetic & Logic\",\n      patterns: [/^arithm_/, /^compare_/],\n    },\n    {\n      key: \"cells\",\n      label: \"Cells & Tuples\",\n      patterns: [/^cell_/, /^tuple$/],\n    },\n    {\n      key: \"dictionaries\",\n      label: \"Dictionaries\",\n      patterns: [/^dict_/],\n    },\n    {\n      key: \"constants\",\n      label: \"Constants\",\n      patterns: [/^const_/],\n    },\n    {\n      key: \"crypto\",\n      label: \"Crypto\",\n      patterns: [/^app_crypto/],\n    },\n    {\n      key: \"applications\",\n      label: \"Blockchain\",\n      patterns: [/^app_(?!crypto)/],\n    },\n    {\n      key: \"exceptions\",\n      label: \"Exceptions\",\n      patterns: [/^exceptions$/],\n    },\n    {\n      key: \"debug\",\n      label: \"Debugging\",\n      patterns: [/^debug$/],\n    }\n  ];\n\n  const CATEGORY_GROUP_KEYS = new Set(\n    CATEGORY_GROUPS.map((group) => group.key)\n  );\n\n  function resolveCategoryGroup(categoryKey) {\n    const normalized = (categoryKey || \"\").toLowerCase();\n    for (const group of CATEGORY_GROUPS) {\n      if (\n        Array.isArray(group.patterns) &&\n        group.patterns.length > 0 &&\n        group.patterns.some((pattern) => pattern.test(normalized))\n      ) {\n        return group;\n      }\n    }\n    return CATEGORY_GROUPS[CATEGORY_GROUPS.length - 1];\n  }\n\n  function humanizeCategoryKey(key) {\n    if (!key) return \"Uncategorized\";\n    if (CATEGORY_MAP[key]) return CATEGORY_MAP[key];\n    return key\n      .split(/[_\\s]+/)\n      .filter(Boolean)\n      .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n      .join(\" \");\n  }\n\n  function formatGasDisplay(gas) {\n    if (Array.isArray(gas)) {\n      return gas.length > 0 ? gas.join(\" / \") : \"N/A\";\n    }\n    if (typeof gas === \"number\") {\n      return gas.toLocaleString();\n    }\n    if (typeof gas === \"string\") {\n      const value = gas.trim();\n      if (!value) return \"N/A\";\n      return value.replace(/\\//g, \" / \").replace(/\\s+/g, \" \");\n    }\n    return \"N/A\";\n  }\n\n  function formatOperandSummary(operand) {\n    if (!operand) return \"\";\n    const name =\n      typeof operand.name === \"string\" && operand.name ? operand.name : \"?\";\n    const type = typeof operand.type === \"string\" ? operand.type : \"\";\n    const size =\n      typeof operand.size === \"number\"\n        ? operand.size\n        : typeof operand.bits === \"number\"\n        ? operand.bits\n        : undefined;\n    const hasRange =\n      operand.min_value !== undefined &&\n      operand.min_value !== null &&\n      operand.max_value !== undefined &&\n      operand.max_value !== null;\n    const range = hasRange\n      ? ` [${operand.min_value}; ${operand.max_value}]`\n      : \"\";\n    const sizePart = size !== undefined ? `(${size})` : \"\";\n    return `${name}${type ? `:${type}` : \"\"}${sizePart}${range}`;\n  }\n\n  function formatInlineMarkdown(text) {\n    if (typeof text !== \"string\") return \"\";\n    const trimmed = text.trim();\n    if (!trimmed) return \"\";\n    const escaped = trimmed\n      .replace(/&/g, \"&amp;\")\n      .replace(/</g, \"&lt;\")\n      .replace(/>/g, \"&gt;\");\n    const withCode = escaped.replace(/`([^`]+)`/g, (_match, code) => {\n      return `<code>${code}</code>`;\n    });\n    const withLinks = withCode.replace(\n      /\\[([^\\]]+)\\]\\((https?:[^)\\s]+)\\)/g,\n      (_match, label, url) =>\n        `<a href=\"${url}\" target=\"_blank\" rel=\"noreferrer\">${label}</a>`\n    );\n    return withLinks.replace(/\\n/g, \"<br />\");\n  }\n\n  function compareOpcodes(a, b) {\n    const sanitize = (value) => (value || \"\").replace(/[^0-9a-f]/gi, \"\");\n    const ax = Number.parseInt(sanitize(a), 16);\n    const bx = Number.parseInt(sanitize(b), 16);\n    if (!Number.isNaN(ax) && !Number.isNaN(bx) && ax !== bx) {\n      return ax - bx;\n    }\n    return (a || \"\").localeCompare(b || \"\");\n  }\n\n  // Search helpers for relevance-based filtering and sorting\n  function createSearchTokens(query) {\n    if (typeof query !== \"string\") return [];\n    return query\n      .toLowerCase()\n      .split(/\\s+/)\n      .map((t) => t.trim())\n      .filter((t) => t.length >= 2); // drop 1-char tokens as too noisy\n  }\n\n  function escapeRegExp(value) {\n    return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n  }\n\n  function highlightMatches(text, tokens) {\n    if (typeof text !== \"string\") return text;\n    const safeTokens = Array.isArray(tokens)\n      ? tokens.filter((token) => token && token.length > 0)\n      : [];\n    if (safeTokens.length === 0) return text;\n    const pattern = safeTokens.map(escapeRegExp).join(\"|\");\n    const regex = new RegExp(`(${pattern})`, \"gi\");\n    const parts = text.split(regex);\n    return parts.map((part, idx) =>\n      idx % 2 === 1 ? (\n        <span key={`highlight-${idx}`} className=\"tvm-highlight\">\n          {part}\n        </span>\n      ) : (\n        part\n      )\n    );\n  }\n\n  function highlightHtmlContent(html, tokens) {\n    if (typeof html !== \"string\") return html || \"\";\n    const safeTokens = Array.isArray(tokens)\n      ? tokens.filter((token) => token && token.length > 0)\n      : [];\n    if (safeTokens.length === 0) return html;\n    const pattern = safeTokens.map(escapeRegExp).join(\"|\");\n    if (!pattern) return html;\n    const regex = new RegExp(`(${pattern})`, \"gi\");\n    return html\n      .split(/(<[^>]+>)/g)\n      .map((segment) => {\n        if (segment.startsWith(\"<\")) return segment;\n        return segment.replace(regex, '<span class=\"tvm-highlight\">$1</span>');\n      })\n      .join(\"\");\n  }\n\n  function getItemSearchFields(item) {\n    const aliasMnemonics = Array.isArray(item.aliases)\n      ? item.aliases\n          .map((alias) => (typeof alias.mnemonic === \"string\" ? alias.mnemonic : \"\"))\n          .filter(Boolean)\n      : [];\n    return {\n      mnemonic: String(item.mnemonic || \"\").toLowerCase(),\n      opcode: String(item.opcode || \"\").toLowerCase(),\n      fift: String(item.fift || \"\").toLowerCase(),\n      aliases: aliasMnemonics.map((s) => s.toLowerCase()),\n    };\n  }\n\n  function computeFieldMatchScore(field, token) {\n    if (!token) return null;\n    if (!field) return null;\n    if (field === token) return 0; // exact\n    if (field.startsWith(token)) return 3; // prefix\n    if (field.includes(token)) return 7; // substring\n    return null; // no match\n  }\n\n  function computeBestAliasMatchScore(aliases, token) {\n    if (!Array.isArray(aliases) || aliases.length === 0) return null;\n    let best = null;\n    for (const a of aliases) {\n      const s = computeFieldMatchScore(a, token);\n      if (s === 0) return 1; // alias exact slightly worse than mnemonic exact\n      if (s !== null) best = best === null ? s + 1 : Math.min(best, s + 1);\n    }\n    return best;\n  }\n\n  function itemRelevanceScore(item, tokens) {\n    if (!Array.isArray(tokens) || tokens.length === 0) return 1000; // neutral when no query\n    const { mnemonic, opcode, fift, aliases } = getItemSearchFields(item);\n    let total = 0;\n    for (const token of tokens) {\n      // try fields in priority order\n      const scores = [\n        computeFieldMatchScore(mnemonic, token),\n        computeBestAliasMatchScore(aliases, token),\n        computeFieldMatchScore(opcode, token) !== null\n          ? computeFieldMatchScore(opcode, token) + 2 // de-prioritize opcode a bit\n          : null,\n        computeFieldMatchScore(fift, token) !== null\n          ? computeFieldMatchScore(fift, token) + 5 // fift is weakest signal\n          : null,\n      ].filter((s) => s !== null);\n      if (scores.length === 0) return Infinity; // token didn't match any field\n      total += Math.min(...scores);\n    }\n    return total;\n  }\n\n  // Build anchor ids compatible with static MDX (slug of \"<opcode> <mnemonic>\"\")\n  function buildAnchorId(instruction) {\n    const opcodeText = String(instruction.opcode || \"\").trim().toLowerCase();\n    const titleText = `${instruction.mnemonic}`.trim().toLowerCase();\n    const raw = `${opcodeText} ${titleText}`.trim();\n    const slug = raw\n      .replace(/\\s+/g, \"-\")\n      .replace(/-+/g, \"-\")\n      .replace(/^-+|-+$/g, \"\");\n    return encodeURIComponent(slug);\n  }\n\n  function copyAnchorUrl(anchorId) {\n    try {\n      const { location, navigator } = window;\n      const base = location ? `${location.origin}${location.pathname}` : \"\";\n      const url = `${base}#${anchorId}`;\n      if (navigator && navigator.clipboard && navigator.clipboard.writeText) {\n        return navigator.clipboard.writeText(url);\n      }\n      const ta = document.createElement(\"textarea\");\n      ta.value = url;\n      ta.setAttribute(\"readonly\", \"\");\n      ta.style.position = \"absolute\";\n      ta.style.left = \"-9999px\";\n      document.body.appendChild(ta);\n      ta.select();\n      document.execCommand(\"copy\");\n      document.body.removeChild(ta);\n      return Promise.resolve();\n    } catch (err) {\n      return Promise.reject(err);\n    }\n  }\n\n  function copyPlainText(value) {\n    try {\n      const { navigator, document } = window;\n      if (navigator?.clipboard?.writeText) {\n        return navigator.clipboard.writeText(value);\n      }\n      const ta = document.createElement(\"textarea\");\n      ta.value = value;\n      ta.setAttribute(\"readonly\", \"\");\n      ta.style.position = \"absolute\";\n      ta.style.left = \"-9999px\";\n      document.body.appendChild(ta);\n      ta.select();\n      document.execCommand(\"copy\");\n      document.body.removeChild(ta);\n      return Promise.resolve();\n    } catch (err) {\n      return Promise.reject(err);\n    }\n  }\n\n  function formatAliasOperands(operands) {\n    return Object.entries(operands)\n      .map(([name, value]) => `${name}=${value}`)\n      .join(\", \");\n  }\n\n  function cleanAliasDescription(html) {\n    if (typeof html !== \"string\") return \"\";\n    let output = html.trim();\n    if (!output) return \"\";\n    output = output.replace(/^<p>/i, \"\").replace(/<\\/p>$/i, \"\");\n    output = output.replace(/\\.+$/g, \"\");\n    return output.trim();\n  }\n\n  function extractImplementationRefs(implementation) {\n    if (!Array.isArray(implementation)) return [];\n    return implementation\n      .map((item) => {\n        if (!item || typeof item !== \"object\") return null;\n        const file = typeof item.file === \"string\" ? item.file : \"\";\n        const functionName =\n          typeof item.function_name === \"string\" ? item.function_name : \"\";\n        const line = typeof item.line === \"number\" ? item.line : undefined;\n        const path = typeof item.path === \"string\" ? item.path : \"\";\n        if (!file && !functionName && !path) return null;\n        return { file, functionName, line, path };\n      })\n      .filter(Boolean);\n  }\n\n  function buildGitHubLineUrl(rawUrl, line) {\n    if (typeof rawUrl !== \"string\" || !rawUrl) return \"\";\n    let url = rawUrl;\n    const RAW_PREFIX = \"https://raw.githubusercontent.com/\";\n    if (rawUrl.startsWith(RAW_PREFIX)) {\n      const parts = rawUrl.slice(RAW_PREFIX.length).split(\"/\");\n      if (parts.length >= 4) {\n        const owner = parts[0];\n        const repo = parts[1];\n        const commit = parts[2];\n        const filePath = parts.slice(3).join(\"/\");\n        url = `https://github.com/${owner}/${repo}/blob/${commit}/${filePath}`;\n      } else {\n        url = rawUrl.replace(RAW_PREFIX, \"https://github.com/\");\n      }\n    }\n    if (typeof line === \"number\" && Number.isFinite(line) && line > 0) {\n      url = url.split(\"#\")[0] + `#L${line}`;\n    }\n    return url;\n  }\n\n  function renderControlFlowSummary(controlFlow) {\n    if (!controlFlow || typeof controlFlow !== \"object\") {\n      return (\n        <p className=\"tvm-missing-placeholder\">\n          Control flow details are not available.\n        </p>\n      );\n    }\n\n    const branches = Array.isArray(controlFlow.branches)\n      ? controlFlow.branches.filter(Boolean)\n      : [];\n    const nobranch = Boolean(controlFlow.nobranch);\n    const isContinuationObject = (value) =>\n      Boolean(value && typeof value === \"object\" && typeof value.type === \"string\");\n\n    const formatPrimitiveValue = (value) => {\n      if (value === null || value === undefined) return \"\";\n      if (Array.isArray(value)) {\n        return value\n          .map((item) => formatPrimitiveValue(item))\n          .filter(Boolean)\n          .join(\", \");\n      }\n      if (typeof value === \"object\") {\n        return \"\";\n      }\n      if (typeof value === \"boolean\") {\n        return value ? \"true\" : \"false\";\n      }\n      return String(value);\n    };\n\n    const describeContinuation = (node) => {\n      if (!isContinuationObject(node)) {\n        return {\n          typeLabel: \"unknown\",\n          valueLabel: \"?\",\n          detailLabel: \"\",\n          text: \"unknown ?\",\n        };\n      }\n\n      const type = String(node.type || \"\").toLowerCase();\n      let typeLabel = \"unknown\";\n      let valueLabel = \"\";\n\n      switch (type) {\n        case \"variable\":\n          typeLabel = \"var\";\n          valueLabel = typeof node.var_name === \"string\" ? node.var_name : \"?\";\n          break;\n        case \"register\":\n          typeLabel = \"register\";\n          if (typeof node.index === \"number\") {\n            valueLabel = `c${node.index}`;\n          } else if (typeof node.var_name === \"string\") {\n            valueLabel = `c{${node.var_name}}`;\n          } else {\n            valueLabel = \"c?\";\n          }\n          break;\n        case \"cc\":\n          typeLabel = \"cc\";\n          valueLabel = \"\";\n          break;\n        case \"special\":\n          typeLabel = \"special\";\n          valueLabel = typeof node.name === \"string\" && node.name ? node.name : \"?\";\n          break;\n        default:\n          typeLabel = node.type ? String(node.type) : \"unknown\";\n          valueLabel = \"\";\n          break;\n      }\n\n      const detailParts = [];\n      if (type === \"special\") {\n        const args = node.args && typeof node.args === \"object\" ? node.args : {};\n        Object.entries(args).forEach(([argKey, argValue]) => {\n          if (!isContinuationObject(argValue)) {\n            const formatted = formatPrimitiveValue(argValue);\n            if (formatted) {\n              detailParts.push(`${argKey}=${formatted}`);\n            }\n          }\n        });\n      }\n\n      const knownKeys = new Set([\"type\", \"var_name\", \"index\", \"name\", \"args\", \"save\"]);\n      Object.entries(node).forEach(([key, value]) => {\n        if (knownKeys.has(key)) return;\n        const formatted = formatPrimitiveValue(value);\n        if (formatted) {\n          detailParts.push(`${key}=${formatted}`);\n        }\n      });\n\n      const detailLabel = detailParts.length > 0 ? `(${detailParts.join(\", \")})` : \"\";\n      const text = [typeLabel, valueLabel, detailLabel]\n        .filter(Boolean)\n        .join(\" \")\n        .replace(/\\s+/g, \" \")\n        .trim();\n\n      return { typeLabel, valueLabel, detailLabel, text };\n    };\n\n    const gatherChildContinuations = (node) => {\n      if (!isContinuationObject(node)) return [];\n      const type = String(node.type || \"\").toLowerCase();\n      const children = [];\n\n      const saveEntries =\n        node.save && typeof node.save === \"object\"\n          ? Object.entries(node.save).filter(([, value]) => isContinuationObject(value))\n          : [];\n      saveEntries\n        .sort(([aKey], [bKey]) => aKey.localeCompare(bKey))\n        .forEach(([slot, value]) => {\n          children.push({\n            label: String(slot),\n            node: value,\n          });\n        });\n\n      if (type === \"special\") {\n        const args = node.args && typeof node.args === \"object\" ? node.args : {};\n        Object.entries(args).forEach(([argKey, argValue]) => {\n          if (isContinuationObject(argValue)) {\n            children.push({\n              label: argKey,\n              node: argValue,\n            });\n          }\n        });\n      }\n\n      return children.map((child) => {\n        const raw = child.label ? String(child.label) : \"\";\n        const cleaned = raw.replace(/^(arg|save)\\s+/i, \"\").trim();\n        return {\n          label: cleaned,\n          node: child.node,\n        };\n      });\n    };\n\n    const buildContinuationTree = (node, path = \"root\") => {\n      const summary = describeContinuation(node);\n      const children = gatherChildContinuations(node).map((child, idx) => ({\n        label: child.label,\n        tree: buildContinuationTree(child.node, `${path}.${idx}`),\n      }));\n      return { id: path, summary, children };\n    };\n\n    const splitEdgeLabel = (label) => {\n      if (!label) {\n        return { primary: \"\", secondary: \"\" };\n      }\n      const text = label.trim();\n      if (!text) {\n        return { primary: \"\", secondary: \"\" };\n      }\n      const tokens = text.split(/\\s+/);\n      if (tokens.length <= 1) {\n        return { primary: text, secondary: \"\" };\n      }\n      return {\n        primary: tokens[0],\n        secondary: tokens.slice(1).join(\" \"),\n      };\n    };\n\n    const computeSpan = (tree) => {\n      if (!tree.children || tree.children.length === 0) {\n        tree.span = 1;\n        return 1;\n      }\n      let total = 0;\n      tree.children.forEach((child) => {\n        total += computeSpan(child.tree);\n      });\n      tree.span = Math.max(total, 1);\n      return tree.span;\n    };\n\n    const H_SPACING = 200;\n    const V_SPACING = 110;\n    const NODE_HEIGHT = 42;\n    const NODE_MIN_WIDTH = 140;\n    const PADDING_X = 60;\n    const PADDING_Y = 60;\n\n    let canvasMeasureCtx = null;\n    const measureNodeWidth = (summary) => {\n      if (typeof document !== \"undefined\") {\n        if (!canvasMeasureCtx) {\n          const canvas = document.createElement(\"canvas\");\n          canvasMeasureCtx = canvas.getContext(\"2d\");\n        }\n        if (canvasMeasureCtx) {\n          canvasMeasureCtx.font = \"600 13px 'JetBrains Mono', 'Menlo', 'Monaco', monospace\";\n          const typeText = (summary.typeLabel || \"\").toUpperCase();\n          const parts = [typeText];\n          if (summary.valueLabel) parts.push(summary.valueLabel);\n          if (summary.detailLabel) parts.push(summary.detailLabel);\n          const text = parts.join(\" \").trim();\n          const metrics = canvasMeasureCtx.measureText(text || \"node\");\n          return Math.max(metrics.width + 48, NODE_MIN_WIDTH);\n        }\n      }\n      const fallbackLength =\n        (summary.typeLabel || \"\").length +\n        (summary.valueLabel || \"\").length +\n        (summary.detailLabel || \"\").length;\n      return Math.max(fallbackLength * 7 + 48, NODE_MIN_WIDTH);\n    };\n\n    const assignPositions = (\n      tree,\n      nodes,\n      nodeMap,\n      edges,\n      depth = 0,\n      offsetSpan = 0\n    ) => {\n      const span = Math.max(tree.span || 1, 1);\n      const spanWidth = span * H_SPACING;\n      const x = PADDING_X + offsetSpan + spanWidth / 2;\n      const y = PADDING_Y + depth * V_SPACING;\n      const width = measureNodeWidth(tree.summary);\n      const nodeEntry = {\n        id: tree.id,\n        summary: tree.summary,\n        x,\n        y,\n        width,\n        height: NODE_HEIGHT,\n      };\n      nodes.push(nodeEntry);\n      nodeMap.set(tree.id, nodeEntry);\n\n      let childOffset = offsetSpan;\n      tree.children.forEach((child) => {\n        assignPositions(child.tree, nodes, nodeMap, edges, depth + 1, childOffset);\n        edges.push({\n          from: tree.id,\n          to: child.tree.id,\n          label: child.label,\n        });\n        childOffset += Math.max(child.tree.span || 1, 1) * H_SPACING;\n      });\n    };\n\n    return (\n      <div>\n        {(branches.length > 0 || !nobranch) ? (<div><b>Falls through: </b>{nobranch ? \"Yes\" : \"No\"}</div>) : null}\n        {branches.length > 0 ? (\n          <div className=\"tvm-control-flow-branches\">\n            {branches.map((branch, index) => {\n              const rootSummary = describeContinuation(branch);\n              const branchType = (rootSummary.typeLabel || \"\").toUpperCase();\n              const branchTitleText = `Branch -> ${branchType}${\n                rootSummary.valueLabel ? ` ${rootSummary.valueLabel}` : \"\"\n              }`;\n              const tree = buildContinuationTree(branch, `branch-${index}`);\n              computeSpan(tree);\n              const nodes = [];\n              const nodeMap = new Map();\n              const edges = [];\n              assignPositions(tree, nodes, nodeMap, edges);\n\n              let minX = Infinity;\n              let maxX = -Infinity;\n              let minY = Infinity;\n              let maxY = -Infinity;\n              nodes.forEach((node) => {\n                minX = Math.min(minX, node.x - node.width / 2);\n                maxX = Math.max(maxX, node.x + node.width / 2);\n                minY = Math.min(minY, node.y - node.height / 2);\n                maxY = Math.max(maxY, node.y + node.height / 2);\n              });\n\n              const shiftX = Number.isFinite(minX) ? PADDING_X - minX : 0;\n              const shiftY = Number.isFinite(minY) ? PADDING_Y - minY : 0;\n              if (shiftX || shiftY) {\n                nodes.forEach((node) => {\n                  node.x += shiftX;\n                  node.y += shiftY;\n                });\n              }\n\n              const canvasWidth = Math.max(maxX - minX + PADDING_X * 2, 260);\n              const canvasHeight = Math.max(maxY - minY + PADDING_Y * 2, NODE_HEIGHT + PADDING_Y * 2);\n\n              const edgeLayouts = edges\n                .map((edge, edgeIdx) => {\n                  const from = nodeMap.get(edge.from);\n                  const to = nodeMap.get(edge.to);\n                  if (!from || !to) return null;\n                  const fromX = from.x;\n                  const fromY = from.y + from.height / 2;\n                  const toX = to.x;\n                  const toY = to.y - to.height / 2;\n                  const midY = fromY + (toY - fromY) / 2;\n                  const path = `M ${fromX} ${fromY} C ${fromX} ${midY}, ${toX} ${midY}, ${toX} ${toY}`;\n                  const labelX = (fromX + toX) / 2;\n                  const labelY = midY;\n                  const segments = splitEdgeLabel(edge.label);\n                  const hasSecondary = Boolean(segments.secondary);\n                  return {\n                    id: `${edge.from}->${edge.to}-${edgeIdx}`,\n                    path,\n                    labelX,\n                    labelY,\n                    segments,\n                    hasSecondary,\n                  };\n                })\n                .filter(Boolean);\n\n              return (\n                <div key={`branch-${index}`} className=\"tvm-control-flow-branch\">\n                  <div className=\"tvm-control-flow-branch-header\">\n                    <span className=\"tvm-control-flow-branch-title\">\n                      {highlightMatches(branchTitleText, searchTokens)}\n                    </span>\n                  </div>\n                  <div className=\"tvm-flow-graph-wrapper\">\n                    <div\n                      className=\"tvm-flow-canvas\"\n                      style={{\n                        width: `${canvasWidth}px`,\n                        height: `${canvasHeight}px`,\n                      }}\n                    >\n                      <svg\n                        className=\"tvm-flow-canvas-svg\"\n                        width={canvasWidth}\n                        height={canvasHeight}\n                        viewBox={`0 0 ${canvasWidth} ${canvasHeight}`}\n                        preserveAspectRatio=\"xMinYMin meet\"\n                      >\n                        <defs>\n                          <marker\n                            id=\"tvm-flow-arrowhead\"\n                            markerWidth=\"8\"\n                            markerHeight=\"8\"\n                            refX=\"6\"\n                            refY=\"4\"\n                            orient=\"auto\"\n                            markerUnits=\"strokeWidth\"\n                          >\n                            <path d=\"M1 1 L7 4 L1 7 Z\" fill=\"currentColor\" />\n                          </marker>\n                        </defs>\n                        {edgeLayouts.map((edge) => (\n                          <path\n                            key={`edge-path-${edge.id}`}\n                            d={edge.path}\n                            className=\"tvm-flow-graph-line\"\n                            markerEnd=\"url(#tvm-flow-arrowhead)\"\n                          />\n                        ))}\n                      </svg>\n                      {edgeLayouts.map((edge) => (\n                        edge.segments.primary ? (\n                      <div\n                        key={`edge-label-${edge.id}`}\n                        className={`tvm-flow-edge-label${\n                          edge.hasSecondary ? ' has-secondary' : ''\n                        }`}\n                        style={{\n                          left: `${edge.labelX}px`,\n                          top: `${edge.labelY}px`,\n                        }}\n                      >\n                        <span className=\"tvm-flow-edge-label-primary\">\n                          {highlightMatches(edge.segments.primary.toUpperCase(), searchTokens)}\n                        </span>\n                        {edge.segments.secondary && (\n                          <span className=\"tvm-flow-edge-label-secondary\">\n                            {highlightMatches(edge.segments.secondary.toUpperCase(), searchTokens)}\n                          </span>\n                        )}\n                      </div>\n                        ) : null\n                      ))}\n                      {nodes.map((node) => (\n                        <div\n                          key={node.id}\n                          className=\"tvm-flow-node\"\n                          style={{\n                            left: `${node.x}px`,\n                            top: `${node.y}px`,\n                          }}\n                        >\n                          <span\n                            className=\"tvm-control-flow-node-pill\"\n                            style={{ minWidth: `${node.width}px` }}\n                          >\n                            <span className=\"tvm-control-flow-node-type\">\n                              {highlightMatches(\n                                (node.summary.typeLabel || \"\").toUpperCase(),\n                                searchTokens\n                              )}\n                            </span>\n                            {node.summary.valueLabel && (\n                              <span className=\"tvm-control-flow-node-value\">\n                                {highlightMatches(node.summary.valueLabel, searchTokens)}\n                              </span>\n                            )}\n                            {node.summary.detailLabel && (\n                              <span className=\"tvm-control-flow-node-extra\">\n                                {highlightMatches(node.summary.detailLabel, searchTokens)}\n                              </span>\n                            )}\n                          </span>\n                        </div>\n                      ))}\n                    </div>\n                  </div>\n                </div>\n              );\n            })}\n          </div>\n        ) : (\n          <p className=\"tvm-detail-muted\">\n            {nobranch\n              ? \"Instruction does not modify the current continuation.\"\n              : \"Control flow branches are not documented in the specification.\"}\n          </p>\n        )}\n      </div>\n    );\n  }\n\n  function renderStackEntry(entry, key, mode) {\n    if (!entry) return null;\n\n    if (entry.type === \"conditional\") {\n      if (mode === \"compact\" || mode === \"detail-inline\") {\n        return (\n          <span\n            key={key}\n            className=\"tvm-stack-pill tvm-stack-pill--conditional\"\n          >\n            Conditional: {highlightMatches(String(entry.name || \"?\"), searchTokens)}\n          </span>\n        );\n      }\n\n      return (\n        <div key={key} className=\"tvm-stack-conditional\">\n          <span className=\"tvm-stack-conditional-name\">\n            Conditional: {highlightMatches(String(entry.name || \"?\"), searchTokens)}\n          </span>\n          {Array.isArray(entry.match) && entry.match.length > 0 ? (\n            entry.match.map((matchArm, idx) => (\n              <div\n                key={`${key}-match-${idx}`}\n                className=\"tvm-stack-conditional-branch\"\n              >\n                <span className=\"tvm-stack-conditional-label\">\n                  = {highlightMatches(String(matchArm.value ?? \"\"), searchTokens)}\n                </span>\n                <div className=\"tvm-stack-conditional-values\">\n                  {Array.isArray(matchArm.stack) &&\n                  matchArm.stack.length > 0 ? (\n                    matchArm.stack\n                      .slice()\n                      .reverse()\n                      .map((nested, nestedIdx) =>\n                        renderStackEntry(\n                          nested,\n                          `${key}-match-${idx}-item-${nestedIdx}`,\n                          \"detail-inline\"\n                        )\n                      )\n                  ) : (\n                    <span className=\"tvm-stack-pill tvm-stack-pill--empty\">\n                      Empty\n                    </span>\n                  )}\n                </div>\n              </div>\n            ))\n          ) : (\n            <span className=\"tvm-stack-pill tvm-stack-pill--empty\">\n              Empty branches\n            </span>\n          )}\n          {Array.isArray(entry.else) && (\n            <div className=\"tvm-stack-conditional-branch\">\n              <span className=\"tvm-stack-conditional-label\">else</span>\n              <div className=\"tvm-stack-conditional-values\">\n                {entry.else.length > 0 ? (\n                  entry.else\n                    .slice()\n                    .reverse()\n                    .map((nested, nestedIdx) =>\n                      renderStackEntry(\n                        nested,\n                        `${key}-else-${nestedIdx}`,\n                        \"detail-inline\"\n                      )\n                    )\n                ) : (\n                  <span className=\"tvm-stack-pill tvm-stack-pill--empty\">\n                    Empty\n                  </span>\n                )}\n              </div>\n            </div>\n          )}\n        </div>\n      );\n    }\n\n    if (entry.type === \"array\") {\n      const label = `${entry.name || \"items\"}[${entry.length_var ?? \"\"}]`;\n      return (\n        <span key={key} className=\"tvm-stack-pill tvm-stack-pill--array\">\n          {highlightMatches(label, searchTokens)}\n        </span>\n      );\n    }\n\n    if (entry.type === \"const\") {\n      const value =\n        entry.value === null\n          ? \"null\"\n          : entry.value === undefined\n          ? \"?\"\n          : entry.value;\n      return (\n        <span key={key} className=\"tvm-stack-pill tvm-stack-pill--const\">\n          {highlightMatches(String(value), searchTokens)}: {highlightMatches(\n            String(entry.value_type || \"Const\"),\n            searchTokens\n          )}\n        </span>\n      );\n    }\n\n    const valueTypes =\n      Array.isArray(entry.value_types) && entry.value_types.length > 0\n        ? entry.value_types.join(\"/\")\n        : entry.value_type || \"Any\";\n    const label = entry.name ? `${entry.name}: ${valueTypes}` : valueTypes;\n\n    return (\n      <span key={key} className=\"tvm-stack-pill tvm-stack-pill--simple\">\n        {highlightMatches(label, searchTokens)}\n      </span>\n    );\n  }\n\n  function renderStackColumn(title, items, mode = \"detail\") {\n    const safeItems = Array.isArray(items) ? items : [];\n    const reversed = safeItems.slice().reverse();\n    const limit = mode === \"compact\" ? 4 : reversed.length;\n    const shown = reversed.slice(0, limit);\n    const truncated = mode === \"compact\" && reversed.length > shown.length;\n\n    return (\n      <div\n        className={`tvm-stack-column ${\n          mode === \"compact\" ? \"tvm-stack-column--compact\" : \"\"\n        }`}\n      >\n        <div className=\"tvm-stack-column-title\">{title}</div>\n        <div className=\"tvm-stack-top\">TOP</div>\n        <div className=\"tvm-stack-list\">\n          {shown.length === 0 && <span className=\"tvm-stack-empty\">Empty</span>}\n          {shown.map((entry, idx) =>\n            renderStackEntry(entry, `${title}-${idx}`, mode)\n          )}\n          {truncated && (\n            <span className=\"tvm-stack-pill tvm-stack-pill--more\">\n              +{reversed.length - shown.length} more\n            </span>\n          )}\n        </div>\n      </div>\n    );\n  }\n\n  function renderStackColumns(instruction, mode = \"detail\") {\n    const inputs = instruction?.valueFlow?.inputs ?? [];\n    const outputs = instruction?.valueFlow?.outputs ?? [];\n\n    return (\n      <div\n        className={`tvm-stack-columns ${\n          mode === \"compact\" ? \"tvm-stack-columns--compact\" : \"\"\n        }`}\n      >\n        {renderStackColumn(\"Inputs\", inputs, mode)}\n        {renderStackColumn(\"Outputs\", outputs, mode)}\n      </div>\n    );\n  }\n\n  function renderInstructionDetail(instruction, options = {}) {\n    const { isAnchorTarget = false, onOpenRawJson = () => {} } = options;\n    const hasAliases =\n      Array.isArray(instruction.aliases) && instruction.aliases.length > 0;\n    const readsRegisters = Array.isArray(instruction.registers?.inputs)\n      ? instruction.registers.inputs\n      : [];\n    const writesRegisters = Array.isArray(instruction.registers?.outputs)\n      ? instruction.registers.outputs\n      : [];\n    const hasRegisterInfo = readsRegisters.length > 0 || writesRegisters.length > 0;\n    const hasStackData =\n      !instruction.missing.inputs || !instruction.missing.outputs;\n    const hasFiftExamples =\n      Array.isArray(instruction.fiftExamples) &&\n      instruction.fiftExamples.length > 0;\n    const descriptionHtml = highlightHtmlContent(\n      instruction.descriptionHtml || instruction.description || \"\",\n      searchTokens\n    );\n    const implementationRefs = Array.isArray(instruction.implementationRefs)\n      ? instruction.implementationRefs.filter(Boolean)\n      : [];\n    const hasImplementation = implementationRefs.length > 0;\n\n    const renderRegisterList = (list, keyPrefix) => {\n      const tokens = Array.isArray(list)\n        ? list\n            .map((register, idx) => {\n              if (!register) return null;\n              if (register.type === \"special\" && register.name) {\n                return (\n                  <span\n                    key={`${keyPrefix}-special-${idx}`}\n                    className=\"tvm-register-token tvm-register-token--special\"\n                  >\n                    {register.name}\n                  </span>\n                );\n              }\n              const sub =\n                register.type === \"variable\"\n                  ? register.var_name || \"i\"\n                  : typeof register.index === \"number\"\n                  ? register.index\n                  : register.var_name || \"?\";\n              return (\n                <span key={`${keyPrefix}-const-${idx}`} className=\"tvm-register-token\">\n                  c<sub>{sub}</sub>\n                </span>\n              );\n            })\n            .filter(Boolean)\n        : [];\n\n      return tokens.flatMap((token, idx) =>\n        idx === 0\n          ? [token]\n          : [\n              <span key={`${keyPrefix}-sep-${idx}`} className=\"tvm-register-sep\">\n                ,{\" \"}\n              </span>,\n              token,\n            ]\n      );\n    };\n\n    const badgeNodes = [\n      <span key=\"gas\" className=\"tvm-detail-badge\">\n        <span className=\"tvm-detail-badge-label\">Gas</span>{\" \"}\n        <span className=\"tvm-detail-badge-value\">\n          {highlightMatches(String(instruction.gasDisplay || \"N/A\"), searchTokens)}\n        </span>\n      </span>,\n      <span key=\"version\" className=\"tvm-detail-badge\">\n        <span className=\"tvm-detail-badge-label\">TVM</span>{\" \"}\n        <span className=\"tvm-detail-badge-value\">\n          {highlightMatches(\n            instruction.since > 0 ? `v${instruction.since}` : \"v0\",\n            searchTokens\n          )}\n        </span>\n      </span>,\n    ];\n\n    if (hasRegisterInfo) {\n      if (readsRegisters.length > 0) {\n        badgeNodes.push(\n          <span key=\"registers-read\" className=\"tvm-detail-badge tvm-detail-badge--register\">\n            <span className=\"tvm-detail-badge-label\">Read registers</span>{\" \"}\n            <span className=\"tvm-detail-badge-value\">\n              {renderRegisterList(readsRegisters, \"read\")}\n            </span>\n          </span>\n        );\n      }\n      if (writesRegisters.length > 0) {\n        badgeNodes.push(\n          <span key=\"registers-write\" className=\"tvm-detail-badge tvm-detail-badge--register\">\n            <span className=\"tvm-detail-badge-label\">Write registers</span>{\" \"}\n            <span className=\"tvm-detail-badge-value\">\n              {renderRegisterList(writesRegisters, \"write\")}\n            </span>\n          </span>\n        );\n      }\n    }\n\n    const panelClassName = `tvm-detail-panel${\n      isAnchorTarget ? \" is-anchor-target\" : \"\"\n    }`;\n\n    return (\n      <div className={panelClassName}>\n        <div className=\"tvm-detail-header\">\n          <div className=\"tvm-detail-heading\">\n            <div className=\"tvm-detail-header-main\">\n              <h4 className=\"tvm-detail-title\">{instruction.mnemonic}</h4>\n            </div>\n          </div>\n          <div className=\"tvm-detail-actions\">\n            <button\n              type=\"button\"\n              className=\"tvm-button tvm-button--ghost\"\n              onClick={() => onOpenRawJson(instruction)}\n            >\n              Raw JSON\n            </button>\n          </div>\n        </div>\n\n        <div className=\"tvm-detail-columns\">\n          <div className=\"tvm-detail-main\">\n            {descriptionHtml ? (\n              <div\n                className=\"tvm-description\"\n                dangerouslySetInnerHTML={{ __html: descriptionHtml }}\n              />\n            ) : (\n              <p className=\"tvm-missing-placeholder\">Description not available.</p>\n            )}\n\n            <div className=\"tvm-detail-badges\">{badgeNodes}</div>\n\n            <div className=\"tvm-detail-block\">\n              <span className=\"tvm-detail-subtitle\">Fift command</span>\n              {instruction.fift ? (\n                <code className=\"tvm-detail-code tvm-detail-code--inline\">\n                  {highlightMatches(String(instruction.fift), searchTokens)}\n                </code>\n              ) : (\n                <span className=\"tvm-detail-muted\">Not documented.</span>\n              )}\n            </div>\n\n            <div className=\"tvm-detail-block\">\n              <span className=\"tvm-detail-subtitle\">Control flow</span>\n              {renderControlFlowSummary(instruction.controlFlow)}\n            </div>\n\n            {hasImplementation && (\n              <div className=\"tvm-detail-block\">\n                <span className=\"tvm-detail-subtitle\">Implementation</span>\n                <div className=\"tvm-impl-badges\">\n                  {implementationRefs.map((ref, idx) => {\n                    const filename = ref.file || \"source\";\n                    const linePart =\n                      typeof ref.line === \"number\" && ref.line > 0\n                        ? `:${ref.line}`\n                        : \"\";\n                    const href = buildGitHubLineUrl(ref.path, ref.line);\n                    return (\n                      <a\n                        key={`${instruction.mnemonic}-impl-${idx}`}\n                        className=\"tvm-detail-badge tvm-detail-badge--link\"\n                        href={href}\n                        target=\"_blank\"\n                        rel=\"noreferrer\"\n                      >\n                        {filename}\n                        {linePart}\n                      </a>\n                    );\n                  })}\n                </div>\n              </div>\n            )}\n\n            {hasFiftExamples && (\n              <section className=\"tvm-detail-section tvm-detail-section--wide\">\n                <h4 className=\"tvm-detail-title\">Fift examples</h4>\n                <div className=\"tvm-example-list\">\n                  {instruction.fiftExamples.map((example, idx) => {\n                    const description =\n                      typeof example.description === \"string\" ? example.description : \"\";\n                    const fiftCode = typeof example.fift === \"string\" ? example.fift : \"\";\n                    return (\n                      <div\n                        key={`${instruction.mnemonic}-example-${idx}`}\n                        className=\"tvm-example-item\"\n                      >\n                        {description && (\n                          <p\n                            className=\"tvm-example-description\"\n                            dangerouslySetInnerHTML={{\n                              __html: formatInlineMarkdown(description),\n                            }}\n                          />\n                        )}\n                        {fiftCode && (\n                          <code className=\"tvm-detail-code tvm-example-code\">{fiftCode}</code>\n                        )}\n                      </div>\n                    );\n                  })}\n                </div>\n              </section>\n            )}\n\n            {hasAliases && (\n              <section className=\"tvm-detail-section tvm-detail-section--wide\">\n                <h4 className=\"tvm-detail-title\">Aliases</h4>\n                <div className=\"tvm-alias-list\">\n                  {instruction.aliases.map((alias) => {\n                    const aliasDescriptionHtml = cleanAliasDescription(\n                      alias.description || \"\"\n                    );\n                    const hasAliasMeta =\n                      Boolean(alias.doc_fift) ||\n                      (alias.operands && Object.keys(alias.operands).length > 0);\n\n                    return (\n                      <div key={alias.mnemonic} className=\"tvm-alias-item\">\n                        <div className=\"tvm-alias-headline\">\n                          <code>{alias.mnemonic}</code>\n                          <span className=\"tvm-alias-meta\">\n                            alias of <code>{alias.alias_of}</code>\n                          </span>\n                        </div>\n                        {aliasDescriptionHtml && (\n                          <div\n                            className=\"tvm-alias-description\"\n                            dangerouslySetInnerHTML={{\n                              __html: aliasDescriptionHtml,\n                            }}\n                          />\n                        )}\n                        {hasAliasMeta && (\n                          <div className=\"tvm-alias-meta-row\">\n                            {alias.doc_fift && (\n                              <span className=\"tvm-alias-pill\">\n                                Fift <code>{alias.doc_fift}</code>\n                              </span>\n                            )}\n                            {alias.operands && Object.keys(alias.operands).length > 0 && (\n                              <span className=\"tvm-alias-pill\">\n                                Operands {formatAliasOperands(alias.operands)}\n                              </span>\n                            )}\n                          </div>\n                        )}\n                      </div>\n                    );\n                  })}\n                </div>\n              </section>\n            )}\n          </div>\n\n          <aside className=\"tvm-detail-side\">\n            <div className=\"tvm-side-block\">\n              <span className=\"tvm-side-title\">Opcode</span>\n              {instruction.tlb ? (\n                <code className=\"tvm-detail-code\">\n                  {highlightMatches(String(instruction.tlb), searchTokens)}\n                </code>\n              ) : (\n                <p className=\"tvm-missing-placeholder\">TL-B layout not available.</p>\n              )}\n            </div>\n\n            <div className=\"tvm-side-block\">\n              <span className=\"tvm-side-title\">Category</span>\n              <div className=\"tvm-side-category-value\">\n                {highlightMatches(instruction.rawCategoryLabel, searchTokens)}\n              </div>\n            </div>\n\n            <div className=\"tvm-side-block\">\n              <span className=\"tvm-side-title\">Operands</span>\n              {Array.isArray(instruction.operands) && instruction.operands.length > 0 ? (\n                <div className=\"tvm-operands-list\">\n                  {instruction.operands.map((operand, idx) => {\n                    if (!operand || typeof operand !== \"object\") return null;\n                    const summary = highlightMatches(\n                      formatOperandSummary(operand),\n                      searchTokens\n                    );\n                    const hasRange =\n                      operand.min_value !== undefined || operand.max_value !== undefined;\n                    return (\n                      <div key={`operand-${idx}`} className=\"tvm-operands-item\">\n                        <div className=\"tvm-operands-line\">{summary}</div>\n                        {hasRange && (\n                          <div className=\"tvm-operands-detail\">\n                            Range {highlightMatches(String(operand.min_value ?? \"?\"), searchTokens)} – {highlightMatches(\n                              String(operand.max_value ?? \"?\"),\n                              searchTokens\n                            )}\n                          </div>\n                        )}\n                      </div>\n                    );\n                  })}\n                </div>\n              ) : (\n                <p className=\"tvm-detail-muted\">No operands.</p>\n              )}\n            </div>\n\n            <div className=\"tvm-side-block\">\n              <span className=\"tvm-side-title\">Stack</span>\n              {hasStackData ? (\n                renderStackColumns(instruction, \"detail\")\n              ) : (\n                <p className=\"tvm-missing-placeholder\">Stack effects not available.</p>\n              )}\n            </div>\n          </aside>\n        </div>\n\n        \n      </div>\n    );\n  }\n\n  const [spec, setSpec] = useState(null);\n  const [error, setError] = useState(null);\n  const [loading, setLoading] = useState(true);\n  const [search, setSearch] = useState(\"\");\n  const [category, setCategory] = useState(\"All\");\n  const [subcategory, setSubcategory] = useState(\"All\");\n  const [sortMode, setSortMode] = useState(\"opcode\");\n  const [expanded, setExpanded] = useState({});\n  const [copied, setCopied] = useState({});\n  const [activeAnchorId, setActiveAnchorId] = useState(null);\n  const [rawModalInstruction, setRawModalInstruction] = useState(null);\n  const [rawModalCopied, setRawModalCopied] = useState(false);\n  const searchInputRef = useRef(null);\n  const rawModalCopyTimeoutRef = useRef(null);\n  const tableStyles = useMemo(\n    () => `\n.tvm-instruction-app {\n  --tvm-border: var(--mint-border-color, rgb(var(--gray-400) / 0.24));\n  --tvm-border-strong: rgb(var(--gray-400) / 0.32);\n  --tvm-surface: var(--mint-surface-elevated, rgb(var(--background-light)));\n  --tvm-surface-secondary: rgb(var(--gray-50) / 0.65);\n  --tvm-text-primary: var(--mint-text-primary, rgb(var(--gray-800)));\n  --tvm-text-secondary: var(--mint-text-secondary, rgb(var(--gray-600) / 0.85));\n  --tvm-text-muted: var(--mint-text-tertiary, rgb(var(--gray-400) / 0.68));\n  --tvm-accent: rgb(var(--primary));\n  --tvm-accent-soft: rgb(var(--primary) / 0.16);\n  --tvm-accent-strong: rgb(var(--primary-light));\n  --tvm-accent-subtle: rgb(var(--primary-dark));\n  --tvm-callout-bg: var(--callout-bg-color, rgb(var(--primary) / 0.12));\n  --tvm-callout-border: var(--callout-border-color, rgb(var(--primary) / 0.2));\n  --tvm-callout-text: var(--callout-text-color, rgb(var(--primary)));\n  --tvm-stack-simple-bg: var(--tvm-accent-soft);\n  --tvm-stack-simple-text: var(--tvm-accent-subtle);\n  --tvm-stack-const-bg: rgb(var(--primary) / 0.2);\n  --tvm-stack-const-text: var(--tvm-accent-subtle);\n  --tvm-stack-array-bg: rgb(var(--primary) / 0.2);\n  --tvm-stack-array-text: var(--tvm-text-primary);\n  --tvm-stack-conditional-bg: rgb(var(--primary-dark) / 0.22);\n  --tvm-stack-conditional-text: var(--tvm-accent-subtle);\n  --tvm-stack-conditional-border: rgb(var(--primary-dark) / 0.32);\n  --tvm-stack-label: var(--mint-text-tertiary, rgb(var(--gray-600) / 0.65));\n  --tvm-pill-muted-bg: rgb(var(--gray-400) / 0.12);\n  --tvm-row-padding-y: 0.85rem;\n  --tvm-row-padding-x: 1rem;\n  --tvm-chip-padding-y: 0.2rem;\n  --tvm-chip-padding-x: 0.6rem;\n  --tvm-control-height: 2.75rem;\n  color: var(--tvm-text-primary);\n  background: var(--tvm-surface);\n  border: 1px solid var(--tvm-border);\n  border-radius: 14px;\n  padding: 1.5rem;\n  box-shadow: 0 24px 60px -40px rgb(var(--gray-900) / 0.9);\n}\n\n:where(.dark) .tvm-instruction-app {\n  --tvm-border: rgb(var(--gray-800) / 0.65);\n  --tvm-border-strong: rgb(var(--gray-600) / 0.85);\n  --tvm-surface: rgb(var(--gray-950));\n  --tvm-surface-secondary: rgb(var(--gray-900) / 0.85);\n  --tvm-text-primary: rgb(var(--gray-100));\n  --tvm-text-secondary: rgb(var(--gray-300));\n  --tvm-text-muted: rgb(var(--gray-400) / 0.9);\n  --tvm-accent: rgb(var(--primary-light));\n  --tvm-accent-soft: rgb(var(--primary) / 0.22);\n  --tvm-accent-strong: rgb(var(--primary));\n  --tvm-accent-subtle: rgb(var(--primary-light));\n  --tvm-callout-bg: rgb(var(--primary) / 0.24);\n  --tvm-callout-border: rgb(var(--primary-light) / 0.35);\n  --tvm-callout-text: rgb(var(--primary-light));\n  --tvm-stack-simple-bg: rgb(var(--primary) / 0.25);\n  --tvm-stack-simple-text: rgb(var(--primary-light));\n  --tvm-stack-const-bg: rgb(var(--primary-dark) / 0.4);\n  --tvm-stack-const-text: rgb(var(--primary-light));\n  --tvm-stack-array-bg: rgb(var(--primary) / 0.25);\n  --tvm-stack-array-text: rgb(var(--gray-50));\n  --tvm-stack-conditional-bg: rgb(var(--primary-dark) / 0.38);\n  --tvm-stack-conditional-text: rgb(var(--primary-light));\n  --tvm-stack-conditional-border: rgb(var(--primary) / 0.5);\n  --tvm-stack-label: rgb(var(--gray-400) / 0.85);\n  --tvm-pill-muted-bg: rgb(var(--gray-800) / 0.85);\n  box-shadow: 0 24px 80px -60px rgb(0 0 0 / 0.65);\n  color-scheme: dark;\n}\n\n.tvm-instruction-toolbar {\n  display: flex;\n  flex-direction: column;\n  gap: 1rem;\n  margin-bottom: 1.25rem;\n}\n\n.tvm-toolbar-search {\n  display: flex;\n}\n\n.tvm-toolbar-search .tvm-field--search {\n  flex: 1 1 auto;\n}\n\n.tvm-search-row {\n  display: flex;\n  align-items: stretch;\n  gap: 0.75rem;\n}\n\n.tvm-search-row .tvm-search-input {\n  flex: 1 1 auto;\n}\n\n.tvm-search-row .tvm-toolbar-utilities {\n  position: static;\n  width: auto;\n  align-self: stretch;\n  align-items: stretch;\n}\n\n.tvm-search-row .tvm-toolbar-utilities .tvm-button {\n  height: 100%;\n}\n\n.tvm-toolbar-utilities {\n  display: flex;\n  gap: 0.5rem;\n  align-items: center;\n  justify-content: flex-end;\n  justify-self: end;\n  align-self: end;\n  width: max-content;\n}\n\n.tvm-toolbar-filters {\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(220px, max-content));\n  gap: 0.75rem;\n  align-items: end;\n  justify-content: flex-start;\n}\n\n.tvm-toolbar-filters .tvm-field {\n  min-width: 0;\n  width: min(280px, 100%);\n}\n\n.tvm-field--sort {\n  width: min(240px, 100%);\n}\n\n.tvm-field--category {\n  width: min(280px, 100%);\n}\n\n.tvm-field--subcategory {\n  width: min(300px, 100%);\n}\n\n\n\n.tvm-field {\n  display: flex;\n  flex-direction: column;\n  gap: 0.35rem;\n  min-width: 190px;\n  flex: 1;\n}\n\n.tvm-field label {\n  font-size: 0.72rem;\n  font-weight: 600;\n  color: var(--tvm-text-secondary);\n  text-transform: uppercase;\n  letter-spacing: 0.08em;\n}\n\n.tvm-field input,\n.tvm-field select {\n  width: 100%;\n  border-radius: 8px;\n  border: 1px solid var(--tvm-border);\n  padding: 0.55rem 0.75rem;\n  background: var(--tvm-surface-secondary);\n  color: var(--tvm-text-primary);\n  font-size: 0.95rem;\n  min-height: var(--tvm-control-height);\n}\n\n.tvm-field--search {\n  min-width: min(260px, 100%);\n}\n\n.tvm-search-input {\n  position: relative;\n  display: flex;\n  align-items: center;\n}\n\n.tvm-field--search input {\n  padding-left: 2.2rem;\n}\n\n.tvm-search-icon {\n  position: absolute;\n  left: 0.75rem;\n  width: 1rem;\n  height: 1rem;\n  color: var(--tvm-text-secondary);\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n}\n\n.tvm-search-icon svg {\n  width: 100%;\n  height: 100%;\n}\n\n.tvm-clear-search {\n  position: absolute;\n  right: 0.5rem;\n  border: none;\n  background: none;\n  color: var(--tvm-text-secondary);\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  padding: 0.2rem;\n  cursor: pointer;\n  transition: color 0.2s ease-in-out;\n}\n\n.tvm-clear-search svg {\n  width: 14px;\n  height: 14px;\n}\n\n.tvm-clear-search:hover {\n  color: var(--tvm-accent-strong);\n}\n\n.tvm-button {\n  display: inline-flex;\n  align-items: center;\n  gap: 0.35rem;\n  border-radius: 8px;\n  border: 1px solid var(--tvm-border);\n  background: var(--tvm-surface-secondary);\n  color: var(--tvm-text-primary);\n  font-size: 0.82rem;\n  padding: 0 0.95rem;\n  min-height: var(--tvm-control-height);\n  font-weight: 500;\n  cursor: pointer;\n  transition: background 0.2s ease-in-out, border-color 0.2s ease-in-out, color 0.2s ease-in-out;\n}\n\n.tvm-button svg {\n  width: 16px;\n  height: 16px;\n}\n\n.tvm-button:disabled {\n  opacity: 0.55;\n  cursor: not-allowed;\n}\n\n.tvm-button:not(:disabled):hover {\n  border-color: var(--tvm-border-strong);\n  background: rgb(var(--gray-200) / 0.12);\n}\n\n:where(.dark) .tvm-instruction-app .tvm-button:not(:disabled):hover {\n  background: rgb(var(--gray-800) / 0.55);\n  border-color: var(--tvm-border-strong);\n}\n\n.tvm-button--ghost {\n  background: transparent;\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-button--ghost:not(:disabled):hover {\n  color: var(--tvm-text-primary);\n  background: rgb(var(--gray-200) / 0.1);\n}\n\n:where(.dark) .tvm-instruction-app .tvm-button--ghost:not(:disabled):hover {\n  background: rgb(var(--gray-800) / 0.4);\n  color: var(--tvm-text-primary);\n}\n\n.tvm-instruction-meta {\n  margin-bottom: 1rem;\n  font-size: 0.85rem;\n  color: var(--tvm-text-secondary);\n  display: flex;\n  flex-direction: column;\n  gap: 0.75rem;\n}\n\n.tvm-meta-items {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 0.75rem;\n  align-items: center;\n}\n\n.tvm-meta-item {\n  display: inline-flex;\n  align-items: center;\n  gap: 0.35rem;\n}\n\n.tvm-meta-link {\n  display: inline-flex;\n  align-items: center;\n  color: var(--tvm-accent-subtle);\n  font-weight: 500;\n  text-decoration: none;\n  gap: 0.3rem;\n}\n\n.tvm-meta-link:hover {\n  text-decoration: underline;\n}\n\n.tvm-meta-chips {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 0.35rem;\n}\n\n.tvm-meta-chip {\n  display: inline-flex;\n  align-items: center;\n  gap: 0.25rem;\n  border-radius: 999px;\n  padding: var(--tvm-chip-padding-y) var(--tvm-chip-padding-x);\n  font-size: 0.72rem;\n  color: var(--tvm-text-secondary);\n  background: var(--tvm-pill-muted-bg);\n  border: 1px solid transparent;\n  appearance: none;\n  cursor: pointer;\n  transition: border-color 0.2s ease-in-out, color 0.2s ease-in-out, background 0.2s ease-in-out;\n}\n\n.tvm-meta-chip:hover {\n  border-color: var(--tvm-border-strong);\n  color: var(--tvm-text-primary);\n}\n\n.tvm-meta-chip:focus-visible {\n  outline: 2px solid var(--tvm-accent-strong);\n  outline-offset: 2px;\n}\n\n.tvm-meta-chip-label {\n  white-space: nowrap;\n}\n\n.tvm-meta-chip-close {\n  font-size: 0.85em;\n  line-height: 1;\n}\n\n.tvm-highlight {\n  display: inline;\n  background: rgb(var(--primary) / 0.22);\n  color: inherit;\n  border-radius: 4px;\n  padding: 0 0.08em;\n  line-height: inherit;\n  box-decoration-break: clone;\n}\n\n.tvm-spec-grid-container {\n  border: 1px solid var(--tvm-border);\n  border-radius: 12px;\n  background: var(--tvm-surface-secondary);\n  box-shadow: inset 0 1px 0 rgb(var(--gray-400) / 0.08);\n}\n\n.tvm-spec-grid-scroll {\n  overflow-x: auto;\n}\n\n.tvm-spec-grid-scroll::-webkit-scrollbar {\n  height: 6px;\n}\n\n.tvm-spec-grid-scroll::-webkit-scrollbar-thumb {\n  background: var(--tvm-border-strong);\n  border-radius: 999px;\n}\n\n.tvm-spec-header,\n.tvm-spec-row {\n  --tvm-grid-template: 60px 110px 260px minmax(320px, 2fr);\n  display: grid;\n  grid-template-columns: var(--tvm-grid-template);\n  min-width: 860px;\n}\n\n.tvm-spec-header {\n  background: rgb(var(--gray-400) / 0.12);\n  text-transform: uppercase;\n  letter-spacing: 0.08em;\n  font-size: 0.7rem;\n  color: var(--tvm-text-secondary);\n}\n\n:where(.dark) .tvm-instruction-app .tvm-spec-header {\n  background: rgb(var(--gray-800) / 0.65);\n  color: var(--tvm-text-muted);\n}\n\n.tvm-spec-header > div {\n  padding: calc(var(--tvm-row-padding-y) - 0.1rem) var(--tvm-row-padding-x);\n  font-weight: 600;\n}\n\n.tvm-spec-row {\n  border-top: 1px solid var(--tvm-border);\n  transition: background 0.2s ease-in-out;\n  cursor: pointer;\n  align-items: center;\n}\n\n.tvm-spec-row:hover {\n  background: rgb(var(--primary) / 0.08);\n}\n\n.tvm-spec-row.is-expanded {\n  background: rgb(var(--primary) / 0.12);\n}\n\n:where(.dark) .tvm-instruction-app .tvm-spec-row:hover {\n  background: rgb(var(--primary) / 0.18);\n}\n\n:where(.dark) .tvm-instruction-app .tvm-spec-row.is-expanded {\n  background: rgb(var(--primary) / 0.26);\n}\n\n.tvm-spec-row.is-anchor-target {\n  background: rgb(var(--primary) / 0.16);\n  box-shadow: inset 0 0 0 1px var(--tvm-accent-strong);\n}\n\n.tvm-spec-row--detail.is-anchor-target {\n  background: rgb(var(--primary) / 0.1);\n}\n\n.tvm-spec-row--detail {\n  cursor: default;\n  background: var(--tvm-surface-secondary);\n  align-items: stretch;\n}\n\n.tvm-spec-cell {\n  padding: var(--tvm-row-padding-y) var(--tvm-row-padding-x);\n  display: flex;\n  flex-direction: column;\n  gap: 0.35rem;\n  min-width: 0;\n  color: var(--tvm-text-primary);\n}\n\n.tvm-spec-cell--full {\n  grid-column: 1 / -1;\n}\n\n.tvm-spec-cell--opcode {\n  font-family: 'JetBrains Mono', 'Menlo', 'Monaco', monospace;\n  font-size: 0.85rem;\n  justify-content: center;\n  align-items: center;\n}\n\n.tvm-spec-cell--anchor {\n  justify-content: center;\n  align-items: center;\n}\n\n.tvm-spec-cell--name {\n  gap: 0.4rem;\n}\n\n.tvm-name-line {\n  position: relative;\n}\n\n.tvm-copy-link {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  width: 22px;\n  height: 22px;\n  border-radius: 6px;\n  border: 1px solid var(--tvm-border);\n  background: var(--tvm-surface-secondary);\n  color: var(--tvm-text-secondary);\n  cursor: pointer;\n}\n\n.tvm-copy-link:hover {\n  border-color: var(--tvm-border-strong);\n}\n\n.tvm-copy-link svg {\n  width: 14px;\n  height: 14px;\n}\n\n.tvm-copy-link.is-copied {\n  border-color: var(--tvm-accent-strong);\n  background: var(--tvm-accent-soft);\n  color: var(--tvm-accent-strong);\n}\n\n.tvm-name-line {\n  display: flex;\n  align-items: baseline;\n  flex-wrap: wrap;\n  gap: 0.5rem;\n}\n\n.tvm-row-indicator {\n  margin-left: auto;\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  width: 24px;\n  height: 24px;\n  border-radius: 50%;\n  color: var(--tvm-text-muted);\n  transition: transform 0.2s ease-in-out, color 0.2s ease-in-out, background 0.2s ease-in-out;\n  pointer-events: none;\n}\n\n.tvm-row-indicator svg {\n  width: 14px;\n  height: 14px;\n}\n\n.tvm-spec-row:hover .tvm-row-indicator {\n  background: var(--tvm-pill-muted-bg);\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-spec-row.is-anchor-target .tvm-row-indicator {\n  color: var(--tvm-accent-strong);\n}\n\n.tvm-row-indicator.is-expanded {\n  transform: rotate(180deg);\n  color: var(--tvm-accent-strong);\n}\n\n.tvm-mnemonic {\n  font-family: 'JetBrains Mono', 'Menlo', 'Monaco', monospace;\n  font-size: 1rem;\n  font-weight: 600;\n  color: var(--tvm-text-primary);\n  white-space: pre;\n}\n\n.tvm-spec-cell--gas {\n  font-family: 'JetBrains Mono', 'Menlo', 'Monaco', monospace;\n  font-size: 0.85rem;\n  justify-content: center;\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-spec-cell--description p {\n  margin: 0;\n}\n\n.tvm-description p {\n  margin: 0;\n}\n\n.tvm-description {\n  font-size: 0.92rem;\n  line-height: 1.45;\n  color: var(--tvm-text-secondary);\n  display: -webkit-box;\n  -webkit-line-clamp: 3;\n  -webkit-box-orient: vertical;\n  overflow: hidden;\n}\n\n.tvm-description-meta {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 0.35rem;\n}\n\n.tvm-category-pill {\n  display: inline-flex;\n  align-items: center;\n  padding: 0.2rem 0.55rem;\n  border-radius: 999px;\n  background: var(--tvm-accent-soft);\n  color: var(--tvm-accent-subtle);\n  font-size: 0.72rem;\n  letter-spacing: 0.03em;\n}\n\n.tvm-inline-badge {\n  display: inline-flex;\n  align-items: center;\n  padding: 0.18rem 0.45rem;\n  border-radius: 999px;\n  font-size: 0.7rem;\n  letter-spacing: 0.05em;\n  text-transform: uppercase;\n  background: var(--tvm-accent-soft);\n  color: var(--tvm-accent-subtle);\n}\n\n.tvm-inline-badge--muted {\n  background: var(--tvm-pill-muted-bg);\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-fift {\n  font-size: 0.78rem;\n  color: var(--tvm-text-secondary);\n  font-family: 'JetBrains Mono', 'Menlo', 'Monaco', monospace;\n}\n\n.tvm-operands {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 0.35rem;\n}\n\n.tvm-operand-chip {\n  display: inline-flex;\n  align-items: center;\n  padding: 0.18rem 0.45rem;\n  border-radius: 6px;\n  border: 1px solid var(--tvm-border);\n  background: var(--tvm-pill-muted-bg);\n  font-size: 0.72rem;\n  font-family: 'JetBrains Mono', 'Menlo', 'Monaco', monospace;\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-stack-columns {\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\n  gap: 0.6rem;\n}\n\n.tvm-stack-column {\n  background: var(--tvm-surface-secondary);\n  border: 1px solid rgb(var(--gray-400) / 0.35);\n  border-radius: 10px;\n  padding: 0.6rem 0.65rem;\n  min-width: 0;\n}\n\n.tvm-stack-column--compact {\n  padding: 0.5rem 0.55rem;\n}\n\n.tvm-stack-column-title {\n  font-size: 0.7rem;\n  text-transform: uppercase;\n  letter-spacing: 0.08em;\n  color: var(--tvm-text-secondary);\n  margin-bottom: 0.35rem;\n}\n\n.tvm-stack-top {\n  font-size: 0.7rem;\n  color: var(--tvm-text-muted);\n  margin-bottom: 0.35rem;\n}\n\n.tvm-stack-list {\n  display: flex;\n  flex-direction: column;\n  gap: 0.35rem;\n}\n\n.tvm-stack-pill {\n  display: inline-flex;\n  align-items: center;\n  padding: 0.18rem 0.45rem;\n  border-radius: 6px;\n  font-size: 0.75rem;\n  font-family: 'JetBrains Mono', 'Menlo', 'Monaco', monospace;\n  width: fit-content;\n}\n\n.tvm-instruction-app.is-density-compact .tvm-stack-pill {\n  font-size: 0.7rem;\n  padding: 0.14rem 0.35rem;\n}\n\n.tvm-stack-pill--simple {\n  background: var(--tvm-stack-simple-bg);\n  color: var(--tvm-stack-simple-text);\n}\n\n.tvm-stack-pill--const {\n  background: var(--tvm-stack-const-bg);\n  color: var(--tvm-stack-const-text);\n}\n\n.tvm-stack-pill--array {\n  background: var(--tvm-stack-array-bg);\n  color: var(--tvm-stack-array-text);\n}\n\n.tvm-stack-pill--conditional {\n  background: var(--tvm-stack-conditional-bg);\n  color: var(--tvm-stack-conditional-text);\n}\n\n.tvm-stack-pill--empty {\n  background: var(--tvm-pill-muted-bg);\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-stack-pill--more {\n  background: rgb(var(--gray-400) / 0.18);\n  color: var(--tvm-text-secondary);\n}\n\n:where(.dark) .tvm-instruction-app .tvm-stack-pill--more {\n  background: rgb(var(--gray-700) / 0.5);\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-stack-footnote {\n  display: inline-block;\n  font-family: 'JetBrains Mono', 'Menlo', 'Monaco', monospace;\n  font-size: 0.75rem;\n  background: rgb(var(--gray-200) / 0.12);\n  border: 1px solid var(--tvm-border);\n  border-radius: 6px;\n  padding: 0.3rem 0.45rem;\n  color: var(--tvm-text-secondary);\n  max-width: 100%;\n  overflow-wrap: anywhere;\n}\n\n:where(.dark) .tvm-instruction-app .tvm-stack-footnote {\n  background: rgb(var(--gray-900) / 0.6);\n  border-color: var(--tvm-border);\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-stack-conditional {\n  border-left: 2px solid var(--tvm-stack-conditional-border);\n  padding-left: 0.55rem;\n  display: flex;\n  flex-direction: column;\n  gap: 0.35rem;\n}\n\n.tvm-stack-conditional-name {\n  font-size: 0.78rem;\n  font-weight: 600;\n  color: var(--tvm-stack-conditional-text);\n}\n\n.tvm-stack-conditional-branch {\n  display: flex;\n  flex-direction: column;\n  gap: 0.25rem;\n}\n\n.tvm-stack-conditional-label {\n  font-size: 0.7rem;\n  text-transform: uppercase;\n  letter-spacing: 0.05em;\n  color: var(--tvm-stack-label);\n}\n\n.tvm-stack-conditional-values {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 0.3rem;\n}\n\n.tvm-stack-array {\n  display: flex;\n  flex-direction: column;\n  gap: 0.3rem;\n}\n\n.tvm-stack-array-preview {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 0.3rem;\n  padding-left: 0.4rem;\n}\n\n.tvm-stack-empty {\n  font-size: 0.78rem;\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-detail-panel {\n  background: var(--tvm-surface);\n  border: 1px solid var(--tvm-border);\n  border-radius: 14px;\n  padding: 1rem 1.15rem 1.25rem;\n  box-shadow: 0 18px 40px -30px rgb(var(--gray-900) / 0.7);\n}\n\n.tvm-detail-panel.is-anchor-target {\n  border-color: var(--tvm-accent-strong);\n  box-shadow: 0 0 0 2px var(--tvm-accent-soft), 0 18px 40px -30px rgb(var(--gray-900) / 0.7);\n}\n\n.tvm-detail-header {\n  display: flex;\n  justify-content: space-between;\n  align-items: flex-start;\n  gap: 1rem;\n  flex-wrap: wrap;\n  margin-bottom: 1rem;\n}\n\n.tvm-detail-header-main {\n  display: flex;\n  align-items: baseline;\n  gap: 0.45rem;\n  flex-wrap: wrap;\n}\n\n.tvm-detail-heading {\n  display: flex;\n  flex-direction: column;\n  gap: 0.55rem;\n  align-items: flex-start;\n  flex: 1 1 auto;\n}\n\n.tvm-detail-actions {\n  display: flex;\n  gap: 0.5rem;\n  flex-wrap: wrap;\n  align-items: center;\n  justify-content: flex-end;\n}\n\n.tvm-detail-title {\n  margin: 0;\n  font-size: 0.78rem;\n  letter-spacing: 0.05em;\n  text-transform: uppercase;\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-detail-badges {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 0.45rem;\n}\n\n.tvm-detail-badge {\n  display: inline-flex;\n  align-items: center;\n  gap: 0.35rem;\n  border: 1px solid var(--tvm-border);\n  border-radius: 999px;\n  background: var(--tvm-surface-secondary);\n  padding: 0.28rem 0.7rem;\n  font-size: 0.78rem;\n  color: var(--tvm-text-primary);\n}\n\n.tvm-detail-badge-label {\n  font-size: 0.68rem;\n  text-transform: uppercase;\n  letter-spacing: 0.08em;\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-detail-badge-value {\n  font-weight: 600;\n  display: inline-flex;\n  gap: 0.2rem;\n  color: var(--tvm-text-primary);\n}\n\n.tvm-detail-badge--register {\n  background: rgb(var(--primary) / 0.08);\n  border-color: rgb(var(--primary) / 0.2);\n}\n\n.tvm-register-token {\n  font-family: 'JetBrains Mono', 'Menlo', 'Monaco', monospace;\n  font-size: 0.82rem;\n  color: var(--tvm-text-primary);\n}\n\n.tvm-register-token sub {\n  font-size: 0.7em;\n}\n\n.tvm-register-token--special {\n  font-weight: 600;\n  text-transform: uppercase;\n}\n\n.tvm-register-sep {\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-detail-columns {\n  display: flex;\n  flex-wrap: wrap;\n  gap: clamp(1rem, 2.5vw, 1.6rem);\n  align-items: flex-start;\n  margin-bottom: 1.1rem;\n}\n\n.tvm-detail-main {\n  flex: 1 1 320px;\n  min-width: 0;\n  display: flex;\n  flex-direction: column;\n  gap: 0.8rem;\n}\n\n.tvm-detail-block {\n  display: flex;\n  flex-direction: column;\n  gap: 0.45rem;\n  background: var(--tvm-surface-secondary);\n  border: 1px solid var(--tvm-border);\n  border-radius: 12px;\n  padding: 0.85rem 0.95rem;\n}\n\n.tvm-detail-main .tvm-description {\n  display: block;\n  color: var(--tvm-text-primary);\n  -webkit-line-clamp: initial;\n  -webkit-box-orient: initial;\n  overflow: visible;\n}\n\n.tvm-detail-subtitle {\n  font-size: 0.7rem;\n  letter-spacing: 0.04em;\n  text-transform: uppercase;\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-detail-fift {\n  display: flex;\n  flex-direction: column;\n  gap: 0.4rem;\n}\n\n.tvm-detail-code {\n  display: block;\n  font-family: 'JetBrains Mono', 'Menlo', 'Monaco', monospace;\n  font-size: 0.78rem;\n  line-height: 1.45;\n  white-space: pre-wrap;\n  background: rgb(var(--gray-200) / 0.08);\n  border: 1px solid var(--tvm-border);\n  border-radius: 8px;\n  padding: 0.6rem 0.65rem;\n  color: var(--tvm-text-primary);\n  overflow-x: auto;\n  max-width: 100%;\n}\n\n.tvm-detail-code--inline {\n  display: block;\n  padding: 0.5rem 0.6rem;\n  word-break: break-word;\n}\n\n.tvm-detail-muted {\n  margin: 0;\n  font-size: 0.78rem;\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-detail-side {\n  flex: 0 1 300px;\n  display: flex;\n  flex-direction: column;\n  gap: 0.9rem;\n}\n\n.tvm-side-block {\n  display: flex;\n  flex-direction: column;\n  gap: 0.5rem;\n  background: var(--tvm-surface-secondary);\n  border: 1px solid rgb(var(--gray-400) / 0.3);\n  border-radius: 12px;\n  padding: 0.85rem 0.95rem;\n}\n\n.tvm-side-category-value {\n  font-size: 0.9rem;\n  font-weight: 600;\n  color: var(--tvm-text-primary);\n}\n\n.tvm-side-category-raw {\n  font-size: 0.82rem;\n  font-weight: 400;\n  color: var(--tvm-text-secondary);\n  margin-left: 0.3rem;\n}\n\n.tvm-side-title {\n  font-size: 0.7rem;\n  letter-spacing: 0.04em;\n  text-transform: uppercase;\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-detail-section {\n  display: flex;\n  flex-direction: column;\n  gap: 0.55rem;\n  background: var(--tvm-surface-secondary);\n  border: 1px solid rgb(var(--gray-400) / 0.3);\n  border-radius: 12px;\n  padding: 0.85rem 0.95rem;\n  margin-bottom: 0.9rem;\n}\n\n.tvm-detail-section--wide {\n  margin-bottom: 0.9rem;\n}\n\n.tvm-operands-list {\n  display: flex;\n  flex-direction: column;\n  gap: 0.6rem;\n}\n\n.tvm-operands-item {\n  background: var(--tvm-surface);\n  border: 1px solid rgb(var(--gray-400) / 0.25);\n  border-radius: 10px;\n  padding: 0.65rem 0.75rem;\n  display: flex;\n  flex-direction: column;\n  gap: 0.35rem;\n}\n\n.tvm-operands-line {\n  font-weight: 600;\n  font-size: 0.88rem;\n  color: var(--tvm-text-primary);\n}\n\n.tvm-operands-detail {\n  font-size: 0.78rem;\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-impl-badges {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 0.45rem;\n}\n\n.tvm-detail-badge--link {\n  text-decoration: none;\n  color: var(--tvm-text-primary);\n  transition: border-color 0.2s ease-in-out, color 0.2s ease-in-out;\n}\n\n.tvm-detail-badge--link:hover {\n  border-color: var(--tvm-accent);\n  color: var(--tvm-accent);\n}\n\n.tvm-modal {\n  position: fixed;\n  inset: 0;\n  z-index: 1000;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  padding: 1rem;\n}\n\n.tvm-modal-backdrop {\n  position: absolute;\n  inset: 0;\n  background: rgb(var(--gray-900) / 0.45);\n  backdrop-filter: blur(1px);\n}\n\n.tvm-modal-dialog {\n  position: relative;\n  background: var(--tvm-surface);\n  border: 1px solid var(--tvm-border);\n  border-radius: 14px;\n  box-shadow: 0 32px 90px -40px rgb(var(--gray-900) / 0.9);\n  width: min(720px, 100%);\n  max-height: calc(100% - 2rem);\n  overflow: hidden;\n  display: flex;\n  flex-direction: column;\n  gap: 0.9rem;\n  padding: 1.1rem 1.2rem 1.3rem;\n  color: var(--tvm-text-primary);\n}\n\n.tvm-modal-header {\n  display: flex;\n  justify-content: space-between;\n  align-items: flex-start;\n  gap: 1rem;\n}\n\n.tvm-modal-header-text {\n  display: flex;\n  flex-direction: column;\n  gap: 0.35rem;\n}\n\n.tvm-modal-header-text h3 {\n  margin: 0;\n  font-size: 1rem;\n  color: var(--tvm-text-primary);\n}\n\n.tvm-modal-subtitle {\n  margin: 0;\n  font-size: 0.85rem;\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-modal-subtitle code {\n  font-family: 'JetBrains Mono', 'Menlo', 'Monaco', monospace;\n  font-size: 0.82rem;\n  padding: 0.1rem 0.3rem;\n  border-radius: 0.4rem;\n  background: var(--tvm-pill-muted-bg);\n  color: var(--tvm-text-primary);\n}\n\n.tvm-modal-actions {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 0.45rem;\n  justify-content: flex-end;\n}\n\n.tvm-modal-code {\n  flex: 1 1 auto;\n  margin: 0;\n  border: 1px solid var(--tvm-border-strong);\n  border-radius: 10px;\n  padding: 0.85rem 0.95rem;\n  background: rgb(var(--gray-200) / 0.16);\n  font-family: 'JetBrains Mono', 'Menlo', 'Monaco', monospace;\n  font-size: 0.82rem;\n  line-height: 1.55;\n  overflow: auto;\n  white-space: pre;\n  color: var(--tvm-text-primary);\n  tab-size: 2;\n}\n\n:where(.dark) .tvm-instruction-app .tvm-modal-code {\n  background: rgb(var(--gray-900) / 0.7);\n}\n\n@media (max-width: 1040px) {\n  .tvm-instruction-toolbar {\n    flex-direction: column;\n    align-items: stretch;\n  }\n\n  .tvm-toolbar-utilities {\n    justify-content: flex-start;\n    width: 100%;\n  }\n}\n\n@media (max-width: 900px) {\n  .tvm-spec-grid-scroll {\n    overflow-x: visible;\n  }\n\n  .tvm-spec-header {\n    display: none;\n  }\n\n  .tvm-spec-row,\n  .tvm-spec-row--detail {\n    --tvm-grid-template: 48px minmax(0, 1fr);\n    grid-template-columns: var(--tvm-grid-template);\n    min-width: 0;\n    align-items: start;\n  }\n\n  .tvm-spec-row .tvm-spec-cell--anchor {\n    grid-row: span 2;\n  }\n\n  .tvm-spec-row .tvm-spec-cell--opcode {\n    grid-row: 1;\n    grid-column: 2 / -1;\n    justify-content: flex-start;\n    align-items: baseline;\n  }\n\n  .tvm-spec-row .tvm-spec-cell--name {\n    grid-column: 2 / -1;\n  }\n\n  .tvm-spec-row .tvm-spec-cell--description {\n    grid-column: 1 / -1;\n  }\n}\n\n@media (max-width: 960px) {\n  .tvm-detail-header {\n    align-items: stretch;\n  }\n\n  .tvm-detail-columns {\n    flex-direction: column;\n  }\n\n  .tvm-detail-section {\n    margin-bottom: 0.8rem;\n  }\n}\n\n@media (max-width: 720px) {\n  .tvm-detail-panel {\n    padding: 0.95rem 1rem 1.1rem;\n  }\n\n  .tvm-side-block,\n  .tvm-detail-section {\n    padding: 0.85rem 0.9rem;\n  }\n\n  .tvm-detail-actions {\n    width: 100%;\n    justify-content: stretch;\n  }\n\n  .tvm-detail-actions .tvm-button {\n    flex: 1 1 auto;\n  }\n}\n\n@media (max-width: 640px) {\n  .tvm-modal {\n    padding: 0.75rem;\n  }\n\n  .tvm-modal-dialog {\n    width: 100%;\n    max-height: calc(100% - 1.5rem);\n    padding: 1rem;\n  }\n\n  .tvm-modal-actions {\n    width: 100%;\n    justify-content: stretch;\n  }\n\n  .tvm-modal-actions .tvm-button {\n    flex: 1 1 auto;\n  }\n}\n\n.tvm-control-flow {\n  display: flex;\n  flex-direction: column;\n  gap: 0.65rem;\n  padding: 0.75rem 0.8rem;\n  border-radius: 12px;\n  border: 1px solid var(--tvm-border);\n  background: var(--tvm-surface-secondary);\n}\n\n.tvm-control-flow-status {\n  display: flex;\n  align-items: center;\n  gap: 0.75rem;\n  font-size: 0.85rem;\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-control-flow-label {\n  font-weight: 600;\n  text-transform: uppercase;\n  letter-spacing: 0.05em;\n}\n\n.tvm-control-flow-value {\n  font-family: 'JetBrains Mono', 'Menlo', 'Monaco', monospace;\n  font-size: 0.85rem;\n  color: var(--tvm-text-primary);\n}\n\n.tvm-control-flow-branches {\n  list-style: none;\n  margin: 0;\n  margin-top: 0.5rem;\n  padding: 0;\n  display: flex;\n  flex-direction: column;\n  gap: 0.55rem;\n}\n\n.tvm-control-flow-branch {\n  background: var(--tvm-surface);\n  border: 1px solid rgb(var(--gray-400) / 0.35);\n  border-radius: 10px;\n  padding: 0.65rem 0.75rem;\n  display: flex;\n  flex-direction: column;\n  gap: 0.45rem;\n}\n\n.tvm-control-flow-branch-header {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 0.5rem;\n  align-items: baseline;\n}\n\n.tvm-control-flow-branch-title {\n  font-size: 0.84rem;\n  font-weight: 600;\n  color: var(--tvm-text-primary);\n}\n\n.tvm-control-flow-branch-condition {\n  font-size: 0.76rem;\n  color: var(--tvm-text-secondary);\n}\n\n\n.tvm-flow-graph-wrapper {\n  position: relative;\n  width: 100%;\n  overflow-x: auto;\n  padding: 0.35rem 0;\n}\n\n.tvm-flow-canvas {\n  position: relative;\n  display: inline-block;\n  min-height: 120px;\n  min-width: 100%;\n}\n\n.tvm-flow-canvas-svg {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  overflow: visible;\n  pointer-events: none;\n}\n\n.tvm-flow-graph-line {\n  fill: none;\n  stroke: rgb(var(--primary) / 0.45);\n  stroke-width: 1.6;\n}\n\n\n.tvm-flow-node {\n  position: absolute;\n  transform: translate(-50%, -50%);\n  pointer-events: auto;\n}\n\n.tvm-flow-edge-label {\n  position: absolute;\n  transform: translate(-50%, -50%);\n  pointer-events: none;\n  display: flex;\n  align-items: center;\n  gap: 0.25rem;\n  font-family: 'JetBrains Mono', 'Menlo', 'Monaco', monospace;\n  font-size: 0.75rem;\n  text-transform: uppercase;\n  letter-spacing: 0.05em;\n  padding: 0.08rem 0.45rem;\n  border-radius: 999px;\n  border: 1px solid rgb(var(--primary) / 0.2);\n  background: var(--tvm-surface);\n}\n\n.tvm-flow-edge-label.has-secondary {\n  background: linear-gradient(\n    90deg,\n    rgb(var(--primary) / 0.08) 0%,\n    rgb(var(--primary) / 0.08) 50%,\n    rgb(var(--primary) / 0.04) 50%,\n    rgb(var(--primary) / 0.04) 100%\n  );\n}\n\n.tvm-flow-edge-label-primary {\n  color: rgb(var(--primary));\n}\n\n.tvm-flow-edge-label-secondary {\n  color: rgb(var(--primary) / 0.55);\n}\n\n.tvm-control-flow-node-pill {\n  display: inline-flex;\n  align-items: center;\n  gap: 0.35rem;\n  border: 1px solid rgb(var(--primary) / 0.25);\n  border-radius: 999px;\n  padding: 0.18rem 0.65rem;\n  background: rgb(var(--primary) / 0.05);\n  white-space: nowrap;\n}\n\n.tvm-control-flow-node-type {\n  text-transform: uppercase;\n  letter-spacing: 0.08em;\n  font-size: 0.66rem;\n  font-weight: 600;\n  color: rgb(var(--primary) / 0.9);\n}\n\n.tvm-control-flow-node-value {\n  font-family: 'JetBrains Mono', 'Menlo', 'Monaco', monospace;\n  font-size: 0.66rem;\n  color: var(--tvm-text-primary);\n}\n\n.tvm-control-flow-node-extra {\n  font-size: 0.72rem;\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-missing-placeholder {\n  margin: 0;\n  font-size: 0.78rem;\n  color: var(--tvm-callout-text);\n  background: rgb(var(--primary) / 0.04);\n  border: 1px solid rgb(var(--primary) / 0.12);\n  border-radius: 8px;\n  padding: 0.35rem 0.55rem;\n}\n\n.tvm-example-list {\n  list-style: none;\n  margin: 0;\n  padding: 0;\n  display: flex;\n  flex-direction: column;\n  gap: 0.75rem;\n}\n\n.tvm-example-item {\n  display: flex;\n  flex-direction: column;\n  gap: 0.35rem;\n  background: var(--tvm-surface);\n  border: 1px solid rgb(var(--gray-400) / 0.28);\n  border-radius: 10px;\n  padding: 0.7rem 0.85rem;\n}\n\n.tvm-example-description {\n  margin: 0;\n  font-size: 0.82rem;\n  color: var(--tvm-text-primary);\n}\n\n.tvm-example-description a {\n  color: var(--tvm-accent);\n  text-decoration: none;\n}\n\n.tvm-example-description a:hover {\n  text-decoration: underline;\n}\n\n.tvm-example-code {\n  white-space: pre-wrap;\n}\n\n\n\n.tvm-alias-list {\n  list-style: none;\n  margin: 0;\n  padding: 0;\n  display: flex;\n  flex-direction: column;\n  gap: 0.6rem;\n}\n\n.tvm-alias-item {\n  list-style: none;\n  display: flex;\n  flex-direction: column;\n  gap: 0.4rem;\n  background: var(--tvm-surface-secondary);\n  border: 1px solid var(--tvm-border);\n  border-radius: 8px;\n  padding: 0.55rem 0.7rem;\n}\n\n.tvm-alias-headline {\n  display: flex;\n  align-items: baseline;\n  gap: 0.4rem;\n}\n\n.tvm-alias-headline code {\n  font-family: 'JetBrains Mono', 'Menlo', 'Monaco', monospace;\n  font-size: 0.85rem;\n  color: var(--tvm-text-primary);\n}\n\n.tvm-alias-meta {\n  font-size: 0.75rem;\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-alias-description {\n  margin: 0;\n  font-size: 0.82rem;\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-alias-meta-row {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 0.35rem;\n}\n\n.tvm-alias-pill {\n  display: inline-flex;\n  align-items: center;\n  gap: 0.3rem;\n  padding: 0.18rem 0.45rem;\n  border-radius: 6px;\n  background: var(--tvm-pill-muted-bg);\n  color: var(--tvm-text-secondary);\n  font-size: 0.72rem;\n}\n\n.tvm-alias-pill code {\n  font-family: 'JetBrains Mono', 'Menlo', 'Monaco', monospace;\n}\n\n.tvm-loading-row,\n.tvm-empty-row,\n.tvm-error-row {\n  grid-column: 1 / -1;\n  text-align: center;\n  padding: 1.5rem 1rem;\n  font-size: 0.92rem;\n  color: var(--tvm-text-secondary);\n}\n\n.tvm-error-row {\n  color: var(--tvm-accent-strong);\n}\n\n@media (max-width: 1024px) {\n  .tvm-instruction-app {\n    padding: 1.1rem;\n  }\n\n  .tvm-spec-header,\n  .tvm-spec-row {\n    --tvm-grid-template: 48px 95px 220px minmax(280px, 2fr);\n    min-width: 720px;\n  }\n}\n\n@media (max-width: 768px) {\n  .tvm-field {\n    width: 100%;\n    min-width: 0;\n  }\n\n  .tvm-toolbar-filters {\n    grid-template-columns: 1fr;\n  }\n\n  .tvm-toolbar-utilities {\n    justify-self: stretch;\n    justify-content: flex-start;\n  }\n\n  .tvm-toolbar-divider {\n    display: none;\n  }\n\n  .tvm-meta-items {\n    flex-direction: column;\n    align-items: flex-start;\n    gap: 0.5rem;\n  }\n\n  .tvm-stack-columns {\n    flex-direction: column;\n  }\n}\n`,\n    []\n  );\n  const searchTokens = useMemo(() => createSearchTokens(search), [search]);\n\n  useEffect(() => {\n    let cancelled = false;\n\n    async function load() {\n      try {\n        setLoading(true);\n        setError(null);\n        const response = await fetch(SPEC_URL);\n        if (!response.ok) {\n          throw new Error(`Failed to load spec (${response.status})`);\n        }\n        const payload = await response.json();\n        if (!cancelled) {\n          setSpec(payload);\n          setLoading(false);\n          return;\n        }\n      } catch (cause) {\n        if (!cancelled) {\n          setError(cause instanceof Error ? cause.message : \"Unknown error\");\n        }\n      } finally {\n        if (!cancelled) {\n          setLoading(false);\n        }\n      }\n    }\n\n    load();\n\n    return () => {\n      cancelled = true;\n    };\n  }, []);\n\n  useEffect(() => {\n    setExpanded({});\n  }, [spec]);\n\n  useEffect(() => {\n    if (typeof window === \"undefined\") return;\n    try {\n      const raw = window.localStorage.getItem(PERSIST_KEY);\n      if (!raw) return;\n      const prefs = JSON.parse(raw);\n      if (prefs && typeof prefs === \"object\") {\n        if (typeof prefs.search === \"string\") setSearch(prefs.search);\n        if (\n          typeof prefs.category === \"string\" &&\n          (prefs.category === \"All\" || CATEGORY_GROUP_KEYS.has(prefs.category))\n        ) {\n          setCategory(prefs.category);\n        }\n        if (typeof prefs.subcategory === \"string\") {\n          setSubcategory(prefs.subcategory);\n        }\n        if (\n          typeof prefs.sortMode === \"string\" &&\n          [\"opcode\", \"name\", \"category\", \"since\"].includes(prefs.sortMode)\n        ) {\n          setSortMode(prefs.sortMode);\n        }\n      }\n    } catch (err) {\n      // ignore malformed localStorage content\n    }\n  }, []);\n\n  useEffect(() => {\n    if (typeof window === \"undefined\") return;\n    try {\n      const payload = JSON.stringify({\n        search,\n        category,\n        subcategory,\n        sortMode,\n      });\n      window.localStorage.setItem(PERSIST_KEY, payload);\n    } catch (err) {\n      // ignore persistence failures (private mode, etc.)\n    }\n  }, [search, category, subcategory, sortMode]);\n\n  useEffect(() => {\n    if (typeof window === \"undefined\") return;\n    const handler = (event) => {\n      if (event.defaultPrevented || event.key !== \"/\") return;\n      if (event.altKey || event.ctrlKey || event.metaKey) return;\n      const active = document.activeElement;\n      if (active) {\n        const tagName = active.tagName ? active.tagName.toLowerCase() : \"\";\n        if (\n          tagName === \"input\" ||\n          tagName === \"textarea\" ||\n          active.isContentEditable\n        ) {\n          return;\n        }\n      }\n      event.preventDefault();\n      if (searchInputRef.current && typeof searchInputRef.current.focus === \"function\") {\n        searchInputRef.current.focus();\n      }\n    };\n    window.addEventListener(\"keydown\", handler);\n    return () => window.removeEventListener(\"keydown\", handler);\n  }, []);\n\n  useEffect(() => {\n    if (typeof window === \"undefined\") return;\n    const syncHash = () => {\n      const hash = window.location.hash ? window.location.hash.slice(1) : \"\";\n      if (!hash) {\n        setActiveAnchorId(null);\n        return;\n      }\n      try {\n        setActiveAnchorId(decodeURIComponent(hash));\n      } catch (_err) {\n        setActiveAnchorId(hash);\n      }\n    };\n    syncHash();\n    window.addEventListener(\"hashchange\", syncHash);\n    return () => window.removeEventListener(\"hashchange\", syncHash);\n  }, []);\n\n  const instructions = useMemo(() => {\n    if (!spec) {\n      return [];\n    }\n\n    const aliasByMnemonic = new Map();\n    const aliases = Array.isArray(spec.aliases) ? spec.aliases : [];\n    aliases.forEach((alias) => {\n      if (!alias || !alias.alias_of) return;\n      const list = aliasByMnemonic.get(alias.alias_of) || [];\n      list.push(alias);\n      aliasByMnemonic.set(alias.alias_of, list);\n    });\n\n    return (Array.isArray(spec.instructions) ? spec.instructions : []).map(\n      (raw, idx) => {\n        const doc = raw.doc || {};\n        const bytecode = raw.bytecode || {};\n        const valueFlow = raw.value_flow || {};\n        const inputs = Array.isArray(valueFlow.inputs?.stack)\n          ? valueFlow.inputs.stack\n          : [];\n        const outputs = Array.isArray(valueFlow.outputs?.stack)\n          ? valueFlow.outputs.stack\n          : [];\n        const registersIn = Array.isArray(valueFlow.inputs?.registers)\n          ? valueFlow.inputs.registers\n          : [];\n        const registersOut = Array.isArray(valueFlow.outputs?.registers)\n          ? valueFlow.outputs.registers\n          : [];\n\n        const categoryKeyRaw = doc.category || \"uncategorized\";\n        const categoryGroup = resolveCategoryGroup(categoryKeyRaw);\n        const categoryGroupKey = categoryGroup.key;\n        const categoryGroupLabel = categoryGroup.label;\n        const rawCategoryLabel = humanizeCategoryKey(categoryKeyRaw);\n        const descriptionMissing = !doc.description;\n        const stackDocMissing = !doc.stack;\n        const gasMissing = !doc.gas;\n        const tlbMissing = !bytecode.tlb;\n        const inputsMissing = !Array.isArray(valueFlow.inputs?.stack);\n        const outputsMissing = !Array.isArray(valueFlow.outputs?.stack);\n        const implementationRefs = extractImplementationRefs(raw.implementation);\n        const implementationMissing = implementationRefs.length === 0;\n        const controlFlowMissing =\n          !raw.control_flow || !Array.isArray(raw.control_flow.branches);\n\n        const opcode = bytecode.prefix || \"\";\n        const anchorId = buildAnchorId({ opcode, mnemonic: raw.mnemonic });\n\n        return {\n          uid: `${raw.mnemonic}__${opcode || 'nop'}__${idx}`,\n          mnemonic: raw.mnemonic,\n          since: typeof raw.since_version === \"number\" ? raw.since_version : 0,\n          anchorId,\n          categoryKey: categoryGroupKey,\n          categoryLabel: categoryGroupLabel,\n          rawCategoryKey: categoryKeyRaw,\n          rawCategoryLabel,\n          description: doc.description || \"\",\n          descriptionHtml: typeof doc.description_html === \"string\"\n            ? doc.description_html\n            : \"\",\n          fift: doc.fift || \"\",\n          fiftExamples: Array.isArray(doc.fift_examples)\n            ? doc.fift_examples\n                .map((example) =>\n                  example && typeof example === \"object\"\n                    ? {\n                        description:\n                          typeof example.description === \"string\"\n                            ? example.description\n                            : \"\",\n                        fift:\n                          typeof example.fift === \"string\" ? example.fift : \"\",\n                      }\n                    : null\n                )\n                .filter((example) =>\n                  example && (example.description || example.fift)\n                )\n            : [],\n          gas: doc.gas || \"\",\n          gasDisplay: formatGasDisplay(doc.gas),\n          stackDoc: doc.stack || \"\",\n          opcode,\n          tlb: bytecode.tlb || \"\",\n          operands: Array.isArray(bytecode.operands) ? bytecode.operands : [],\n          valueFlow: {\n            inputs,\n            outputs,\n          },\n          registers: {\n            inputs: registersIn,\n            outputs: registersOut,\n          },\n          controlFlow: raw.control_flow || null,\n          implementationRefs,\n          rawSpec: raw,\n          aliases: aliasByMnemonic.get(raw.mnemonic) || [],\n          missing: {\n            description: descriptionMissing,\n            gas: gasMissing,\n            tlb: tlbMissing,\n            stackDoc: stackDocMissing,\n            inputs: inputsMissing,\n            outputs: outputsMissing,\n            implementation: implementationMissing,\n            controlFlow: controlFlowMissing,\n          },\n        };\n      }\n    );\n  }, [spec]);\n\n  const anchorInstruction = useMemo(() => {\n    if (!activeAnchorId) return null;\n    return instructions.find((item) => item.anchorId === activeAnchorId) || null;\n  }, [instructions, activeAnchorId]);\n\n  useEffect(() => {\n    if (!anchorInstruction) return;\n    setExpanded((prev) => {\n      if (prev[anchorInstruction.uid]) return prev;\n      return {\n        ...prev,\n        [anchorInstruction.uid]: true,\n      };\n    });\n  }, [anchorInstruction]);\n\n  useEffect(() => {\n    if (!anchorInstruction) return;\n    if (typeof document === \"undefined\" || typeof window === \"undefined\") return;\n    if (!anchorInstruction.anchorId) return;\n    const frame =\n      typeof window.requestAnimationFrame === \"function\"\n        ? window.requestAnimationFrame.bind(window)\n        : (cb) => setTimeout(cb, 0);\n    frame(() => {\n      const element = document.getElementById(anchorInstruction.anchorId);\n      if (element && typeof element.scrollIntoView === \"function\") {\n        element.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\n      }\n    });\n  }, [anchorInstruction]);\n\n  const subcategoryMap = useMemo(() => {\n    const groups = new Map();\n    instructions.forEach((item) => {\n      if (!item || !item.categoryKey) return;\n      const groupKey = item.categoryKey;\n      const rawKey = item.rawCategoryKey || \"uncategorized\";\n      const label = item.rawCategoryLabel || humanizeCategoryKey(rawKey);\n      if (!groups.has(groupKey)) {\n        groups.set(groupKey, new Map());\n      }\n      const entries = groups.get(groupKey);\n      if (!entries.has(rawKey)) {\n        entries.set(rawKey, {\n          value: rawKey,\n          label,\n          count: 0,\n        });\n      }\n      const record = entries.get(rawKey);\n      record.count += 1;\n      if (!record.label && label) {\n        record.label = label;\n      }\n    });\n    const normalized = new Map();\n    groups.forEach((entries, key) => {\n      const list = Array.from(entries.values()).sort((a, b) =>\n        a.label.localeCompare(b.label)\n      );\n      normalized.set(key, list);\n    });\n    return normalized;\n  }, [instructions]);\n\n  const categoryOptions = useMemo(() => {\n    const present = new Set(subcategoryMap.keys());\n    const ordered = CATEGORY_GROUPS.filter((group) => present.has(group.key)).map(\n      (group) => ({ value: group.key, label: group.label })\n    );\n    return [\n      { value: \"All\", label: \"All categories\" },\n      ...ordered,\n    ];\n  }, [subcategoryMap]);\n\n  const currentSubcategoryOptions = useMemo(() => {\n    if (category === \"All\") return [];\n    return subcategoryMap.get(category) || [];\n  }, [subcategoryMap, category]);\n\n  const showSubcategorySelect =\n    category !== \"All\" && currentSubcategoryOptions.length > 1;\n\n  useEffect(() => {\n    if (category === \"All\") return;\n    const hasSelection = categoryOptions.some(\n      (option) => option.value === category\n    );\n    if (!hasSelection) {\n      setCategory(\"All\");\n    }\n  }, [categoryOptions, category]);\n\n  useEffect(() => {\n    if (category === \"All\") {\n      if (subcategory !== \"All\") {\n        setSubcategory(\"All\");\n      }\n      return;\n    }\n    const options = currentSubcategoryOptions;\n    if (!options || options.length <= 1) {\n      if (subcategory !== \"All\") {\n        setSubcategory(\"All\");\n      }\n      return;\n    }\n    const hasSubcategory = options.some((option) => option.value === subcategory);\n    if (!hasSubcategory) {\n      setSubcategory(\"All\");\n    }\n  }, [category, subcategory, currentSubcategoryOptions]);\n\n  const filtered = useMemo(() => {\n    const forcedUid = anchorInstruction?.uid ?? null;\n    return instructions.filter((item) => {\n      if (forcedUid && item.uid === forcedUid) return true;\n      if (category !== \"All\" && item.categoryKey !== category) return false;\n      if (\n        category !== \"All\" &&\n        subcategory !== \"All\" &&\n        item.rawCategoryKey !== subcategory\n      ) {\n        return false;\n      }\n      return itemRelevanceScore(item, searchTokens) !== Infinity;\n    });\n  }, [\n    instructions,\n    category,\n    subcategory,\n    searchTokens,\n    anchorInstruction,\n  ]);\n\n  const sorted = useMemo(() => {\n    const copy = filtered.slice();\n    const hasQuery = searchTokens.length > 0;\n    if (hasQuery) {\n      const tokens = searchTokens;\n      copy.sort((a, b) => {\n        const sa = itemRelevanceScore(a, tokens);\n        const sb = itemRelevanceScore(b, tokens);\n        if (sa !== sb) return sa - sb;\n        // tie-breakers\n        return (\n          a.mnemonic.localeCompare(b.mnemonic) ||\n          compareOpcodes(a.opcode, b.opcode)\n        );\n      });\n    } else if (sortMode !== \"opcode\") {\n      copy.sort((a, b) => {\n        switch (sortMode) {\n          case \"name\":\n            return a.mnemonic.localeCompare(b.mnemonic);\n          case \"category\":\n            return (\n              a.categoryLabel.localeCompare(b.categoryLabel) ||\n              a.opcode.localeCompare(b.opcode)\n            );\n          case \"since\":\n            return (b.since == 9999 ? -1 : b.since) -  (a.since == 9999 ? -1 : a.since);\n          default:\n            return (\n              compareOpcodes(a.opcode, b.opcode) ||\n              a.mnemonic.localeCompare(b.mnemonic)\n            );\n        }\n      });\n    }\n\n    const forcedUid = anchorInstruction?.uid ?? null;\n    if (forcedUid) {\n      let forcedItem = null;\n      const forcedIndex = copy.findIndex((item) => item.uid === forcedUid);\n      if (forcedIndex >= 0) {\n        [forcedItem] = copy.splice(forcedIndex, 1);\n      } else if (anchorInstruction) {\n        forcedItem = anchorInstruction;\n      }\n      if (forcedItem) {\n        copy.unshift(forcedItem);\n      }\n    }\n\n    return copy;\n  }, [filtered, sortMode, searchTokens, anchorInstruction]);\n\n  const hasActiveFilters = useMemo(\n    () =>\n      searchTokens.length > 0 ||\n      category !== \"All\" ||\n      subcategory !== \"All\" ||\n      sortMode !== \"opcode\",\n    [searchTokens, category, subcategory, sortMode]\n  );\n\n  const handleResetFilters = useCallback(() => {\n    setSearch(\"\");\n    setCategory(\"All\");\n    setSubcategory(\"All\");\n    setSortMode(\"opcode\");\n  }, []);\n\n  const activeFilters = useMemo(() => {\n    const chips = [];\n    const searchDisplay = search.trim();\n    if (searchTokens.length > 0 && searchDisplay) {\n      chips.push({\n        key: \"search\",\n        label: `Query: \"${searchDisplay}\"`,\n        ariaLabel: `Remove search filter ${searchDisplay}`,\n        onRemove: () => setSearch(\"\"),\n      });\n    }\n    if (category !== \"All\") {\n      const match = categoryOptions.find((option) => option.value === category);\n      const label = match ? match.label : humanizeCategoryKey(category);\n      chips.push({\n        key: \"category\",\n        label: `Category: ${label}`,\n        ariaLabel: `Remove category filter ${label}`,\n        onRemove: () => setCategory(\"All\"),\n      });\n    }\n    if (category !== \"All\" && subcategory !== \"All\") {\n      const match = currentSubcategoryOptions.find(\n        (option) => option.value === subcategory\n      );\n      const label = match ? match.label : humanizeCategoryKey(subcategory);\n      chips.push({\n        key: \"subcategory\",\n        label: `Subcategory: ${label}`,\n        ariaLabel: `Remove subcategory filter ${label}`,\n        onRemove: () => setSubcategory(\"All\"),\n      });\n    }\n    if (sortMode !== \"opcode\") {\n      const sortLabels = {\n        since: \"Newest\",\n      };\n      const label = sortLabels[sortMode] || \"Opcode\";\n      chips.push({\n        key: \"sort\",\n        label: `Sort: ${label}`,\n        ariaLabel: `Remove sort override ${label}`,\n        onRemove: () => setSortMode(\"opcode\"),\n      });\n    }\n    return chips;\n  }, [\n    searchTokens,\n    search,\n    category,\n    subcategory,\n    categoryOptions,\n    currentSubcategoryOptions,\n    sortMode,\n    setSearch,\n    setCategory,\n    setSubcategory,\n    setSortMode,\n  ]);\n\n  const toggleRow = useCallback((uid) => {\n    setExpanded((prev) => ({\n      ...prev,\n      [uid]: !prev[uid],\n    }));\n  }, []);\n\n  const openRawJsonModal = useCallback(\n    (instruction) => {\n      if (!instruction) return;\n      const payload = {\n        mnemonic: instruction.mnemonic,\n        opcode: instruction.opcode,\n        anchorId: instruction.anchorId,\n        raw: instruction.rawSpec || instruction,\n      };\n      setRawModalInstruction(payload);\n      setRawModalCopied(false);\n      if (rawModalCopyTimeoutRef.current) {\n        clearTimeout(rawModalCopyTimeoutRef.current);\n        rawModalCopyTimeoutRef.current = null;\n      }\n    },\n    []\n  );\n\n  const closeRawJsonModal = useCallback(() => {\n    setRawModalInstruction(null);\n    setRawModalCopied(false);\n    if (rawModalCopyTimeoutRef.current) {\n      clearTimeout(rawModalCopyTimeoutRef.current);\n      rawModalCopyTimeoutRef.current = null;\n    }\n  }, []);\n\n  const handleCopyRawJson = useCallback((jsonText) => {\n    copyPlainText(jsonText)\n      .then(() => {\n        setRawModalCopied(true);\n        if (rawModalCopyTimeoutRef.current) {\n          clearTimeout(rawModalCopyTimeoutRef.current);\n        }\n        rawModalCopyTimeoutRef.current = setTimeout(() => {\n          setRawModalCopied(false);\n          rawModalCopyTimeoutRef.current = null;\n        }, 1500);\n      })\n      .catch(() => {\n        // ignore clipboard failures\n      });\n  }, []);\n\n  useEffect(() => {\n    if (!rawModalInstruction) return;\n    if (typeof window === \"undefined\") return;\n    const handleKeyDown = (event) => {\n      if (event.defaultPrevented) return;\n      if (event.key === \"Escape\") {\n        event.preventDefault();\n        closeRawJsonModal();\n      }\n    };\n    window.addEventListener(\"keydown\", handleKeyDown);\n    return () => window.removeEventListener(\"keydown\", handleKeyDown);\n  }, [rawModalInstruction, closeRawJsonModal]);\n\n  const rawModalJson = useMemo(() => {\n    if (!rawModalInstruction) return \"\";\n    try {\n      return JSON.stringify(rawModalInstruction.raw ?? null, null, 2);\n    } catch (err) {\n      return \"// Failed to serialize instruction\";\n    }\n  }, [rawModalInstruction]);\n\n  useEffect(() => {\n    return () => {\n      if (rawModalCopyTimeoutRef.current) {\n        clearTimeout(rawModalCopyTimeoutRef.current);\n        rawModalCopyTimeoutRef.current = null;\n      }\n    };\n  }, []);\n\n  return (\n    <div className=\"tvm-instruction-app\">\n      <style>{tableStyles}</style>\n\n      <div className=\"tvm-instruction-toolbar\">\n        <div className=\"tvm-toolbar-search\">\n          <div className=\"tvm-field tvm-field--search\">\n            <label htmlFor=\"tvm-search\">Search</label>\n            <div className=\"tvm-search-row\">\n              <div className=\"tvm-search-input\">\n                <span className=\"tvm-search-icon\" aria-hidden=\"true\">\n                  <svg\n                    viewBox=\"0 0 24 24\"\n                    fill=\"none\"\n                    xmlns=\"http://www.w3.org/2000/svg\"\n                  >\n                    <circle\n                      cx=\"11\"\n                      cy=\"11\"\n                      r=\"6\"\n                      stroke=\"currentColor\"\n                      strokeWidth=\"2\"\n                    />\n                    <path\n                      d=\"M20 20l-3.5-3.5\"\n                      stroke=\"currentColor\"\n                      strokeWidth=\"2\"\n                      strokeLinecap=\"round\"\n                    />\n                  </svg>\n                </span>\n                <input\n                  id=\"tvm-search\"\n                  type=\"search\"\n                  placeholder=\"Find by mnemonic, opcode, description…\"\n                  value={search}\n                  onChange={(event) => setSearch(event.currentTarget.value)}\n                  ref={searchInputRef}\n                />\n                {search && (\n                  <button\n                    type=\"button\"\n                    className=\"tvm-clear-search\"\n                    onClick={() => setSearch(\"\")}\n                    aria-label=\"Clear search\"\n                  >\n                    <svg\n                      viewBox=\"0 0 24 24\"\n                      fill=\"none\"\n                      xmlns=\"http://www.w3.org/2000/svg\"\n                    >\n                      <path\n                        d=\"M15 9l-6 6\"\n                        stroke=\"currentColor\"\n                        strokeWidth=\"2\"\n                        strokeLinecap=\"round\"\n                      />\n                      <path\n                        d=\"M9 9l6 6\"\n                        stroke=\"currentColor\"\n                        strokeWidth=\"2\"\n                        strokeLinecap=\"round\"\n                      />\n                    </svg>\n                  </button>\n                )}\n              </div>\n              <div className=\"tvm-toolbar-utilities\">\n                <button\n                  type=\"button\"\n                  className=\"tvm-button tvm-button--ghost\"\n                  onClick={handleResetFilters}\n                  disabled={!hasActiveFilters}\n                >\n                  Reset filters\n                </button>\n              </div>\n            </div>\n          </div>\n        </div>\n\n        <div className=\"tvm-toolbar-filters\">\n          <div className=\"tvm-field tvm-field--sort\">\n            <label htmlFor=\"tvm-sort\">Sort</label>\n            <select\n              id=\"tvm-sort\"\n              value={sortMode}\n              onChange={(event) => setSortMode(event.currentTarget.value)}\n            >\n              <option value=\"opcode\">Opcode</option>\n              <option value=\"since\">Newest</option>\n            </select>\n          </div>\n\n          <div className=\"tvm-field tvm-field--category\">\n            <label htmlFor=\"tvm-category\">Category</label>\n            <select\n              id=\"tvm-category\"\n              value={category}\n              onChange={(event) => setCategory(event.currentTarget.value)}\n            >\n              {categoryOptions.map((option) => (\n                <option key={option.value} value={option.value}>\n                  {option.label}\n                </option>\n              ))}\n            </select>\n          </div>\n\n          {showSubcategorySelect && (\n            <div className=\"tvm-field tvm-field--subcategory\">\n              <label htmlFor=\"tvm-subcategory\">Subcategory</label>\n              <select\n                id=\"tvm-subcategory\"\n                value={subcategory}\n                onChange={(event) => setSubcategory(event.currentTarget.value)}\n              >\n                <option value=\"All\">All subcategories</option>\n                {currentSubcategoryOptions.map((option) => (\n                  <option key={option.value} value={option.value}>\n                    {option.label}\n                  </option>\n                ))}\n              </select>\n            </div>\n          )}\n        </div>\n      </div>\n\n      <div className=\"tvm-instruction-meta\">\n        <div className=\"tvm-meta-items\">\n          {loading && <span className=\"tvm-meta-item\">Loading specification…</span>}\n          {error && !loading && (\n            <span className=\"tvm-meta-item\">Failed to load specification.</span>\n          )}\n          {!loading && !error && (\n            <span className=\"tvm-meta-item\">\n              Showing {sorted.length} of {instructions.length} instructions\n            </span>\n          )}\n        </div>\n        {activeFilters.length > 0 && (\n          <div className=\"tvm-meta-chips\" aria-live=\"polite\">\n            {activeFilters.map(({ key, label, ariaLabel, onRemove }) => (\n              <button\n                key={key}\n                type=\"button\"\n                className=\"tvm-meta-chip\"\n                onClick={onRemove}\n                aria-label={ariaLabel || `Remove filter ${label}`}\n                title={label}\n              >\n                <span className=\"tvm-meta-chip-label\">{label}</span>\n                <span className=\"tvm-meta-chip-close\" aria-hidden=\"true\">\n                  ×\n                </span>\n              </button>\n            ))}\n          </div>\n        )}\n      </div>\n\n      <div className=\"tvm-spec-grid-container\">\n        <div className=\"tvm-spec-grid-scroll\">\n          <div className=\"tvm-spec-header\" role=\"row\">\n            <div>Link</div>\n            <div>Opcode</div>\n            <div>Instruction</div>\n            <div>Description</div>\n          </div>\n\n          {error && <div className=\"tvm-error-row\">{error}</div>}\n\n          {!error && (\n            <>\n              {loading && (\n                <div className=\"tvm-loading-row\">Loading specification…</div>\n              )}\n              {!loading && sorted.length === 0 && (\n                <div className=\"tvm-empty-row\">\n                  No instructions match the filters.\n                </div>\n              )}\n              {!loading &&\n                sorted.flatMap((instruction) => {\n                  const isExpanded = Boolean(expanded[instruction.uid]);\n                  const aliasCount = Array.isArray(instruction.aliases)\n                    ? instruction.aliases.length\n                    : 0;\n                  const detailId = `tvm-detail-${instruction.uid}`;\n                  const anchorId = instruction.anchorId || buildAnchorId(instruction);\n                  const isAnchorTarget =\n                    anchorInstruction && anchorInstruction.uid === instruction.uid;\n                  const rowClassName = [\n                    \"tvm-spec-row\",\n                    isExpanded ? \"is-expanded\" : \"\",\n                    isAnchorTarget ? \"is-anchor-target\" : \"\",\n                  ]\n                    .filter(Boolean)\n                    .join(\" \");\n                  const descriptionHtml = highlightHtmlContent(\n                    instruction.descriptionHtml || instruction.description || \"\",\n                    searchTokens\n                  );\n\n                  const nodes = [\n                    <div\n                      key={instruction.uid}\n                      id={anchorId}\n                      className={rowClassName}\n                      role=\"button\"\n                      tabIndex={0}\n                      aria-expanded={isExpanded}\n                      aria-controls={detailId}\n                      onClick={() => toggleRow(instruction.uid)}\n                      onKeyDown={(event) => {\n                        if (event.key === \"Enter\" || event.key === \" \") {\n                          event.preventDefault();\n                          toggleRow(instruction.uid);\n                        }\n                      }}\n                    >\n                      <div className=\"tvm-spec-cell tvm-spec-cell--anchor\">\n                        <button\n                          type=\"button\"\n                          className={`tvm-copy-link ${copied[instruction.uid] ? \"is-copied\" : \"\"}`}\n                          aria-label={copied[instruction.uid] ? \"Copied\" : \"Copy link to instruction\"}\n                          onClick={(e) => {\n                            e.stopPropagation();\n                            copyAnchorUrl(anchorId)\n                              .then(() => {\n                                setCopied((prev) => ({ ...prev, [instruction.uid]: true }));\n                                setTimeout(() => {\n                                  setCopied((prev) => {\n                                    const { [instruction.uid]: _omit, ...rest } = prev;\n                                    return rest;\n                                  });\n                                }, 1500);\n                              })\n                              .catch(() => {\n                                // ignore\n                              });\n                          }}\n                          title={copied[instruction.uid] ? \"Copied\" : \"Copy link\"}\n                        >\n                          {copied[instruction.uid] ? (\n                            <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n                              <path d=\"M20 6L9 17l-5-5\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/>\n                            </svg>\n                          ) : (\n                            <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n                              <path d=\"M10.59 13.41a1.996 1.996 0 0 0 2.82 0l3.59-3.59a2 2 0 0 0-2.83-2.83l-1.17 1.17\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/>\n                              <path d=\"M13.41 10.59a1.996 1.996 0 0 0-2.82 0L7 14.18a2 2 0 1 0 2.83 2.83l1.17-1.17\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"/>\n                            </svg>\n                          )}\n                        </button>\n                      </div>\n                      <div className=\"tvm-spec-cell tvm-spec-cell--opcode\">\n                        <code>\n                          {highlightMatches(\n                            instruction.opcode || \"—\",\n                            searchTokens\n                          )}\n                        </code>\n                      </div>\n                      <div className=\"tvm-spec-cell tvm-spec-cell--name\">\n                        <div className=\"tvm-name-line\">\n                          <span className=\"tvm-mnemonic\">\n                            {highlightMatches(\n                              instruction.mnemonic,\n                              searchTokens\n                            )}\n                          </span>\n                          {instruction.since > 0 && (\n                            <span className=\"tvm-inline-badge\">\n                              {instruction.since != 9999 ? `since v${instruction.since}` : 'unimplemented yet' }\n                            </span>\n                          )}\n                          {aliasCount > 0 && (\n                            <span className=\"tvm-inline-badge tvm-inline-badge--muted\">\n                              {aliasCount} alias{aliasCount > 1 ? \"es\" : \"\"}\n                            </span>\n                          )}\n                          <span\n                            className={`tvm-row-indicator ${\n                              isExpanded ? \"is-expanded\" : \"\"\n                            }`}\n                            aria-hidden=\"true\"\n                          >\n                            <svg\n                              viewBox=\"0 0 24 24\"\n                              fill=\"none\"\n                              xmlns=\"http://www.w3.org/2000/svg\"\n                            >\n                              <path\n                                d=\"M6 9l6 6 6-6\"\n                                stroke=\"currentColor\"\n                                strokeWidth=\"2\"\n                                strokeLinecap=\"round\"\n                                strokeLinejoin=\"round\"\n                              />\n                            </svg>\n                          </span>\n                        </div>\n                        {instruction.operands.length > 0 && (\n                          <div className=\"tvm-operands\">\n                            {instruction.operands.map((operand, idx) => (\n                              <span key={idx} className=\"tvm-operand-chip\">\n                                {highlightMatches(\n                                  formatOperandSummary(operand),\n                                  searchTokens\n                                )}\n                              </span>\n                            ))}\n                          </div>\n                        )}\n                      </div>\n                      <div className=\"tvm-spec-cell tvm-spec-cell--description\">\n                        {instruction.description || instruction.descriptionHtml ? (\n                          <div\n                            className=\"tvm-description\"\n                            dangerouslySetInnerHTML={{ __html: descriptionHtml }}\n                          />\n                        ) : null}\n                        <div className=\"tvm-description-meta\">\n                          <span className=\"tvm-category-pill\">\n                            {instruction.categoryLabel}\n                          </span>\n                        </div>\n                      </div>\n                    </div>,\n                  ];\n\n                  if (isExpanded) {\n                    nodes.push(\n                      <div\n                        key={`${instruction.uid}-detail`}\n                        className={`tvm-spec-row tvm-spec-row--detail ${\n                          isAnchorTarget ? \"is-anchor-target\" : \"\"\n                        }`}\n                      >\n                        <div\n                          className=\"tvm-spec-cell tvm-spec-cell--full\"\n                          id={detailId}\n                        >\n                          {renderInstructionDetail(instruction, {\n                            isAnchorTarget,\n                            onOpenRawJson: openRawJsonModal,\n                          })}\n                        </div>\n                      </div>\n                    );\n                  }\n\n                  return nodes;\n                })}\n            </>\n          )}\n      </div>\n    </div>\n\n      {rawModalInstruction && (\n        <div\n          className=\"tvm-modal\"\n          role=\"dialog\"\n          aria-modal=\"true\"\n          aria-labelledby=\"tvm-raw-json-title\"\n        >\n          <div className=\"tvm-modal-backdrop\" onClick={closeRawJsonModal} />\n          <div\n            className=\"tvm-modal-dialog\"\n            role=\"document\"\n            onClick={(event) => event.stopPropagation()}\n          >\n            <div className=\"tvm-modal-header\">\n              <div className=\"tvm-modal-header-text\">\n                <h3 id=\"tvm-raw-json-title\">Raw instruction JSON</h3>\n                <p className=\"tvm-modal-subtitle\">\n                  {rawModalInstruction.opcode ? (\n                    <>\n                      <code>{rawModalInstruction.opcode}</code>\n                      {\" \"}\n                    </>\n                  ) : null}\n                  {rawModalInstruction.mnemonic}\n                </p>\n              </div>\n              <div className=\"tvm-modal-actions\">\n                <button\n                  type=\"button\"\n                  className=\"tvm-button tvm-button--ghost\"\n                  onClick={() => handleCopyRawJson(rawModalJson)}\n                >\n                  {rawModalCopied ? \"Copied\" : \"Copy JSON\"}\n                </button>\n                <button\n                  type=\"button\"\n                  className=\"tvm-button\"\n                  onClick={closeRawJsonModal}\n                >\n                  Close\n                </button>\n              </div>\n            </div>\n            <pre className=\"tvm-modal-code\">{rawModalJson}</pre>\n          </div>\n        </div>\n      )}\n    </div>\n  );\n};\n\nexport default TvmInstructionTable;\n"
  },
  {
    "path": "standard/tokens/airdrop.mdx",
    "content": "---\ntitle: \"Airdrop\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\nimport { Image } from '/snippets/image.jsx';\n\n## The problem: distributing at scale\n\nRewarding thousands (or millions) of users by sending assets to each address proactively looks simple until the network fees add up. Network fees scale fast when the sender pays for every transfer.\n\n## The twist: let users claim\n\nAn airdrop flips the model. Instead of the distributor paying all fees, each eligible user claims their allocation and covers the network fees themselves.\n\nThe straightforward approach is to keep a precomputed mapping of recipient → allocation in the contract. When a user sends a claim message, the contract releases the preassigned drop for that user.\n\n<Image\n  src=\"/resources/images/claim_light.png\"\n  darkSrc=\"/resources/images/claim_dark.png\"\n  alt=\"User claims allocation from airdrop contract\"\n/>\n\n## The naive approach and its limit\n\nKeep a precomputed mapping of recipient → allocation in the contract. When a user sends a claim message, the contract releases the preassigned amount. This works until the list becomes too large. Starting at roughly 3,000 entries, problems begin to surface with the external limit (see more in [limits](/foundations/limits#message-and-transaction-limits)).\n\n## Scalable airdrop architecture\n\nA scalable airdrop consists of two independent modules:\n\n1. Double-claim prevention ensures each user can claim only once\n1. Eligibility verification proves the user is entitled to claim a specific drop\n\nThese modules are independent and can be combined in different ways.\n\n### Double-claim prevention\n\n#### Markers\n\nThe airdrop has a small per-user marker contract that records whether the user has already claimed. This marker blocks any subsequent attempts.\n\n### Eligibility verification\n\n#### Merkle proof\n\nThe airdrop contract stores a root hash of a dictionary (see [hashmap](/languages/tl-b/complex-and-non-trivial-examples#hashmap)) containing all allocations. Users present a [Merkle proof](/foundations/proofs/overview) to verify their allocation against this root.\n\nOn-chain state:\n\n- Root hash (256 bits)\n\nHow to prepare:\n\n1. Prepare a list of eligible recipients and their allocations, and construct a dictionary.\n1. Store the root hash in the airdrop contract.\n1. Provide each user with their Merkle proof.\n\n#### Signed proof\n\nThe airdrop contract stores a backend public key. The backend signs authorization messages for eligible users. Users present the signature to claim.\n\nOn-chain state:\n\n- Backend public key (256 bits)\n\nHow to prepare:\n\n1. Deploy airdrop contract with backend public key.\n1. Backend validates eligibility criteria on demand.\n1. Backend signs authorization messages for eligible users.\n\nFor signature implementation details and security considerations, see [signing messages](/contract-dev/signing).\n\n### Claim flow\n\nThe claim process combines both modules.\n\n1. User sends a message that deploys their marker contract along with proof.\n1. Marker contract checks it has not been deployed before (double-claim prevention).\n1. Airdrop contract verifies proof (eligibility verification).\n1. Airdrop contract transfers assets to recipient.\n\n<Image\n  src=\"/resources/images/airdrop-light.png\"\n  darkSrc=\"/resources/images/airdrop-dark.png\"\n  alt=\"Airdrop claim flow\"\n/>\n\n### Choosing an approach\n\nMerkle proof fits when:\n\n- Trustless, verifiable distribution is required.\n- Eligibility list is static or changes infrequently.\n- Backend control over claims is not desired.\n\nSigned authorization fits when:\n\n- Eligibility rules change frequently or depend on external data.\n- Trust in the backend is acceptable (centralized projects, known organizations).\n- Lower gas costs per claim are a priority.\n\n## Examples\n\n- [cNFT](/standard/tokens/nft/comparison#cnft)\n- [Mintless Jetton](/standard/tokens/jettons/mintless/overview)\n"
  },
  {
    "path": "standard/tokens/jettons/api.mdx",
    "content": "---\ntitle: \"API\"\n---\n\nThis page describes all messages and methods related to Jetton processing that are specified in TEPs.\n\n## [TEP 0074](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md)\n\n### Transfer message layout\n\n| Field                  | Type                | Description                                                                                                              |\n| :--------------------- | :------------------ | :----------------------------------------------------------------------------------------------------------------------- |\n| `transfer`             | `0x0f8a7ea5`        | tag                                                                                                                      |\n| `query_id`             | `uint64`            | arbitrary request number                                                                                                 |\n| `amount`               | `VarUInteger 16`    | amount of transferred jettons in elementary units                                                                        |\n| `destination`          | `MsgAddress`        | address of the new owner of the jettons                                                                                  |\n| `response_destination` | `MsgAddress`        | address where to send a response with confirmation of a successful transfer and the rest of the incoming message Toncoin |\n| `custom_payload`       | `Maybe ^Cell`       | optional custom data (which is used by either sender or receiver jetton wallet for inner logic)                          |\n| `forward_ton_amount`   | `VarUInteger 16`    | the amount of nanotons to be sent to the destination address                                                             |\n| `forward_payload`      | `Either Cell ^Cell` | optional custom data that should be sent to the destination address                                                      |\n\n### Forward payload formats\n\nIf you want to send a simple comment in the `forward_payload`, then the `forward_payload` must start with `0x00000000` (32-bit unsigned integer equals to zero) and the comment is contained in the remainder of the `forward_payload`.\n\nIf the comment does not begin with the byte `0xff`, the comment is a text one; it can be displayed \"as is\" to the end user of a wallet (after filtering invalid and control characters and checking that it is a valid UTF-8 string). For instance, users may indicate the purpose (\"for coffee\") of a simple transfer from their wallet to the wallet of another user in this text field.\n\nOn the other hand, if the comment begins with the byte `0xff`, the remainder is a \"binary comment\", which should not be displayed to the end user as text (only as a hex dump if necessary). The intended use of \"binary comments\" is, e.g., to contain a purchase identifier for payments in a store, to be automatically generated and processed by the store's software.\n\nIf the `forward_payload` contains a binary message for interacting with the destination smart contract (for example, with DEX), then there are no prefixes.\n\n### Transfer notification message layout\n\n| Field                   | Type                | Description                                             |\n| ----------------------- | ------------------- | ------------------------------------------------------- |\n| `transfer_notification` | `0x7362d09c`        | tag                                                     |\n| `query_id`              | `uint64`            | should be equal with request's `query_id`               |\n| `amount`                | `VarUInteger 16`    | amount of transferred jettons                           |\n| `sender`                | `MsgAddress`        | an address of the previous owner of transferred jettons |\n| `forward_payload`       | `Either Cell ^Cell` | should be equal with request's `forward_payload`        |\n\n### Excesses message layout\n\n| Field      | Type         | Description                               |\n| ---------- | ------------ | ----------------------------------------- |\n| `excesses` | `0xd53276db` | tag                                       |\n| `query_id` | `uint64`     | should be equal with request's `query_id` |\n\n### Burn message layout\n\n| Field                  | Type             | Description                                                                                                           |\n| ---------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------- |\n| `burn`                 | `0x595f07bc`     | tag                                                                                                                   |\n| `query_id`             | `uint64`         | arbitrary request number                                                                                              |\n| `amount`               | `VarUInteger 16` | amount of burned jettons                                                                                              |\n| `response_destination` | `MsgAddress`     | an address where to send a response with confirmation of a successful burn and the rest of the incoming message coins |\n| `custom_payload`       | `Maybe ^Cell`    | optional custom data                                                                                                  |\n\n### get\\_wallet\\_data()\n\nNo arguments. Outputs:\n\n| Field                | Type             | Description                          |\n| -------------------- | ---------------- | ------------------------------------ |\n| `balance`            | `VarUInteger 16` | amount of jettons on wallet          |\n| `owner`              | `MsgAddress`     | an address of wallet owner           |\n| `jetton`             | `MsgAddress`     | an address of Jetton master contract |\n| `jetton_wallet_code` | `Cell`           | code of this wallet                  |\n\n### get\\_jetton\\_data()\n\nNo arguments. Outputs:\n\n| Field                | Type             | Description                                                        |\n| -------------------- | ---------------- | ------------------------------------------------------------------ |\n| `total_supply`       | `VarUInteger 16` | the total number of issues jettons                                 |\n| `mintable`           | `Bool`           | (-1/0) flag which indicates whether number of jettons can increase |\n| `admin_address`      | `MsgAddress`     | an address of smart contract that controls Jetton                  |\n| `jetton_content`     | `Cell`           | data in accordance to TEP 0064                                     |\n| `jetton_wallet_code` | `Cell`           | code of wallet for that jetton                                     |\n\n### get\\_wallet\\_address()\n\nArgument: `owner_address` as `MsgAddress`.\n\nOutput: `jetton_wallet_address`as `MsgAddress`.\n\n## [TEP 0089](https://github.com/ton-blockchain/TEPs/blob/master/text/0089-jetton-wallet-discovery.md)\n\n### Provide wallet address message layout\n\n| Field                    | Type         | Description                                                    |\n| ------------------------ | ------------ | -------------------------------------------------------------- |\n| `provide_wallet_address` | `0x2c76b973` | tag                                                            |\n| `query_id`               | `uint64`     | arbitrary request number                                       |\n| `owner_address`          | `MsgAddress` | owner's address of Jetton wallet of interest                   |\n| `include_address`        | `Bool`       | whether to include the owner's address in the outgoing message |\n\n### Take wallet address message layout\n\n| Field                 | Type                | Description                                            |\n| --------------------- | ------------------- | ------------------------------------------------------ |\n| `take_wallet_address` | `0xd1735400`        | tag                                                    |\n| `query_id`            | `uint64`            | arbitrary request number                               |\n| `wallet_address`      | `MsgAddress`        | an address of Jetton wallet of interest                |\n| `owner_address`       | `Maybe ^MsgAddress` | optional: owner's address of Jetton wallet of interest |\n"
  },
  {
    "path": "standard/tokens/jettons/burn.mdx",
    "content": "---\ntitle: \"Burn\"\n---\n\nimport { Image } from '/snippets/image.jsx';\nimport { Aside } from \"/snippets/aside.jsx\";\n\nBurning is a process of reducing supply of a certain Jetton, mostly in order to create [deflation](https://en.wikipedia.org/wiki/Deflation).\n\n## Web services\n\nTo burn Jettons manually, use a web service, for example [Minter](https://minter.ton.org/):\n\n- Connect your wallet using TON Connect.\n- Enter the Jetton master contract address into the \"Jetton address\" field.\n- Click the \"Burn\" button in your wallet's balance field and enter the amount you want to burn.\n- Confirm burning in your wallet application.\n\n<Image\n  src=\"/resources/images/burning-ton-minter.png\"\n  darkSrc=\"/resources/images/burning-ton-minter.png\"\n  alt=\"Burning\"\n/>\n\n## Another approach\n\nAn alternative way to burn tokens is to send them to a [\"zero\" account](https://tonviewer.com/UQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKZ), see [How to transfer](/standard/tokens/jettons/transfer) page. A wallet app can be used for this.\n\n## Programmatically\n\nIn more complex cases, it is usually done with an SDK (for example, [`assets-sdk`](https://github.com/ton-community/assets-sdk)) that handles low-level message serialization details. The provided example uses TON Center API. You'll need a mnemonic of a wallet that will pay for the burn. `JETTON_WALLET_ADDR` stands for the Jetton wallet that holds tokens that will be burned.\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  Beware that API keys and mnemonic must not be committed or shared publicly.\n\n  A better approach is to use a `.env` file that is excluded from repository with `.gitignore`. For GitHub CI purposes, consult [their documentation](https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets).\n</Aside>\n\n```typescript\nimport { Address, toNano, WalletContractV5R1, TonClient } from \"@ton/ton\";\nimport { mnemonicToPrivateKey } from \"@ton/crypto\";\nimport { AssetsSDK, createApi } from \"@ton-community/assets-sdk\";\n\nconst NETWORK = \"testnet\";\n// a list of 24 space-separated words\nconst MNEMONIC = \"foo bar baz ...\";\nconst JETTON_WALLET_ADDR = Address.parse(\"<JETTON_WALLET_ADDR>\");\n\nasync function main() {\n    // create an RPC client that will send network requests\n    const client = new TonClient({\n        endpoint: \"https://toncenter.com/api/v2/jsonRPC\",\n    });\n\n    // extract private and public keys from the mnemonic\n    const keyPair = await mnemonicToPrivateKey(MNEMONIC.split(\" \"));\n\n    // create a client for TON wallet\n    const wallet = WalletContractV5R1.create({\n        workchain: 0,\n        // public key is required to deploy a new wallet\n        // if it wasn't deployed yet\n        publicKey: keyPair.publicKey,\n    });\n\n    const provider = client.provider(wallet.address);\n\n    // sender is an object used by assets-sdk to send messages\n    // private key is used to sign messages sent to a wallet\n    const sender = wallet.sender(provider, keyPair.secretKey);\n\n    // create an assets-sdk client\n    const api = await createApi(NETWORK);\n    const sdk = AssetsSDK.create({\n        api,\n        sender,\n    });\n\n    // create a client for interacting with given jetton wallet\n    const jetton = sdk.openJettonWallet(JETTON_WALLET_ADDR);\n\n    // burn 1200000 jettons\n    await jetton.sendBurn(sender, 1200000n);\n}\n\nvoid main();\n```\n"
  },
  {
    "path": "standard/tokens/jettons/comparison.mdx",
    "content": "---\ntitle: \"Jetton comparison\"\nsidebarTitle: \"Comparison\"\n---\n\nThis article will compare different implementations of the TEP-74 standard and explore the best version for each use case.\n\n## In short\n\n[Jetton 2.0](https://github.com/ton-blockchain/jetton-contract/tree/jetton-2.0) is the latest and most optimized Jetton implementation. Unlike previous versions, it deploys Jetton Wallets in the same shardchain as the owner's Toncoin wallet.\n\n## Implementation history\n\n### Jetton 1.0\n\n**Release date**: Apr 18, 2022\n\n[GitHub](https://github.com/ton-blockchain/token-contract/commit/369ae089255edbd807eb499792a0a838c2e1b272)\n\nSince the [initial TEP-74](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md) publication on 12.03.2022, this was the first public Jetton release. It doesn't support Jetton Wallet Discovery ([TEP-89 standard](https://github.com/ton-blockchain/TEPs/blob/master/text/0089-jetton-wallet-discovery.md)) and contains some gas estimation techniques that are now considered bad practice. Overall, this implementation is deprecated and shouldn't be used for any production development.\n\n### Discoverable Jetton\n\n**Release date**: Jan 19, 2023\n\n[GitHub](https://github.com/ton-blockchain/token-contract/commit/f2253cb0f0e1ae0974d7dc0cef3a62cb6e19f806)\n\nFor a long time, this version was the most widely adopted in the community. The [minter.ton.org](https://minter.ton.org/) UI mint tool deploys Jettons with this code. It contains the necessary minimum feature-wise, but isn't optimized for the latest TVM and blockchain changes. Also, the repository itself doesn't include any advanced tests and scripts.\n\n### Stablecoin contract\n\n**Release date**: Apr 14, 2024\n\n[GitHub](https://github.com/ton-blockchain/stablecoin-contract/commit/7a22416d4de61336616960473af391713e100d7b)\n\nWith the USDT release on TON, an advanced version of the Jetton contract was developed. This version introduces many new TVM gas assertion techniques, as well as extended functionality. Since USDT is a centralized asset, there are specific requirements and restrictions for its operations. More specifically, there is no _burn_ opcode, which means that formally, the Governance contract is not TEP-compliant, as Jetton burn functionality is part of the standard. Also, the Minter contract includes a _governance_ mechanism that allows users to perform any actions on other Jetton Wallets.\n\nAnother noticeable advantage of this implementation is extensive testing. All previous versions didn't test edge cases of config changes that will affect storage / forward fees. This test suite became the foundation for all future Jetton versions.\n\n### Notcoin contract\n\n**Release date**: Apr 25, 2024\n\n[GitHub](https://github.com/OpenBuilders/notcoin-contract/commit/c9992514b71f1775cec5df49fbea31a85ddd87f9)\n\nThis version is straightforward - it is a forked Stablecoin contract with removed _governance_ functionality and added burn mechanism. Until recent times, it was the most suitable Jetton for basic on-chain coin use cases.\n\n### Mintless Jetton\n\n**Release date**: Sep 22, 2024\n\n[GitHub](https://github.com/ton-blockchain/mintless-jetton-contract/commit/77763e6b2df6cf96b0840c7306844751200ff046)\n\nDuring the time of massive on-chain project airdrops and CEX listings, there was a demand for a cheap and easy way to distribute initial Jetton tokens. You can read more about the history [here](/standard/tokens/airdrop). This version is also made from the Stablecoin contract with removed governance and allowed burn. It's implemented as a Merkle-proof airdrop, enabling the minting of Jettons directly on the Jetton-Wallet contract in a decentralized manner. The implementation is designed to support large-scale airdrops without incurring high costs or placing a significant load on the blockchain.\n\nTo this day, Mintless Jetton is the only widely known implementation that uses the `custom_payload` field in the original `transfer#0f8a7ea5` TL-B. After the initial claim, each Jetton Wallet can be used as a regular Jetton (which it actually is).\n\nNote that to use Mintless Jetton to its full extent, you will need to cooperate with wallets for additional indexing and payload creation.\n\n### Jetton 2.0\n\n**Release date**: Aug 1, 2025\n\n[GitHub](https://github.com/ton-blockchain/jetton-contract/commit/f2fb1fbb65d8e8ce6ec9f813f3e3dfab9268912a)\n\nThis is the latest Jetton implementation. It utilizes new shardchain optimizations — Jetton Wallet holding a user's token balance is now always deployed in the same shardchain as the owner's wallet. This [became possible](/foundations/messages/deploy#deploying-to-specific-shard) after the TON node introduced functionality to deploy smart contracts into a specific shardchain.\n\nIt makes transfers and operations with [Jetton 2.0](https://github.com/ton-blockchain/jetton-contract/tree/jetton-2.0) up to 3 times faster under heavy network load compared to the previous versions of Jetton. This version is recommended for all new projects working with Jettons.\n"
  },
  {
    "path": "standard/tokens/jettons/find.mdx",
    "content": "---\ntitle: \"How to find Jetton wallet\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\nimport { Image } from '/snippets/image.jsx';\n\nSome applications may want to be able to discover their own or other contract wallets for a specific Jetton Master.\nFor instance, some contracts may want to obtain and store their Jetton wallet for Jetton to handle transfer notifications from it in a specific way.\n\nTo compute the address of a Jetton wallet from the address of its owner (a regular user wallet),\nthe Jetton master contract provides the `get_wallet_address (slice owner_address)` method.\n\n```typescript\nimport { TonClient, Address, beginCell, TupleItemSlice } from \"@ton/ton\";\n\nasync function main() {\n  const client = new TonClient({\n    endpoint: \"https://toncenter.com/api/v2/jsonRPC\",\n  });\n  const jettonMasterAddress = Address.parse(\n    \"put the Jetton master address in any format\",\n  );\n  const walletAddress = Address.parse(\"put owner's address in any format\");\n  const walletAddressCell = beginCell().storeAddress(walletAddress).endCell();\n  // forming the required type for the stack\n  const el: TupleItemSlice = {\n    type: \"slice\",\n    cell: walletAddressCell,\n  };\n  // call the get method with a non-empty stack\n  const data = await client.runMethod(\n    jettonMasterAddress,\n    \"get_wallet_address\",\n    [el],\n  );\n  // get the Jetton wallet address\n  console.log(data.stack.readAddress());\n}\n\nvoid main();\n```\n\nOr if you are sure about the structure of Jetton wallet's initial persistent storage and know its code, you can also manually create [`StateInit`](/foundations/messages/deploy) of the Jetton wallet and thus calculate its address.\n\n<Aside\n  type=\"caution\"\n>\n  Use this method with great care, as the c4 of Jetton wallet contracts is not specified.\n</Aside>\n\n```typescript\nimport {\n  Address,\n  Cell,\n  beginCell,\n  contractAddress,\n  StateInit,\n} from \"@ton/core\";\n\n// let's choose Tether USDT as an example\n\nconst jettonwalletcode = Cell.fromHex(\n  \"b5ee9c72010101010023000842028f452d7a4dfd74066b682365177259ed05734435be76b5fd4bd5d8af2b7c3d68\",\n);\n\nconst masterAddress = Address.parse(\n  \"0:b113a994b5024a16719f69139328eb759596c38a25f59028b146fecdc3621dfe\",\n);\nconst ownerAddress = Address.parse(\"an address in any format\");\nconst jettonwalletdata = beginCell()\n  .storeAddress(ownerAddress)\n  .storeAddress(masterAddress)\n  .storeVarUint(0, 16) // the initial value is always zero\n  .endCell();\n\nconst jettonWalletStateInit: StateInit = {\n  code: jettonwalletcode,\n  data: jettonwalletdata,\n};\n\nconst BASECHAIN = 0; // All Jetton wallet contracts are located in Basechain by default\nconst jettonWalletAddress = contractAddress(BASECHAIN, jettonWalletStateInit);\n\nconsole.log(jettonWalletAddress.toString());\n```\n\nThere are also various web services that allow you to call contract's get methods without writing any code.\nFor example, let's inspect the [Tether USD](https://tonviewer.com/EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs?section=method) master\ncontract page on Tonviewer. Inserting the owner's address in any format and executing the get method, you obtain the Jetton wallet address.\n\n<Image\n  src=\"/resources/images/methods.png\"\n  darkSrc=\"/resources/images/methods.png\"\n  alt=\"Tether USDT master contract\"\n/>\n\nFinally, you can use [built-in APIs](/ecosystem/api/toncenter).\n"
  },
  {
    "path": "standard/tokens/jettons/how-it-works.mdx",
    "content": "---\ntitle: \"How it works\"\n---\n\nimport { Image } from '/snippets/image.jsx';\nimport { Aside } from '/snippets/aside.jsx';\n\nThis article describes the basic ideas and processes behind the implementation of Jettons (aka tokens in Ethereum) in the TON Blockchain.\n\n## Related smart contracts\n\nStandardized tokens on TON (see TEPs [0074](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md)\nand [0089](https://github.com/ton-blockchain/TEPs/blob/master/text/0089-jetton-wallet-discovery.md)) are implemented using a set of\nsmart contracts, including:\n\n- [Jetton master](https://github.com/ton-blockchain/token-contract/blob/main/ft/jetton-minter.fc) (that is also called _Jetton minter_) smart contract;\n- [Jetton wallet](https://github.com/ton-blockchain/token-contract/blob/main/ft/jetton-wallet.fc) smart contract.\n\nIt is important to keep in mind that Jetton standards provide only a general scheme of interaction, leaving the specific implementation of related contracts to developers.\n\n### Jetton master\n\n_Jetton master_ smart contracts store general information about a particular jetton, such as total supply (the total number of tokens of this type),\na metadata link (or the metadata itself), and the code of the standard jetton-wallet smart contract for this jetton. They\nalso have an _owner (admin)_ who, by sending suitable messages to them, [mints new tokens](/standard/tokens/jettons/mint), closes the minting, changes metadata, or transfers the\nadmin rights to another contract.\n\nJetton master contracts also receive notifications about the [burning of tokens](/standard/tokens/jettons/burn).\nWhen they receive such a notification, they must adjust the total supply accordingly.\n\n### Jetton wallet\n\n_Jetton wallet_ smart contracts are used to [transfer](/standard/tokens/jettons/transfer), receive, and [burn](/standard/tokens/jettons/burn) jettons. Each jetton wallet contract stores\nthe wallet balance information for a specific user (owner), the address of the Jetton master contract (for appropriate minting), and some additional information.\nIn certain cases, Jetton wallets are used for individual token holders for each token type.\n\n### Difference between Jetton wallets and regular ones\n\nAlthough both regular wallets and Jetton wallets are smart contracts, there are some significant differences between them.\n\nThe regular wallets' smart contracts are designed for off-chain interaction with their owner. In most implementations, their main purpose is to receive\nexternal messages and perform the operations requested in them. It is through a regular\nwallet that the user sends requests for the transfer of tokens or their burning to the Jetton wallet smart contract.\nThey are designed to store only the native TON Blockchain currency: Toncoin (or TON).\n\nOn the other hand, Jetton wallet smart contracts are designed only for storing and processing tokens. They ignore any external messages and\naccept only special internal ones. They execute commands received only from the Jetton master, another Jetton wallet, or\ntheir owner's regular wallet smart contracts.\n\n## Message layouts\n\nInteractions with Jetton contracts, which users and developers most often encounter, are:\n\n- tokens transfer: sending tokens from one Jetton wallet to another;\n- tokens minting: minting new tokens and transferring them to the Jetton wallet;\n- tokens burning: burn a certain number of tokens on the Jetton wallet contract;\n- wallet address providing: find the address of the Jetton wallet corresponding to a regular wallet.\n\n<Aside\n  type=\"caution\"\n>\n  In all schemes below, you will see the `query id` field. Nowadays, the field is almost deprecated, and the protocol itself doesn't need it.\n  It is mostly used for easier off-chain parsing and other web2 processing.\n</Aside>\n\n### Token transfer\n\n<Image\n  src=\"/resources/images/jettons/transfer_light.png\"\n  darkSrc=\"/resources/images/jettons/transfer_dark.png\"\n  alt=\"Jetton transfer\"\n/>\n\n`Actor A regular wallet -> actor A Jetton wallet`. _Transfer_ message contains the following data:\n\n| Name                   | Type              | Description                                                                                                                                                            |\n| ---------------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `query_id`             | uint64            | Links the three messaging types—transfer, transfer notification, and excesses—to each other. To ensure this process works correctly, **always use a unique query ID**. |\n| `amount`               | VarUInteger 16    | The total jetton amount to transfer.                                                                                                                                   |\n| `destination`          | MsgAddress        | The address of the actor B's regular wallet.                                                                                                                           |\n| `response_destination` | MsgAddress        | The wallet address used to return remaining Toncoin through the excesses message.                                                                                      |\n| `custom_payload`       | Maybe ^Cell       | The optional custom data used by either the sender or receiver jetton wallet for internal logic.                                                                       |\n| `forward_ton_amount`   | VarUInteger 16    | Toncoin to forward to the recipient. Must `> 0` to send a transfer notification with `forward_payload` and must be less than the amount attached to this message.      |\n| `forward_payload`      | Either Cell ^Cell | Optional data. If the first `32` bits equal `0x00000000`, it is a text comment.                                                                                        |\n\nthat meet the TL-B scheme specified in [TEP 0074](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md):\n\n```tlb\ntransfer#0f8a7ea5 query_id:uint64 amount:(VarUInteger 16) destination:MsgAddress\n                 response_destination:MsgAddress custom_payload:(Maybe ^Cell)\n                 forward_ton_amount:(VarUInteger 16) forward_payload:(Either Cell ^Cell)\n                 = InternalMsgBody;\n```\n\n`Actor A Jetton wallet -> actor B Jetton wallet`. _Internal transfer_ message contains the following data:\n\n| Name                   | Type              | Description                                                                                                                                                            |\n| ---------------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `query_id`             | uint64            | Links the three messaging types—transfer, transfer notification, and excesses—to each other. To ensure this process works correctly, **always use a unique query ID**. |\n| `amount`               | VarUInteger 16    | The total jetton amount to transfer.                                                                                                                                   |\n| `sender`               | MsgAddress        | The address of the actor A regular wallet.                                                                                                                             |\n| `response_destination` | Maybe MsgAddress  | The optional wallet address used to return remaining Toncoin through the excesses message.                                                                             |\n| `forward_ton_amount`   | VarUInteger 16    | Toncoin to forward to the recipient. Must `> 0` to send a transfer notification with `forward_payload` and must be less than the amount attached to this message.      |\n| `forward_payload`      | Either Cell ^Cell | Optional data. If the first `32` bits equal `0x00000000`, it is a text comment.                                                                                        |\n\nthat is not specified, but has a recommended TL-B scheme in [TEP 0074](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md):\n\n```tlb\ninternal_transfer#178d4519  query_id:uint64 amount:(VarUInteger 16) from:MsgAddress\n                     response_address:MsgAddress\n                     forward_ton_amount:(VarUInteger 16)\n                     forward_payload:(Either Cell ^Cell)\n                     = InternalMsgBody;\n```\n\n`Actor B Jetton wallet → actor B regular wallet`. The transfer notification message. This is sent only if `forward_ton_amount` is not zero and contains the following data:\n\n| Name              | Type              | Description                                                                                                                                                            |\n| ----------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `query_id`        | uint64            | Links the three messaging types—transfer, transfer notification, and excesses—to each other. To ensure this process works correctly, **always use a unique query ID**. |\n| `amount`          | VarUInteger 16    | The total jetton amount were transferred.                                                                                                                              |\n| `sender`          | MsgAddress        | The address of the actor A regular wallet.                                                                                                                             |\n| `forward_payload` | Either Cell ^Cell | Some data.                                                                                                                                                             |\n\nthat meet the TL-B scheme specified in [TEP 0074](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md):\n\n```tlb\ntransfer_notification#7362d09c query_id:uint64 amount:(VarUInteger 16)\n           sender:MsgAddress forward_payload:(Either Cell ^Cell)\n           = InternalMsgBody;\n```\n\n`Actor B Jetton wallet -> actor C smart contract`. Excess message body. This is sent only if there are remaining Toncoin after paying the fees. Contains the following data:\n\n| Name       | Type   |\n| ---------- | ------ |\n| `query_id` | uint64 |\n\nthat meet the TL-B scheme specified in [TEP 0074](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md):\n\n```tlb\nexcesses#d53276db query_id:uint64 = InternalMsgBody;\n```\n\n### Token minting\n\n<Image\n  src=\"/resources/images/jettons/mint_light.png\"\n  darkSrc=\"/resources/images/jettons/mint_dark.png\"\n  alt=\"Jettons minting\"\n/>\n\n`Admin regular wallet -> Jetton master contract`. _Mint_ message contains the following data:\n\n<Aside\n  type=\"caution\"\n>\n  The following data layout is just a possible example. The structure of the Mint message is not specified in any TEPs and is left to the choice of the developer.\n</Aside>\n\n| Name          | Type       | Description                                                                           |\n| ------------- | ---------- | ------------------------------------------------------------------------------------- |\n| `query_id`    | uint64     | To ensure this process works correctly, **always use a unique query ID**.             |\n| `receiver`    | MsgAddress | The address of the actor A regular wallet.                                            |\n| `mintMessage` | Cell       | The rest of the data as in an internal transfer message, except the `query_id` field. |\n\nThe rest of the messages have already been described above when analyzing the transfer process.\n\n### Token burning\n\n<Image\n  src=\"/resources/images/jettons/burn_light.png\"\n  darkSrc=\"/resources/images/jettons/burn_dark.png\"\n  alt=\"Jettons burning\"\n/>\n\n`Actor A regular wallet -> actor A Jetton wallet`. _Burn_ message contains the following data:\n\n| Name                   | Type           | Description                                                                       |\n| ---------------------- | -------------- | --------------------------------------------------------------------------------- |\n| `query_id`             | uint64         | To ensure this process works correctly, **always use a unique query ID**.         |\n| `amount`               | VarUInteger 16 | The total jetton amount to burn.                                                  |\n| `response_destination` | MsgAddress     | The wallet address used to return remaining Toncoin through the excesses message. |\n| `custom_payload`       | Maybe ^Cell    | The optional custom data used by the receiver jetton wallet for internal logic.   |\n\nthat meet a TL-B scheme in [TEP 0074](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md):\n\n```tlb\nburn#595f07bc query_id:uint64 amount:(VarUInteger 16)\n       response_destination:MsgAddress custom_payload:(Maybe ^Cell)\n       = InternalMsgBody;\n```\n\n`Actor A Jetton wallet -> Jetton master contract`. _Burn notification_ message contains the following data:\n\n| Name                   | Type           | Description                                                                       |\n| ---------------------- | -------------- | --------------------------------------------------------------------------------- |\n| `query_id`             | uint64         | To ensure this process works correctly, **always use a unique query ID**.         |\n| `amount`               | VarUInteger 16 | The total jetton amount was burned.                                               |\n| `sender`               | MsgAddress     | The address of the actor A regular wallet.                                        |\n| `response_destination` | MsgAddress     | The wallet address used to return remaining Toncoin through the excesses message. |\n\nthat is not specified but has a recommended TL-B scheme in [TEP 0074](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md):\n\n```tlb\nburn_notification#7bdd97de query_id:uint64 amount:(VarUInteger 16)\n       sender:MsgAddress response_destination:MsgAddress\n       = InternalMsgBody;\n```\n\n### Wallet address providing\n\nThis process is straightforward. Some actor sends to the Jetton master contract `provide_wallet_address` message that contains the following fields:\n\n| Name              | Type       | Description                                                                |\n| ----------------- | ---------- | -------------------------------------------------------------------------- |\n| `query_id`        | uint64     | To ensure this process works correctly, **always use a unique query ID**.  |\n| `owner_address`   | MsgAddress | The address of the actor for which the Jetton wallet address is needed.    |\n| `include_address` | Bool       | Whether to include the address of the actor himself in the output message. |\n\nThen, the Jetton master contract sends to the actor a message that contains the following fields:\n\n| Name             | Type              | Description                                                               |\n| ---------------- | ----------------- | ------------------------------------------------------------------------- |\n| `query_id`       | uint64            | To ensure this process works correctly, **always use a unique query ID**. |\n| `wallet_address` | MsgAddress        | The Jetton wallet contract address.                                       |\n| `owner_address`  | Maybe ^MsgAddress | The address of the owner.                                                 |\n\nThese messages meet the corresponding TL-B schemes in [TEP 0089](https://github.com/ton-blockchain/TEPs/blob/master/text/0089-jetton-wallet-discovery.md):\n\n```tlb\nprovide_wallet_address#2c76b973 query_id:uint64 owner_address:MsgAddress\ninclude_address:Bool = InternalMsgBody;\n\ntake_wallet_address#d1735400 query_id:uint64 wallet_address:MsgAddress\nowner_address:(Maybe ^MsgAddress) = InternalMsgBody;\n```\n\n## Interaction from UI\n\nThere are three actions that can be performed through the UI:\n\n- [getting wallet balance](/standard/tokens/jettons/wallet-data);\n- [transfer jettons](/standard/tokens/jettons/transfer);\n- indexing available jettons.\n\n### Applications\n\nThe most popular user wallet applications, such as [TonKeeper](https://tonkeeper.com/), use their own SQL-like database. When the user receives a new jetton for the first time,\nthe application processes the `transfer_notification` message. Next, information about the number of jettons received is taken from it, and it is\nchecked if there is information about this jetton in the applications database. If there is, information is added to the database stating that the user has a\nnew type of jetton in the amount received. If not, the database starts indexing this new jetton, and after the validation process begins to show data\nabout it to users. This is how all the jettons that a given user has and their amounts are listed.\n\nFor a user to transfer a given amount of a token to another user, they only need to fill in the `destination` and `amount`\nfields through the application. Next, it will automatically generate a transfer message and send it to the Jetton wallet associated with the user.\n\n### Web services\n\nVarious web services, such as [Tonviewer](https://tonviewer.com/), can also be used to obtain information about the types of user jettons and their amounts.\nUnlike wallet applications, they also have the ability to directly invoke the get methods of related smart contracts.\nHowever, they are not designed to generate and send messages.\n"
  },
  {
    "path": "standard/tokens/jettons/mint.mdx",
    "content": "---\ntitle: \"How to mint new jettons\"\nsidebarTitle: \"Minting jettons\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside\n  type=\"danger\"\n  title=\"Warning — funds at risk\"\n>\n  Minting and sending messages can move funds. Scope: your wallet and the target jetton contracts.\n  Rollback: on-chain transfers are final; rotate keys if a mnemonic leaks. Do first (testnet):\n  use a test wallet and testnet RPC before mainnet.\n</Aside>\n\nIn order to mint new jettons, that particular Jetton must be mintable. Otherwise, it's impossible.\nNext, only mintable Jettons are considered.\n\nMinting is not a specified operation in any of the existing TEPs.\nIts implementation is left to the developer's choice.\nThe following `typescript` code example is based on the minting implementation in\n[Notcoin jetton minter contract](https://github.com/OpenBuilders/notcoin-contract/blob/main/contracts/jetton-minter.fc).\nThis example contains a manual assembly of all the necessary messages and is useful for studying their possible structure.\n\n```typescript\nimport { Address, beginCell, internal, toNano } from \"@ton/core\";\nimport { TonClient, WalletContractV4 } from \"@ton/ton\";\nimport { mnemonicToPrivateKey } from \"@ton/crypto\";\n\nasync function main() {\n    const jettonMasterAddress = Address.parse('<JETTON_MASTER_ADDR>');\n    const receiverAddress = Address.parse('<RECEIVER_ADDR>');\n    const destinationAddress = Address.parse('<WALLET_ADDR>');\n\n    // let's add some forward_payload\n    const forwardPayload = beginCell()\n        .storeUint(0, 32) // 0 opcode means we have a comment\n        .storeStringTail('Mint')\n        .endCell();\n\n    // Forming the master message\n    // internal transfer is also unspecified by the standard, but there is a suggested format in TEP 0074\n    const masterMessage = beginCell()\n        .storeUint(0x178d4519, 32) // opcode for jetton transfer-internal\n        .storeUint(0, 64) // query id\n        .storeCoins(toNano(5)) // jetton amount, amount * 10^9. That is an amount we want to mint\n        .storeAddress(jettonMasterAddress) // from_address. For minting could be any. The Jetton wallet will check from context that the sender is the Jetton master contract and accept the transfer.\n        .storeAddress(destinationAddress) // response destination\n        .storeCoins(toNano('0.02')) // forward_ton_amount - if >0, will send notification message\n        .storeBit(1) // either forward_payload\n        .storeRef(forwardPayload) // we have forward_payload, store it as a reference\n        .endCell();\n\n    // forming the mint message\n    const mintMessageBody = beginCell()\n        .storeUint(0x642b7d07, 32) // opcode for mint\n        .storeUint(0, 64) // query id\n        .storeAddress(receiverAddress) // the user's regular wallet address\n        .storeCoins(toNano(0.1)) // Toncoin intended to user's Jetton wallet\n        .storeRef(masterMessage) // internal transfer message\n        .endCell();\n\n    const mintMessage = internal({\n        to: jettonMasterAddress,\n        value: toNano('0.1'),\n        bounce: true,\n        body: mintMessageBody\n    });\n\n    // connect to your regular wallet\n    const client = new TonClient({\n    endpoint: 'https://toncenter.com/api/v2/jsonRPC',\n    });\n    const provider = client.provider(destinationAddress);\n\n    const MNEMONIC = process.env.MNEMONIC;\n    if (!MNEMONIC) throw new Error(\"Set MNEMONIC to a test mnemonic (testnet).\");\n    const keyPair = await mnemonicToPrivateKey(MNEMONIC.split(\" \"));\n    const walletContract = WalletContractV4.create({\n        workchain: 0,\n        publicKey: keyPair.publicKey,\n    });\n\n    // send the mint message through your wallet\n    const seqno = await walletContract.getSeqno(provider);\n    await walletContract.sendTransfer(provider, {\n        seqno: seqno,\n        secretKey: keyPair.secretKey,\n        messages: [\n            mintMessage,\n        ],\n        });\n}\n\nvoid main();\n```\n\nHowever, there is an [SDK](https://github.com/ton-community/assets-sdk) that allows you to avoid manually creating all the necessary messages.\nAn example of how it can be used to send the mint message is provided below:\n\n```typescript\nimport { Address } from '@ton/core';\n\nimport { AssetsSDK, PinataStorageParams, createApi, createSender, importKey } from \"@ton-community/assets-sdk\";\n\nasync function main() {\n    const NETWORK = 'testnet';\n    const api = await createApi(NETWORK);\n\n    const keyPair = await importKey(process.env.MNEMONIC!);\n    const sender = await createSender('highload-v2', keyPair, api);\n\n    const storage: PinataStorageParams = {\n        pinataApiKey: process.env.PINATA_API_KEY!,\n        pinataSecretKey: process.env.PINATA_SECRET!,\n    };\n\n    const sdk = AssetsSDK.create({\n        api: api,\n        storage: storage,\n        sender: sender,\n    });\n\n    const JETTON_ADDRESS = Address.parse('MY_JETTON_ADDRESS');\n    const jetton = sdk.openJetton(JETTON_ADDRESS);\n\n    const RECEIVER_ADDRESS = Address.parse('RECEIVER_ADDRESS');\n    await jetton.sendMint(sender, RECEIVER_ADDRESS, 1200000n);\n}\n\nvoid main();\n```\n\nFinally, you can use web services as [TON MINTER](https://minter.ton.org/) and avoid writing code, just follow the guides.\n"
  },
  {
    "path": "standard/tokens/jettons/mintless/deploy.mdx",
    "content": "---\ntitle: \"How to deploy mintless Jetton\"\nsidebarTitle: \"Deploy mintless Jetton\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\"\n\n## Introduction\n\nMintless jettons represent a revolutionary approach to token distribution on the TON blockchain. This guide provides a comprehensive walkthrough for deploying mintless jettons, from initial setup to production deployment and ongoing maintenance.\n\n<Aside>\n  Before deploying a mintless jetton, ensure you understand the [basic concepts](/standard/tokens/jettons/mintless) and have experience with standard jetton deployment.\n</Aside>\n\n**Prerequisites**\n\nBefore starting the deployment process, ensure you have:\n\n- A TON wallet with sufficient funds for deployment\n- Understanding of Merkle trees and cryptographic proofs\n- Access to hosting infrastructure for off-chain data\n- List of airdrop recipients with their allocated amounts\n- Development environment set up for TON smart contracts\n\n## Step-by-Step Deployment Guide\n\nDeploying a mintless jetton involves several critical steps:\n\n### 1. Prepare the Merkle Tree\n\nThe foundation of any mintless jetton is a properly constructed Merkle tree containing all airdrop data.\n\n#### Data Collection\n\n- **Compile recipient list**: Gather all wallet addresses eligible for the airdrop\n- **Determine allocations**: Assign token amounts to each recipient based on your distribution criteria\n- **Set time constraints**: Define `start_from` and `expired_at` timestamps for claim availability\n\n#### Tree Generation Process\n\n```\nAirdropItem Structure:\n- amount: Coins (allocated tokens)\n- start_from: uint48 (Unix timestamp for claim start)\n- expired_at: uint48 (Unix timestamp for claim expiry)\n```\n\n- Generate a Merkle tree with all airdrop recipients and their respective amounts\n- Each leaf contains an `AirdropItem` with amount, start time, and expiry\n- Compute the root `merkle_hash` that will be stored on-chain\n\n#### Best Practices\n\n- **Validate addresses**: Ensure all recipient addresses are valid TON addresses\n- **Check allocations**: Verify total allocation doesn't exceed intended supply\n- **Test tree generation**: Use small datasets first to validate your tree construction process\n\n### 2. Deploy the Jetton Master Contract\n\nThe jetton master contract must be extended to support mintless functionality.\n\n#### Contract Requirements\n\n- Include the `merkle_hash` in the contract's storage\n- Implement the `get_mintless_airdrop_hashmap_root` get-method\n- Ensure compatibility with [TEP-177](https://github.com/ton-blockchain/TEPs/pull/177) standard\n- Use the [mintless jetton standard implementation](https://github.com/ton-community/mintless-jetton) as a reference\n\n#### Storage Extensions\n\n```\nStandard jetton storage + {\n  merkle_hash: uint256  // Root hash of the Merkle tree\n}\n```\n\n#### Deployment Checklist\n\n- [ ] Contract includes merkle\\_hash in storage\n- [ ] All standard jetton methods are implemented\n- [ ] Mintless-specific get-methods are available\n- [ ] Contract has been thoroughly tested\n- [ ] Deployment transaction has sufficient gas\n\n### 3. Set Up Off-Chain Infrastructure\n\nMintless jettons require robust off-chain infrastructure to serve Merkle proofs and tree data.\n\n#### Merkle Tree Hosting\n\n- **Storage options**: TON Storage, IPFS, AWS S3, or other reliable hosting\n- **File format**: Store complete tree as BoC (Bag of Cells) file\n- **Accessibility**: Ensure high availability and fast access times\n- **Redundancy**: Consider multiple hosting locations for reliability\n\n#### Custom Payload API Implementation\n\nImplement an API endpoint that provides:\n\n- Individual Merkle proofs for specific addresses\n- Initialization data for Jetton wallet deployment\n- Verification of claim eligibility\n\n**API Endpoints:**\n\n```\nGET /api/v1/proof/{address}\nResponse: {\n  \"proof\": \"base64_encoded_merkle_proof\",\n  \"init_data\": \"base64_encoded_init_data\",\n  \"amount\": \"1000000000\",\n  \"start_from\": 1699123200,\n  \"expired_at\": 1699209600\n}\n```\n\n#### Performance Considerations\n\n- **Caching**: Implement aggressive caching for frequently requested proofs\n- **Load balancing**: Use CDN or load balancers for high-traffic scenarios\n- **Rate limiting**: Protect against abuse while ensuring legitimate access\n\n### 4. Configure Metadata\n\nUpdate your jetton's metadata to include mintless-specific fields.\n\n#### Required Metadata Fields\n\nAccording to the [metadata standard](https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md):\n\n```json\n{\n  \"name\": \"Your Mintless Token\",\n  \"symbol\": \"YMT\",\n  \"decimals\": \"9\",\n  \"description\": \"Description of your token\",\n  \"image\": \"https://example.com/token-logo.png\",\n  \"mintless_merkle_dump_uri\": \"https://example.com/merkle-tree.boc\",\n  \"custom_payload_api_uri\": \"https://example.com/api/v1/\"\n}\n```\n\n#### Key Considerations\n\n- **mintless\\_merkle\\_dump\\_uri**: Direct link to the complete Merkle tree data\n- **custom\\_payload\\_api\\_uri**: Base URL for the custom payload API\n- **Hosting reliability**: Ensure these URIs remain accessible long-term\n- **HTTPS requirement**: Use secure connections for all external resources\n\n## Development Tools and Utilities\n\nSeveral specialized tools can assist with mintless jetton development and auditing.\n\n### mintless-proof-generator (TON Core)\n\nOfficial utility from the TON blockchain core team for Merkle proof generation and verification.\n\n#### Installation\n\n1. **Clone and build**:\n\n```bash\ngit clone https://github.com/ton-blockchain/ton\ncd ton\ngit checkout testnet\nmkdir build && cd build\ncmake ../\nmake mintless-proof-generator\n```\n\nThe compiled utility is located at `build/crypto/mintless-proof-generator`.\n\n#### Usage\n\n**Parse and verify Merkle tree:**\n\n```bash\nbuild/crypto/mintless-proof-generator parse <input-boc> <output-file>\n```\n\nThis command:\n\n- Prints the mintless Merkle dump cell hash\n- Stores the airdrop list in `<output-file>`\n- Format: `<address> <amount> <start_from> <expired_at>` (one per line)\n\n**Generate all Merkle proofs:**\n\n```bash\nbuild/crypto/mintless-proof-generator make_all_proofs <input-boc> <output-file>\n```\n\nUse this for creating the complete proof set needed for `custom_payload_api_uri`.\n\n### mintless-toolbox (Tonkeeper)\n\nCommunity-developed utility from the Tonkeeper team with additional features.\n\n#### Installation\n\n```bash\ngit clone https://github.com/tonkeeper/mintless-toolbox.git\ncd mintless-toolbox\nmake\n```\n\n#### Usage\n\n**Dump airdrop data:**\n\n```bash\n./bin/mintless-cli dump <airdrop-filename>\n```\n\nThis utility:\n\n- Reads airdrop files in various formats\n- Outputs data in CSV format: `address,amount,start_from,expired_at`\n- Provides additional validation and formatting options\n"
  },
  {
    "path": "standard/tokens/jettons/mintless/overview.mdx",
    "content": "---\ntitle: \"Mintless Jetton\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\"\n\n## Introduction\n\n<Aside>\n  To understand this document, you should be familiar with the other basic Jetton standards.\n</Aside>\n\nTON has introduced [Mintless Jettons](https://github.com/ton-community/mintless-jetton?tab=readme-ov-file), an innovative extension of the Jetton standard.\n\nMintless extension adopts [Merkle proofs](/foundations/proofs/overview), using them to make airdrops without requiring traditional minting processes.\n\nIn this article, we will explore how mintless jettons work and how to use them.\n\n## Overview\n\nMintless jettons are an extension ([TEP-177](https://github.com/ton-blockchain/TEPs/pull/177) and [TEP-176](https://github.com/ton-blockchain/TEPs/pull/176)) of the standard Jetton implementation ([TEP-74](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md)) on TON Blockchain.\n\nThis implementation enables large-scale, decentralized airdrops to millions of users while minimizing costs and blockchain load.\n\nNote that to use a mintless jetton to its full extent, you will need to establish an off-chain architecture.\n\n### Basic features\n\n- **Scalability**: Traditional minting processes can be resource-intensive and costly when distributing tokens to a vast number of users.\n- **Efficiency**: By utilizing Merkle trees, mintless jettons store a single hash representing all airdropped amounts, reducing storage requirements.\n- **User-friendly airdrops**: No separate pre-claim: wallets attach a Merkle proof on first transfer, so users don't perform a manual claim action.\n\nBecause mintless jettons extend the standard jettons, you can interact with them the same way as standard jettons — no additional steps required.\n\n## How it works\n\nMintless jettons leverage [Merkle trees](/foundations/proofs/overview) and cryptographic proofs to enable efficient, decentralized airdrops without traditional minting. Here's a detailed breakdown of the technical implementation:\n\n### Merkle Tree Foundation\n\nThe core innovation lies in representing all airdrop data as a single Merkle tree, where:\n\n- **Leaf nodes** contain airdrop information for individual addresses\n- **Internal nodes** store cryptographic hashes of their children\n- **Root hash** represents the entire airdrop dataset with a single 256-bit value\n\nThis approach reduces storage from O(n) per recipient to O(1) for the entire airdrop.\n\n### Data Structures\n\nAirdrop HashMap represents how we store individual users' airdrop information.\n\n```tlb\n_ amount:Coins start_from:uint48 expired_at:uint48 = AirdropItem;\n\n_ _(HashMap 267 AirdropItem) = Airdrop;\n```\n\nEach airdrop entry contains:\n\n- `amount`: Number of tokens allocated to the recipient\n- `start_from`: Unix timestamp when claiming becomes available\n- `expired_at`: Unix timestamp when claiming expires\n\nThe complete airdrop is stored as a HashMap where the key is a 267-bit internal TON account address and the value is an AirdropItem structure.\n\nFor the Jetton Master contract, standard storage is extended with `merkle_hash`: 256-bit root hash of the Merkle tree containing all airdrop data.\n\nThe standard wallet storage is extended with:\n\n- `merkle_hash`: Copy of the master's Merkle hash for validation\n- `already_claimed`: Boolean flag indicating whether the airdrop has been claimed\n\n### Claiming Mechanism\n\n```tlb\nmerkle_airdrop_claim#0df602d6 proof:^Cell = CustomPayload;\n```\n\nThe claiming process uses the `custom_payload` field in standard jetton transfers with:\n\n- `0x0df602d6`: Operation identifier for Merkle airdrop claims\n- `proof`: MerkleProof exotic cell containing the cryptographic proof\n\n```tlb\ntransfer#0f8a7ea5 query_id:uint64 amount:(VarUInteger 16) destination:MsgAddress\n                 response_destination:MsgAddress custom_payload:(Maybe ^Cell)\n                 forward_ton_amount:(VarUInteger 16) forward_payload:(Either Cell ^Cell)\n                 = InternalMsgBody;\n```\n\nThe standard transfer message is enhanced by including the claim proof in `custom_payload`.\n\n### Cryptographic Proof Validation\n\nWhen a jetton wallet receives a transfer with a claim payload, it performs these validation steps:\n\n1. Merkle Proof Verification\n\n- Extracts the MerkleProof exotic cell from `custom_payload`\n- Verifies the proof's cryptographic integrity against the stored `merkle_hash`\n- Ensures the proof path leads to a valid `AirdropItem` for the sender's address\n\n2. Timestamp Validation\n\n- Checks that `now() >= start_from` (claiming period has begun)\n- Verifies that `now() <= expired_at` (claiming period hasn't expired)\n\n3. Claim Status Check\n\n- Ensures `already_claimed == false` (prevents double-claiming)\n\n4. Amount Validation\n\n- Extracts the airdrop amount from the validated AirdropItem\n- Credits this amount to the wallet's balance\n\n### State Transitions\n\nBefore Claim:\n\n```\nJettonWallet {\n  balance: 0,\n  already_claimed: false,\n  merkle_hash: <root_hash>\n}\n```\n\nAfter Successful Claim:\n\n```\nJettonWallet {\n  balance: <airdrop_amount>,\n  already_claimed: true,\n  merkle_hash: <root_hash>\n}\n```\n\n### Off-chain Infrastructure\n\n#### Merkle Tree Generation\n\n1. **Data Collection**: Gather all recipient addresses and their allocated amounts\n1. **Tree Construction**: Build a binary Merkle tree with AirdropItem structures as leaves\n1. **Hash Computation**: Calculate SHA-256 hashes recursively up to the root\n1. **Proof Generation**: Create individual Merkle proofs for each recipient\n\n#### Proof Serving\n\n- **Static Storage**: Host the complete Merkle tree data at `mintless_merkle_dump_uri`\n- **Dynamic API**: Implement `custom_payload_api_uri` to serve individual proofs on demand\n- **Caching**: Optimize proof retrieval with appropriate caching strategies\n\n## Supporting mintless jettons in wallet applications\n\nWallet applications play a key role in improving the user experience with mintless jettons:\n\n- **Display unclaimed jettons**: Wallets should show users the jettons they are eligible to claim based on the Merkle tree data.\n- **Automated claim process**: When users initiate an outgoing transfer, wallets should automatically include the necessary Merkle proof in the transfer message's custom payload.\n\nWallets can achieve this by:\n\nIntegrating with the off-chain API specified in the [custom payload API](https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md#jetton-metadata-example-offchain):\n\n- Check if the jetton is mintless.\n- Verify whether the wallet owner has claimed it.\n- If unclaimed, retrieve data from the custom payload API and add the off-chain balance to the on-chain one.\n- If the user hasn’t claimed the airdrop, retrieve the custom payload and initialization data from the Custom Payload API and include it in the `transfer` message to the Jetton wallet.\n\nUsing a custom API:\n\n- Download the airdrop tree from `mintless_merkle_dump_uri` in the jetton metadata.\n- Parse the data as explained in [Merkle tree generation](#merkle-tree-generation).\n- Make the parsed result available via API.\n\n<Aside>\n  Wallets are not required to support mintless claims, including indexing airdrop trees. Wallet applications may charge the jetton issuer for this service.\n</Aside>\n\n## Supporting mintless jettons in DApps (DEX/Lending platforms)\n\nBecause wallet applications handle claims automatically, DApps don’t need special logic for mintless jettons. DApps can use APIs (such as TonAPI or Ton Center API) to display unclaimed balances.\n\nTo improve the user experience, DApps can check if the user's wallet application supports a specific mintless jetton. If unsupported, retrieve the airdrop proof and initialization data from the Jetton API and include it in the transfer message.\n\n## See also\n\n- [Understanding mintless jettons: a comprehensive guide](https://gist.github.com/EmelyanenkoK/bfe633bdf8e22ca92a5138e59134988f) - the original post.\n- [Mintless jetton standard implementation](https://github.com/ton-community/mintless-jetton)\n- [Jetton offchain payloads TEP](https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md#jetton-metadata-example-offchain)\n- [Jetton metadata standard](https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md)\n"
  },
  {
    "path": "standard/tokens/jettons/overview.mdx",
    "content": "---\ntitle: \"Overview\"\n---\n\nJettons (TEP-74 standard) serve as TON's counterpart to Ethereum's [ERC-20 tokens](https://eips.ethereum.org/EIPS/eip-20), functioning as the primary means of representing monetary value and fungible assets within the TON ecosystem. These tokens embody the principle of fungibility, where each unit holds identical value and can be seamlessly exchanged with any other unit of the same token type.\n\nUse cases:\n\n- To represent currency on-chain, like USDT. Each Jetton can be arbitrary fraction (1 Jetton = 10<sup>-6</sup> USD)\n- To empower governance-like voting systems. Each Jetton equals a vote\n- To represent deposit size in Decentralized Finance\n\nThe technical architecture of Jettons reflects TON's distributed design principles. Rather than storing all token information in a single contract, the system employs a distributed approach where each user maintains their own Jetton wallet contract. The main Jetton contract functions as a central registry, storing essential metadata and tracking total supply, while individual wallet contracts handle user-specific balances and execute transfer operations. This architecture enhances scalability and reduces congestion compared to centralized token models.\n\nRead more:\n\n- [Jetton standard comparison](/standard/tokens/jettons/comparison)\n- [TEP-74](https://github.com/ton-blockchain/TEPs/blob/0d7989fba6f2d9cb08811bf47263a9b314dc5296/text/0074-jettons-standard.md)\n"
  },
  {
    "path": "standard/tokens/jettons/supply-data.mdx",
    "content": "---\ntitle: \"How to get supply data\"\nsidebarTitle: \"Get supply data\"\n---\n\nimport { Image } from '/snippets/image.jsx';\n\nTo retrieve specific Jetton data, use the Jetton master contract's `get_jetton_data()` method.\n\nThis method returns the following data:\n\n| Name                 | Type             | Description                                                                                                               |\n| -------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------- |\n| `total_supply`       | `VarUInteger 16` | the total number of issued jettons measured in indivisible units                                                          |\n| `mintable`           | `Bool`           | Indicates whether new jettons can be minted (-1 for true, 0 for false)                                                    |\n| `admin_address`      | `Address`        | admin's address                                                                                                           |\n| `jetton_content`     | `Cell`           | data formatted according to [TEP-64](https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md) |\n| `jetton_wallet_code` | `Cell`           | a code of the corresponding Jetton wallet                                                                                 |\n\nYou can call the `get_jetton_data()` method from your favorite IDE:\n\n```javascript\nimport { TonClient, Address } from \"@ton/ton\"\n\nasync function main() {\n    const client = new TonClient({\n    endpoint: 'https://toncenter.com/api/v2/jsonRPC',\n    });\n\n    const JettonMasterAddress = Address\n    .parse('0:b113a994b5024a16719f69139328eb759596c38a25f59028b146fecdc3621dfe');\n\n    const data = await client.runMethod(JettonMasterAddress,\n    'get_jetton_data');\n\n    const Stack = data.stack;\n\n    console.log(Stack.readNumber()); // Total supply\n\n    console.log(Stack.readNumber()); // mintable\n\n    console.log(Stack.readAddress().toString()); // Admin address\n\n    console.log(Stack.readCell()); // jetton_content\n\n    console.log(Stack.readCell()) // jetton_wallet_code\n}\n\nvoid main();\n```\n\nOr call it through a web service, such as [Tonviewer](https://tonviewer.com/EQDmVdCZ2SALvyfCDVlPLr0hoPhUxgjNFtTAxemz9V_C5wbN?section=method):\n\n<Image\n  src=\"/resources/images/tonviewer/jetton-data.png\"\n  darkSrc=\"/resources/images/tonviewer/jetton-data-dark.png\"\n/>\n\nFinally, you can get this information using the [API](/ecosystem/api/overview).\n"
  },
  {
    "path": "standard/tokens/jettons/transfer.mdx",
    "content": "---\ntitle: \"How to transfer Jettons\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n[TEP-74](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md#internal-message-handlers) standard specifies that Jetton wallets must support `transfer` operation.\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  Each jetton stores a `decimals` parameter in its metadata. Transferring without accounting for `decimals` can result in sending 1000 times the intended amount—irreversible on mainnet.\n\n  Mitigation: Always retrieve and apply the correct `decimals` value. Test on testnet first. Read [decimals parameter](/standard/tokens/metadata#decimals) for details.\n</Aside>\n\nTo attach a comment, the message has to encode it in `forward_payload` field, and `forward_ton_amount` is some amount of Toncoin attached to let the receiving wallet process the message.\n\nFormat of `forward_payload` for comments and other kinds of attached data can be found in [the API section](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md#forward_payload-format). If `forward_ton_amount` is `0`, `forward_payload` doesn't have to comply with the schema.\n\nA single manual transfer can be done with a web service (for example, [Minter](https://minter.ton.org/)).\n\nA programmatic transfer is usually done with an SDK (for example, [`assets-sdk`](https://github.com/ton-community/assets-sdk)) that handles low-level message serialization details. The provided example uses TON Center API that might [require a key](/ecosystem/api/toncenter/get-api-key). Also you'll need a mnemonic of a wallet that will pay for the transfer.\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  Beware that API keys and mnemonic must not be committed or shared publicly.\n\n  A better approach is to use a `.env` file that is excluded from repository with `.gitignore`. For GitHub CI purposes, consult [their documentation](https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets).\n</Aside>\n\n```ts expandable\nimport { Address, toNano, WalletContractV5R1, TonClient } from \"@ton/ton\";\nimport { mnemonicToPrivateKey } from \"@ton/crypto\";\nimport { AssetsSDK, createApi } from \"@ton-community/assets-sdk\";\n\nconst network = \"testnet\";\n// a list of 24 space-separated words\nconst mnemonic = \"foo bar baz\";\nconst apiKey = \"<API_KEY>\";\nconst jettonMasterAddress = Address.parse(\"<JETTON_MASTER_ADDR>\");\nconst destinationRegularWalletAddress = Address.parse(\"<DESTINATION_WALLET_ADDR>\");\n\nasync function main() {\n    // create an RPC client that will send network requests\n    const client = new TonClient({\n        endpoint: \"https://toncenter.com/api/v2/jsonRPC\",\n        apiKey,\n    });\n\n    // extract private and public keys from the mnemonic\n    const keyPair = await mnemonicToPrivateKey(mnemonic.split(\" \"));\n\n    // create a client for TON wallet\n    const wallet = WalletContractV5R1.create({\n        workchain: 0,\n        // public key is required to deploy a new wallet\n        // if it wasn't deployed yet\n        publicKey: keyPair.publicKey,\n    });\n\n    const provider = client.provider(wallet.address);\n\n    // sender is an object used by assets-sdk to send messages\n    // private key is used to sign messages sent to a wallet\n    const sender = wallet.sender(provider, keyPair.secretKey);\n\n    // create an assets-sdk client\n    const api = await createApi(network);\n    const sdk = AssetsSDK.create({ api, sender });\n\n    // create a client for interacting with jettons of a\n    // certain type\n    const jetton = await sdk.openJetton(jettonMasterAddress);\n\n    // create a client for the sender's Jetton wallet\n    const jettonWallet = await jetton.getWallet(sdk.sender!.address!);\n\n    // tell sender's Jetton wallet to transfer Jettons\n    await jettonWallet.send(sender, destinationRegularWalletAddress, toNano(10));\n}\n\nvoid main();\n```\n\nFor reference, here's a low-level example of the process, where message serialization is done manually.\n\n```ts expandable\nimport { Address, beginCell, internal, SendMode, toNano } from \"@ton/core\";\nimport { TonClient, WalletContractV5R1, TupleItemSlice } from \"@ton/ton\";\nimport { mnemonicToPrivateKey } from \"@ton/crypto\";\n\n// a list of 24 space-separated words\nconst mnemonic = \"foo bar baz\";\nconst apiKey = \"<API key>\";\nconst jettonMasterAddress = Address.parse(\n    \"<Jetton master address>\",\n);\nconst destinationRegularWalletAddress = Address.parse(\n    \"<destination wallet address>\",\n);\n\nasync function main() {\n    // connect to your regular walletV5\n    const client = new TonClient({\n        endpoint: \"https://toncenter.com/api/v2/jsonRPC\",\n        apiKey,\n    });\n\n    const keyPair = await mnemonicToPrivateKey(mnemonic.split(\" \"));\n    const walletContract = WalletContractV5R1.create({\n        workchain: 0,\n        publicKey: keyPair.publicKey,\n    });\n\n    const provider = client.provider(walletContract.address);\n\n\n    // Find your Jetton wallet Address\n    const walletAddressCell = beginCell()\n        .storeAddress(walletContract.address)\n        .endCell();\n    const el: TupleItemSlice = {\n        type: \"slice\",\n        cell: walletAddressCell,\n    };\n    const data = await client.runMethod(\n        jettonMasterAddress,\n        \"get_wallet_address\",\n        [el],\n    );\n    const jettonWalletAddress = data.stack.readAddress();\n\n    // form the transfer message\n    const forwardPayload = beginCell()\n        .storeUint(0, 32) // 0 opcode means we have a comment\n        .storeStringTail(\"for coffee\")\n        .endCell();\n\n    const messageBody = beginCell()\n        // opcode for jetton transfer\n        .storeUint(0x0f8a7ea5, 32)\n        // query id\n        .storeUint(0, 64)\n        // jetton amount, amount * 10^9\n        .storeCoins(toNano(5))\n        // the address of the new jetton owner\n        .storeAddress(destinationRegularWalletAddress)\n        // response destination (in this case, the destination wallet)\n        .storeAddress(destinationRegularWalletAddress)\n        // no custom payload\n        .storeBit(0)\n        // forward amount - if >0, will send notification message\n        .storeCoins(toNano(\"0.02\"))\n        // store forwardPayload as a reference\n        .storeBit(1)\n        .storeRef(forwardPayload)\n        .endCell();\n\n    const transferMessage = internal({\n        to: jettonWalletAddress,\n        value: toNano(\"0.1\"),\n        bounce: true,\n        body: messageBody,\n    });\n\n    // send the transfer message through your wallet\n    const seqno = await walletContract.getSeqno(provider);\n    await walletContract.sendTransfer(provider, {\n        seqno: seqno,\n        secretKey: keyPair.secretKey,\n        messages: [transferMessage],\n        sendMode: SendMode.PAY_GAS_SEPARATELY,\n    });\n}\n\nvoid main();\n```\n"
  },
  {
    "path": "standard/tokens/jettons/wallet-data.mdx",
    "content": "---\ntitle: \"How to get Jetton wallet data\"\nsidebarTitle: \"Get Jetton wallet data\"\n---\n\nimport { Image } from '/snippets/image.jsx';\n\nTo retrieve the Jetton wallet's account jetton amount, owner identification information, and other details related to a specific Jetton wallet contract, use the `get_wallet_data()` [get method](/foundations/messages/overview) within the Jetton wallet contract.\n\nThis method returns the following data:\n\n| Name                    | Type             | Description                                    |\n| ----------------------- | ---------------- | ---------------------------------------------- |\n| `balance`               | `VarUInteger 16` | the amount of nano tokens on the Jetton wallet |\n| `owner`                 | `MsgAddress`     | the address of owner's regular wallet          |\n| `jetton_master_address` | `MsgAddress`     | the address of the Jetton master contract      |\n| `jetton_wallet_code`    | `Cell`           | a code of the Jetton wallet                    |\n\nYou can call the `get_wallet_data()` method from your favorite IDE:\n\n```javascript\nimport { Address, TonClient } from \"@ton/ton\";\n\nasync function main() {\n  const client = new TonClient({\n    endpoint: \"https://toncenter.com/api/v2/jsonRPC\",\n  });\n\n  const JettonwalletAddress = Address.parse(\n    \"EQDmVdCZ2SALvyfCDVlPLr0hoPhUxgjNFtTAxemz9V_C5wbN\",\n  );\n\n  const data = await client.runMethod(JettonwalletAddress, \"get_wallet_data\");\n\n  const Stack = data.stack;\n\n    console.log(\"Balance in nano tokens: \", Stack.readNumber());\n\n    // wallet address\n    console.log(\"Owner: \", Stack.readAddress().toString({ bounceable: false }));\n\n    console.log(\"Jetton Master address: \", Stack.readAddress().toString());\n\n    // default BoC encoding in viewers\n    console.log(\"Jetton Wallet code: \", Stack.readCell().toBoc().toString('hex'));\n}\n\nvoid main();\n```\n\nOr call it through a web service, such as [Tonviewer](https://tonviewer.com/EQDmVdCZ2SALvyfCDVlPLr0hoPhUxgjNFtTAxemz9V_C5wbN?section=method):\n\n<Image\n  src=\"/resources/images/tonviewer/get-wallet-data.png\"\n  darkSrc=\"/resources/images/tonviewer/get-wallet-data-dark.png\"\n/>\n\nFinally, you can get this information using the [API](https://toncenter.com/api/v3/jetton/wallets).\n"
  },
  {
    "path": "standard/tokens/metadata.mdx",
    "content": "---\ntitle: \"Metadata\"\nsidebarTitle: \"Metadata\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nThe metadata standard covering NFTs, NFT collections, and jettons is outlined in [TEP-64](https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md) (TON Enhancement Proposal 64).\n\nOn TON, entities can have three types of metadata: on-chain, semi-chain, and off-chain.\n\n- **On-chain metadata:** stored on the blockchain, including name, attributes, and image.\n- **Off-chain metadata:** stored via a link to a metadata file hosted off-chain.\n- **Semi-chain metadata:** a hybrid approach that stores small fields (e.g., name or attributes) on-chain, while hosting the image off-chain and storing only a link to it.\n\n## Snake data encoding\n\nThe Snake encoding allows a portion of data to be stored in a standardized cell, with the remainder stored recursively in child cells. In this scheme, Snake-encoded data is typically prefixed with the `0x00` byte (see the note below for exceptions). TL-B schema:\n\n```tlb title=\"TL-B\"\ntail#_ {bn:#} b:(bits bn) = SnakeData ~0;\ncons#_ {bn:#} {n:#} b:(bits bn) next:^(SnakeData ~n) = SnakeData ~(n + 1);\n```\n\n[Read more about similar examples](/languages/tl-b/complex-and-non-trivial-examples).\n\nWhen the payload exceeds the maximum size of a single cell, Snake stores the remaining data in child cells. Part of the data is placed in the root cell, and the rest in the first child cell, continuing recursively until all data is stored.\n\nBelow is an example of Snake encoding and decoding in TypeScript:\n\n<Aside type=\"note\">\n  `bufferToChunks`, `BitBuilder`, and `BitReader` are provided by the surrounding tooling and helper utilities.\n</Aside>\n\n```ts title=\"TypeScript\"\nexport function makeSnakeCell(data: Buffer): Cell {\n  const chunks = bufferToChunks(data, 127)\n\n  if (chunks.length === 0) {\n    return beginCell().endCell()\n  }\n\n  if (chunks.length === 1) {\n    return beginCell().storeBuffer(chunks[0]).endCell()\n  }\n\n  let curCell = beginCell()\n\n  for (let i = chunks.length - 1; i >= 0; i--) {\n    const chunk = chunks[i]\n\n    curCell.storeBuffer(chunk)\n\n    if (i - 1 >= 0) {\n      const nextCell = beginCell()\n      nextCell.storeRef(curCell)\n      curCell = nextCell\n    }\n  }\n\n  return curCell.endCell()\n}\n\nexport function flattenSnakeCell(cell: Cell): Buffer {\n  let c: Cell | null = cell;\n\n  const bitResult = new BitBuilder();\n  while (c) {\n    const cs = c.beginParse();\n    if (cs.remainingBits === 0) {\n      break;\n    }\n\n    const data = cs.loadBits(cs.remainingBits);\n    bitResult.writeBits(data);\n    c = c.refs && c.refs[0];\n  }\n\n  const endBits = bitResult.build();\n  const reader = new BitReader(endBits);\n\n  return reader.loadBuffer(reader.remaining / 8);\n}\n```\n\nThe `0x00` byte prefix is not always required in the root cell when using Snake, for example, with off-chain NFT content. Also, cells are filled with bytes rather than bits to simplify parsing. To avoid issues when adding a reference in a child cell after it has already been written to its parent, the Snake cell is constructed in reverse order.\n\n## Chunked encoding\n\nThe chunked encoding stores data in a dictionary that maps `chunk_index` to a chunk. Chunked encoding must be prefixed with the `0x01` byte. This in-structure marker is distinct from the top-level content marker `0x01` that indicates off-chain content. TL-B schema:\n\n```tlb title=\"TL-B\"\nchunked_data#_ data:(HashMapE 32 ^(SnakeData ~0)) = ChunkedData;\n```\n\nBelow is an example of chunked data decoding in TypeScript:\n\n```typescript title=\"TypeScript\"\ninterface ChunkDictValue {\n  content: Buffer;\n}\nexport const ChunkDictValueSerializer = {\n  serialize(src: ChunkDictValue, builder: Builder) {},\n  parse(src: Slice): ChunkDictValue {\n    const snake = flattenSnakeCell(src.loadRef());\n    return { content: snake };\n  },\n};\n\nexport function ParseChunkDict(cell: Slice): Buffer {\n  const dict = cell.loadDict(\n    Dictionary.Keys.Uint(32),\n    ChunkDictValueSerializer\n  );\n\n  let buf = Buffer.alloc(0);\n  for (const [_, v] of dict) {\n    buf = Buffer.concat([buf, v.content]);\n  }\n  return buf;\n}\n```\n\n## NFT metadata attributes\n\n| Attribute     | Type         | Requirement | Description                                                                                             |\n| ------------- | ------------ | ----------- | ------------------------------------------------------------------------------------------------------- |\n| `uri`         | ASCII string | optional    | A URI pointing to a JSON document with metadata used by the semi-chain content layout.                  |\n| `name`        | UTF-8 string | optional    | Identifies the asset.                                                                                   |\n| `description` | UTF-8 string | optional    | Describes the asset.                                                                                    |\n| `image`       | ASCII string | optional    | A URI pointing to a resource with an image MIME type.                                                   |\n| `image_data`  | binary       | optional    | Either a binary representation of the image for the on-chain layout or base64 for the off-chain layout. |\n\n## Jetton metadata attributes\n\n| Attribute      | Type         | Requirement | Description                                                                                                                                                                                                                                                |\n| -------------- | ------------ | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `uri`          | ASCII string | optional    | A URI pointing to a JSON document with metadata used by the semi-chain content layout.                                                                                                                                                                     |\n| `name`         | UTF-8 string | optional    | Identifies the asset.                                                                                                                                                                                                                                      |\n| `description`  | UTF-8 string | optional    | Describes the asset.                                                                                                                                                                                                                                       |\n| `image`        | ASCII string | optional    | A URI pointing to a resource with an image MIME type.                                                                                                                                                                                                      |\n| `image_data`   | binary       | optional    | Either a binary representation of the image for the on-chain layout or base64 for the off-chain layout.                                                                                                                                                    |\n| `symbol`       | UTF-8 string | optional    | Token symbol — for example, \"XMPL\" — used in the form \"You have received 99 XMPL\".                                                                                                                                                                         |\n| `decimals`     | UTF-8 string | optional    | The number of decimal places used by the token. If not specified, the default is 9. A UTF-8–encoded string containing a number from 0 to 255; for example, 8 means the on-chain amount must be divided by 100000000 to get the user-facing representation. |\n| `amount_style` | string       | optional    | Defines how token amounts should be displayed for external applications. One of `n`, `n-of-total`, `%`.                                                                                                                                                    |\n| `render_type`  | string       | optional    | Indicates how external applications should categorize and render the token. `currency` — display as a currency (default). `game` — game-style display: renders like an NFT, also shows the number of tokens, and respects `amount_style`.                  |\n\n### `amount_style`\n\n- `n` — number of jettons (default). If the user has 100 tokens with 0 decimals, display 100.\n- `n-of-total` — the number of jettons out of the total issued. For example, if the `totalSupply` is 1000 and the user has 100, display \"100 of 1000\" (or an equivalent representation of the ratio).\n- `%` — the percentage of total issued jettons. For example, with a total of 1000 and a user balance of 100, display 10% (100 ÷ 1000 = 0.1).\n\n### `render_type`\n\n- `currency` — display as a currency (default).\n- `game` — game-style display that appears as an NFT, shows the number of tokens, and respects `amount_style`.\n\n### `decimals`\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  Each jetton stores a `decimals` parameter in its metadata that determines how amounts are displayed. Transferring without accounting for `decimals` can result in sending drastically more tokens than expected.\n\n  Mitigation: Always retrieve and apply the correct `decimals` value before calculating transfer amounts. Test transfers with small amounts on testnet first.\n</Aside>\n\nThe `decimals` parameter defines the number of decimal places for displaying token amounts. The on-chain balance is stored as an integer in the smallest unit (nano-tokens), and must be divided by 10^decimals to get the user-facing value.\n\nCommon values:\n\n- Most jettons use `decimals: 9` (default when not specified)\n- USDT uses `decimals: 6`\n\nExample: If the on-chain balance is 1000000000 nano-tokens:\n\n- With `decimals: 9` → displayed as 1.0 token\n- With `decimals: 6` → displayed as 1000.0 tokens\n\nWhen transferring jettons programmatically, the amount must be calculated as: `on_chain_amount = display_amount × 10^decimals`.\n\nFor example, to transfer 1 USDT (`decimals: 6`):\n\n- Correct on-chain amount: `1 × 10^6 = 1000000`\n- Incorrect (using default 9): `1 × 10^9 = 1000000000` (transfers 1000 USDT instead of 1)\n\n## Parsing metadata\n\nTo parse metadata, first retrieve the NFT data from the blockchain. For details, see [retrieving NFT data](/standard/tokens/nft/metadata).\n\nAfter the on-chain NFT data is retrieved, determine the content type by reading the first byte of the content, then parse accordingly.\n\n### Off-chain\n\nIf the metadata byte string starts with `0x01`, the content is off-chain. Decode the remainder using Snake as an ASCII string to obtain the URL. Once you fetch the off-chain metadata and identification data, the process is complete. Example URL for off-chain NFT metadata:\n`https://s.getgems.io/nft/b/c/62fba50217c3fe3cbaad9e7f/95/meta.json`\n\nContents of the referenced URL:\n\n```json title=\"json\"\n{\n   \"name\": \"TON Smart Challenge #2 Winners Trophy\",\n   \"description\": \"TON Smart Challenge #2 Winners Trophy 1 place out of 181\",\n   \"image\": \"https://s.getgems.io/nft/b/c/62fba50217c3fe3cbaad9e7f/images/943e994f91227c3fdbccbc6d8635bfaab256fbb4\",\n   \"content_url\": \"https://s.getgems.io/nft/b/c/62fba50217c3fe3cbaad9e7f/content/84f7f698b337de3bfd1bc4a8118cdfd8226bbadf\",\n   \"attributes\": []\n}\n```\n\n### On-chain and semi-chain\n\nIf the metadata byte string starts with `0x00`, it indicates on-chain or semi-chain NFT metadata.\n\nThe metadata is stored in a dictionary where the key is the SHA-256 hash of the attribute name, and the value is data stored using the Snake or chunked format.\n\nRead known attributes such as `uri`, `name`, `image`, `description`, and `image_data`. If the `uri` field is present, the layout is semi-chain: download the off-chain content specified by `uri` and merge it with the dictionary values.\n\nExamples:\n\nOn-chain NFT: [`EQBq5z4N_GeJyBdvNh4tPjMpSkA08p8vWyiAX6LNbr3aLjI0`](https://tonviewer.com/EQBq5z4N_GeJyBdvNh4tPjMpSkA08p8vWyiAX6LNbr3aLjI0)\n\nSemi-chain NFT: [`EQB2NJFK0H5OxJTgyQbej0fy5zuicZAXk2vFZEDrqbQ_n5YW`](https://tonviewer.com/EQB2NJFK0H5OxJTgyQbej0fy5zuicZAXk2vFZEDrqbQ_n5YW)\n\nOn-chain jetton master: [`EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs`](https://tonviewer.com/EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs)\n\n## How to parse\n\nUse the following API to parse metadata: [API Metadata](/ecosystem/api/toncenter/v3/accounts/metadata?playground=open). It handles most cases within gas limits; in rare cases, parsing may fail.\n\n## Important notes on NFT metadata\n\n1. For NFT metadata, the `name`, `description`, and `image` (or `image_data`) fields are commonly used to display the NFT.\n1. For jetton metadata, the `name`, `symbol`, `decimals`, and `image` (or `image_data`) fields are commonly used.\n1. Anyone can create an NFT or jetton using any `name`, `description`, or `image`. To prevent scams and confusion, apps should clearly distinguish tokens by their address rather than by names or tickers.\n1. Some items may include a `video` field linking to video content associated with the NFT or jetton.\n\n## References\n\n- [TON Enhancement Proposal 64 (TEP-64)](https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md)\n"
  },
  {
    "path": "standard/tokens/nft/api.mdx",
    "content": "---\ntitle: \"API\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nNFT messages and methods specified in TEPs.\n\n## [TEP-62](https://github.com/ton-blockchain/TEPs/blob/1fbc23cac69723c53251f686ec90d81bf0e83443/text/0062-nft-standard.md)\n\n### NFT Item\n\n#### Transfer message layout\n\n| Field                  | Type                | Description                                                              |\n| ---------------------- | ------------------- | ------------------------------------------------------------------------ |\n| `transfer`             | `uint32`            | tag equal to `0x5fcc3d14`                                                |\n| `query_id`             | `uint64`            | arbitrary request number                                                 |\n| `new_owner`            | `MsgAddress`        | address of the new owner of the NFT item                                 |\n| `response_destination` | `MsgAddress`        | optional address to receive excess Toncoin, usually the sender's address |\n| `custom_payload`       | `Maybe ^Cell`       | optional custom data                                                     |\n| `forward_amount`       | `VarUInteger 16`    | the amount of Toncoin to be sent to the new owner                        |\n| `forward_payload`      | `Either Cell ^Cell` | optional data that should be forwarded to the new owner                  |\n\n#### Forward payload formats\n\nTo send a simple comment in the `forward_payload`, the `forward_payload` must start with `0x00000000` (32-bit unsigned integer equal to zero); the remainder of the `forward_payload` contains the comment.\n\nIf the comment does not begin with the byte `0xff`, the comment is a text one; it can be displayed \"as is\" to the end user of a wallet (after filtering invalid and control characters and checking that it is a valid UTF-8 string). For instance, users may indicate the purpose (\"for coffee\") of a simple transfer from their wallet to the wallet of another user in this text field.\n\nOn the other hand, if the comment begins with the byte `0xff`, the remainder is a \"binary comment\", which should not be displayed to the end user as text (only as a hex dump if necessary). The intended use of \"binary comments\" is, e.g., to contain a purchase identifier for payments in a store, to be automatically generated and processed by the store's software.\n\nIf the `forward_payload` contains a binary message for interacting with the destination smart contract (for example, with DEX), then there are no prefixes.\n\n#### Ownership assigned message layout\n\n| Field                | Type                | Description                                    |\n| -------------------- | ------------------- | ---------------------------------------------- |\n| `ownership_assigned` | `uint32`            | tag equal to `0x05138d91`                      |\n| `query_id`           | `uint64`            | should be equal to request's `query_id`        |\n| `prev_owner`         | `MsgAddress`        | address of the previous owner of this NFT item |\n| `forward_payload`    | `Either Cell ^Cell` | should be equal to request's `forward_payload` |\n\n#### Excesses message layout\n\n| Field      | Type     | Description                             |\n| ---------- | -------- | --------------------------------------- |\n| `excesses` | `uint32` | tag equal to `0xd53276db`               |\n| `query_id` | `uint64` | should be equal to request's `query_id` |\n\n#### Get static data message layout\n\n| Field             | Type     | Description               |\n| ----------------- | -------- | ------------------------- |\n| `get_static_data` | `uint32` | tag equal to `0x2fcb26a2` |\n| `query_id`        | `uint64` | arbitrary request number  |\n\n#### Report static data message layout\n\n| Field                | Type         | Description                                                               |\n| -------------------- | ------------ | ------------------------------------------------------------------------- |\n| `report_static_data` | `uint32`     | tag equal to `0x8b771735`                                                 |\n| `query_id`           | `uint64`     | should be equal to request's `query_id`                                   |\n| `index`              | `uint256`    | numerical index of this NFT in the collection                             |\n| `collection`         | `MsgAddress` | address of the smart contract of the collection to which this NFT belongs |\n\n<Aside type=\"caution\">Verify that item belongs to collection via [get method in collection](/standard/tokens/nft/api#get-nft-address-by-index), see more [here](/standard/tokens/nft/verify)</Aside>\n\n#### get\\_nft\\_data()\n\nNo arguments. Outputs:\n\n| Field                | Type         | Description                                                               |\n| -------------------- | ------------ | ------------------------------------------------------------------------- |\n| `init?`              | `int`        | if not zero, then this NFT is fully initialized and ready for interaction |\n| `index`              | `int`        | numerical index of this NFT in the collection                             |\n| `collection_address` | `MsgAddress` | address of the smart contract of the collection to which this NFT belongs |\n| `owner_address`      | `MsgAddress` | address of the current owner of this NFT                                  |\n| `individual_content` | `Cell`       | individual NFT content in any format                                      |\n\n<Aside type=\"caution\">Verify that item belongs to collection via [get method in collection](/standard/tokens/nft/api#get-nft-address-by-index), see more [here](/standard/tokens/nft/verify)</Aside>\n\n### NFT Collection\n\n#### get\\_collection\\_data()\n\nNo arguments. Outputs:\n\n| Field                | Type         | Description                                              |\n| -------------------- | ------------ | -------------------------------------------------------- |\n| `next_item_index`    | `int`        | the count of currently deployed NFT items in collection  |\n| `collection_content` | `Cell`       | collection content in a format that complies with TEP-64 |\n| `owner_address`      | `MsgAddress` | collection owner address, zero address if no owner       |\n\n#### get\\_nft\\_address\\_by\\_index()\n\nArgument: `index` as `int`.\n\nOutput: `address` as `MsgAddress`.\n\n#### get\\_nft\\_content()\n\nArguments:\n\n- `index` as `int`\n- `individual_content` as `Cell`\n\nOutput: `full_content` as `Cell`.\n\n## [TEP-66](https://github.com/ton-blockchain/TEPs/blob/c5bfe285ef91810fab02c5352593f5a1455458bf/text/0066-nft-royalty-standard.md)\n\n### Get royalty params message layout\n\n| Field                | Type     | Description               |\n| -------------------- | -------- | ------------------------- |\n| `get_royalty_params` | `uint32` | tag equal to `0x693d3950` |\n| `query_id`           | `uint64` | arbitrary request number  |\n\n### Report royalty params message layout\n\n| Field                   | Type         | Description                             |\n| ----------------------- | ------------ | --------------------------------------- |\n| `report_royalty_params` | `uint32`     | tag equal to `0xa8cb00ad`               |\n| `query_id`              | `uint64`     | should be equal to request's `query_id` |\n| `numerator`             | `uint16`     | royalty numerator                       |\n| `denominator`           | `uint16`     | royalty denominator                     |\n| `destination`           | `MsgAddress` | address to send royalty                 |\n\n### royalty\\_params()\n\nNo arguments. Outputs:\n\n| Field         | Type         | Description                      |\n| ------------- | ------------ | -------------------------------- |\n| `numerator`   | `int`        | royalty numerator (e.g., 11)     |\n| `denominator` | `int`        | royalty denominator (e.g., 1000) |\n| `destination` | `MsgAddress` | address to send royalty          |\n\nRoyalty share is `numerator / denominator`. For example, if `numerator = 11` and `denominator = 1000`, then royalty share is `11 / 1000 * 100% = 1.1%`.\n\n## [TEP-85](https://github.com/ton-blockchain/TEPs/blob/c5bfe285ef91810fab02c5352593f5a1455458bf/text/0085-sbt-standard.md)\n\n### SBT Item\n\n#### Prove ownership message layout\n\n| Field             | Type         | Description                                                            |\n| ----------------- | ------------ | ---------------------------------------------------------------------- |\n| `prove_ownership` | `uint32`     | tag equal to `0x04ded148`                                              |\n| `query_id`        | `uint64`     | arbitrary request number                                               |\n| `destination`     | `MsgAddress` | address of the contract to which the ownership should be proven        |\n| `forward_payload` | `^Cell`      | any data for sending to the destination address from SBT               |\n| `with_content`    | `Bool`       | if true, SBT's individual content cell will be included in the message |\n\n<Aside type=\"caution\">Should be rejected if sender address is not the owner's address.</Aside>\n\n#### Request owner message layout\n\n| Field             | Type         | Description                                                            |\n| ----------------- | ------------ | ---------------------------------------------------------------------- |\n| `request_owner`   | `uint32`     | tag equal to `0xd0c3bfea`                                              |\n| `query_id`        | `uint64`     | arbitrary request number                                               |\n| `destination`     | `MsgAddress` | address of the contract to which the ownership should be proven        |\n| `forward_payload` | `^Cell`      | any data for sending to the destination address from SBT               |\n| `with_content`    | `Bool`       | if true, SBT's individual content cell will be included in the message |\n\n#### Destroy message layout\n\n| Field      | Type     | Description               |\n| ---------- | -------- | ------------------------- |\n| `destroy`  | `uint32` | tag equal to `0x1f04537a` |\n| `query_id` | `uint64` | arbitrary request number  |\n\n<Aside type=\"caution\">Should be rejected if sender address is not the owner's address. Sets the owner's address and authority to null, and sends an excesses message with the contract's balance.</Aside>\n\n#### Revoke message layout\n\n| Field      | Type     | Description               |\n| ---------- | -------- | ------------------------- |\n| `revoke`   | `uint32` | tag equal to `0x6f89f5e3` |\n| `query_id` | `uint64` | arbitrary request number  |\n\n<Aside type=\"caution\">Should be rejected if sender address is not the authority's address or if already revoked. Sets `revoked_at` to current unix time.</Aside>\n\n#### Ownership proof message layout\n\n| Field                | Type          | Description                                                      |\n| -------------------- | ------------- | ---------------------------------------------------------------- |\n| `ownership_proof`    | `uint32`      | tag equal to `0x0524c7ae`                                        |\n| `query_id`           | `uint64`      | should be equal to request's `query_id`                          |\n| `item_id`            | `uint256`     | ID of an SBT                                                     |\n| `owner`              | `MsgAddress`  | SBT owner's address                                              |\n| `data`               | `^Cell`       | data cell passed in `prove_ownership`                            |\n| `revoked_at`         | `uint64`      | unix time when SBT was revoked, 0 if it was not                  |\n| `individual_content` | `Maybe ^Cell` | SBT's individual content if `with_content` was true, null if not |\n\n#### Owner info message layout\n\n| Field        | Type          | Description                                           |\n| ------------ | ------------- | ----------------------------------------------------- |\n| `owner_info` | `uint32`      | tag equal to `0x0dd607e3`                             |\n| `query_id`   | `uint64`      | should be equal to request's `query_id`               |\n| `item_id`    | `uint256`     | ID of an SBT                                          |\n| `initiator`  | `MsgAddress`  | address of request initiator                          |\n| `owner`      | `MsgAddress`  | SBT owner's address                                   |\n| `data`       | `^Cell`       | data cell equal to request's `forward_payload`        |\n| `revoked_at` | `uint64`      | unix time when SBT was revoked, 0 if it was not       |\n| `content`    | `Maybe ^Cell` | SBT's content if `with_content` was true, null if not |\n\n#### get\\_nft\\_data()\n\nSame as [NFT standard](/standard/tokens/nft/api#get-nft-data). No arguments. Outputs:\n\n| Field                | Type         | Description                                                               |\n| -------------------- | ------------ | ------------------------------------------------------------------------- |\n| `init?`              | `int`        | if not zero, then this SBT is fully initialized and ready for interaction |\n| `index`              | `int`        | numerical index of this SBT in the collection                             |\n| `collection_address` | `MsgAddress` | address of the smart contract of the collection to which this SBT belongs |\n| `owner_address`      | `MsgAddress` | SBT owner's address                                                       |\n| `individual_content` | `Cell`       | individual SBT content in any format                                      |\n\n#### get\\_authority\\_address()\n\nNo arguments. Outputs:\n\n| Field       | Type    | Description                                                                                |\n| ----------- | ------- | ------------------------------------------------------------------------------------------ |\n| `authority` | `slice` | authority's address that can revoke SBT, returns `addr_none` (2 zero bits) if no authority |\n\n<Aside type=\"note\">This method is mandatory for SBT. If there is no authority it should return `addr_none` (2 zero bits).</Aside>\n\n#### get\\_revoked\\_time()\n\nNo arguments. Outputs:\n\n| Field        | Type  | Description                                           |\n| ------------ | ----- | ----------------------------------------------------- |\n| `revoked_at` | `int` | unix time of when SBT was revoked, 0 when not revoked |\n"
  },
  {
    "path": "standard/tokens/nft/comparison.mdx",
    "content": "---\ntitle: \"NFT comparison\"\nsidebarTitle: \"Comparison\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nThis page compares the available standards for each layer of the NFT protocol on TON. The protocol has two layers — `Collection` and `Item` — and you can mix standards between layers since they are independent of each other.\n\n<Aside\n  type=\"note\"\n  title=\"Scope\"\n>\n  This page focuses on high‑level capabilities and typical trade‑offs. For low‑level details, see [How it Works](/standard/tokens/nft/how-it-works).\n</Aside>\n\n## Collection\n\nShort overview:\n\n- Default Collection: canonical implementation.\n- cNFT (compressed NFT): optimized for mass distribution.\n\n| Capability                   | Default Collection                                             | cNFT Collection                                                |\n| ---------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------- |\n| Deployment & minting flow    | Items are minted by the creator                                | Any user with a valid proof can deploy their item              |\n| Who pays for item deployment | Creator in most flows                                          | Costs shifted to the audience                                  |\n| Eligibility/allowlist        | Custom off‑chain/on‑chain logic, usually controlled by creator | On‑chain Merkle allowlist, root readable via `get_merkle_root` |\n| Minting permissions          | Typically restricted to the creator                            | Open to any user who provides a valid Merkle proof             |\n| Typical use cases            | Curated drops, controlled minting                              | Mass airdrops, growth campaigns, very large audiences          |\n| Key trade‑offs               | Creator bears mint costs; tighter control                      | Lower creator cost; proof UX and distribution setup required   |\n\n### cNFT\n\nA cNFT (compressed NFT) combines a [standard NFT](/standard/tokens/nft/overview) with an [airdrop‑style distribution](/standard/tokens/airdrop), optimized for large distributions and for shifting minting costs from the creator to end users via [Merkle‑proof](/foundations/serialization/merkle)‑based self‑deployment. NFT items are self‑deployed by users using Merkle proofs instead of [airdrop markers](/standard/tokens/airdrop#markers).\n\n### Additional: Royalty\n\nRoyalty is defined at the collection level and exposed via `get_royalty_params` ([TEP‑66](https://github.com/ton-blockchain/TEPs/blob/1e5b2c4c8290d88d6bc3ddc4729812e3ac232c00/text/0066-nft-royalty-standard.md)). Any collection implementation can follow this model.\n\nMarketplaces can rely on this model and pay royalties to the collection creator regardless of how the collection was deployed.\n\n## Item\n\nShort overview:\n\n- Default Item: fully transferable NFT item that implements the standard transfer operation.\n- SBT (Soulbound Token): a non‑transferable NFT bound to a specific owner by design.\n\n| Capability        | Default Item                              | SBT (Soulbound Token)                                        |\n| ----------------- | ----------------------------------------- | ------------------------------------------------------------ |\n| Transferability   | ✅ Yes                                    | ❌ No                                                        |\n| Typical use cases | Art, collectibles, tickets, gaming assets | Identity, credentials, achievements, non‑transferable badges |\n\n### SBT\n\nAn SBT inherits the uniqueness and metadata model of NFTs but disables transfer operations, binding the token permanently to the recipient's address after mint. This makes SBTs well‑suited for identity and credentials: attendance records, participation proofs, and non‑transferable achievements. It also has an on‑chain API to prove ownership of an SBT item.\n\n#### Core functionality\n\nSBTs provide several key operations that enable secure credential management:\n\n- _Ownership binding_ - the owner is set at mint time and never changes, ensuring permanent association with the recipient.\n- _Ownership proof_ - allows the owner to request the SBT to send a proof to a target contract confirming ownership, with optional content attachment.\n- _Owner information requests_ - any party can request current owner information and optional content from the SBT.\n- _SBT destruction_ - the owner can destroy the SBT contract, clearing ownership and authority fields.\n- _Revocation mechanism_ - the authority can mark the SBT as revoked, preventing further use while maintaining historical records.\n\n## Single NFT (no collection)\n\nA Single NFT is an item contract deployed without an associated collection. It keeps the same ownership semantics but omits shared collection metadata and indexing.\n\n- When to use: one‑off assets, experimental pieces, or cases where collection‑level coordination is unnecessary.\n- Metadata: stored entirely on the item.\n- Discoverability: there is no collection index; external indexers or explicit links are used to surface the item.\n- Trade‑offs: simpler setup but fewer shared features (no collection‑wide royalty/config, no batch queries by index).\n"
  },
  {
    "path": "standard/tokens/nft/deploy.mdx",
    "content": "---\ntitle: \"How to deploy an NFT item\"\nsidebarTitle: \"Deploy an NFT item\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\nimport { Image } from '/snippets/image.jsx';\n\nThe creator sends a message to the collection contract, which deploys a new NFT item with the specified data: the initial owner and the item-specific content. The [NFT standard](/standard/tokens/nft/overview) does not prescribe how this data must be supplied; implementations may vary. Typically, the creator provides the initial owner and item-specific content for each NFT, or this information is derived from the collection itself.\n\n<Image\n  src=\"/resources/images/nft/nft_deploy.svg\"\n  alt=\"Diagram of an NFT item deployment from a collection contract\"\n/>\n\nSince the deployment process is not specified by the standard, logic can vary, and the recipes on this page might not apply to every contract. The [reference NFT implementation](/standard/tokens/nft/reference#deploy-single-item) and most modifications follow the same path: the collection owner sends a message with deploy parameters to the collection, and the collection deploys the item.\n\n## Deploy an item with a wallet\n\nTo deploy an item from a [wallet](/standard/wallets/how-it-works), send a message from the wallet to the collection contract.\n\n### Prerequisites\n\n- [Node.js](https://nodejs.org/en/download) 22+\n- Packages: [`@ton/ton`](https://github.com/ton-org/ton), [`@ton/core`](https://github.com/ton-org/ton-core), [`@ton/crypto`](https://github.com/ton-org/ton-crypto)\n- A funded Testnet wallet mnemonic in the `MNEMONIC` environment variable\n- The sending wallet must be the collection owner; otherwise the collection rejects deployments\n\n<Aside\n  type=\"danger\"\n  title=\"Funds and secrets\"\n>\n  This procedure spends funds, uses a wallet mnemonic, and interacts with a collection contract. Run it on Testnet first to test the desired behavior.\n</Aside>\n\nThe following example uses the `@ton/ton` stack for TypeScript. These libraries provide interfaces to work with wallet contracts and compose messages.\n\n```ts expandable\nimport { Address, beginCell, internal, toNano } from \"@ton/core\";\nimport { TonClient, WalletContractV5R1, SendMode } from \"@ton/ton\";\nimport { mnemonicToPrivateKey } from \"@ton/crypto\";\n\nconst collectionAddress = Address.parse(\"<COLLECTION_ADDRESS>\");\nconst recipientAddress = Address.parse(\"<RECIPIENT_ADDRESS>\");\nconst itemContent = \"<ITEM_CONTENT>\";\n\nasync function main() {\n    // Toncenter endpoint (Testnet)\n    const client = new TonClient({\n        endpoint: \"https://testnet.toncenter.com/api/v2/jsonRPC\",\n    });\n\n    // Obtain the next item index\n    const nextItemIndex = (\n        await client.runMethod(\n            collectionAddress,\n            \"get_collection_data\",\n        )\n    ).stack.readBigNumber();\n    // Read the next item index. See the explanation after the code.\n\n    // individual content\n    const content = beginCell()\n        .storeStringTail(itemContent)\n        .endCell();\n\n    const body = beginCell()\n        // deploy opcode\n        .storeUint(1, 32)\n        // query id\n        .storeUint(0, 64)\n        .storeUint(nextItemIndex, 64)\n        // Forwarded to the new item as its initial balance.\n        // Ensure `value` >= this amount + all fees.\n        .storeCoins(toNano(\"0.005\"))\n        .storeRef(\n            beginCell()\n                .storeAddress(recipientAddress)\n                .storeRef(content)\n                .endCell(),\n        )\n        .endCell();\n\n    // Compose deploy message\n    const msg = internal({\n        to: collectionAddress,\n        // Total attached to the collection. Must cover\n        // the forwarded amount below (0.005) plus\n        // execution/storage fees;\n        // keep a safety margin (e.g., 0.01-0.02 TON)\n        value: toNano(\"0.01\"),\n        bounce: true,\n        body,\n    });\n\n    // Initialize wallet\n    const mnemonic = process.env.MNEMONIC;\n    if (!mnemonic) {\n        throw new Error(\"Set MNEMONIC\");\n    }\n    const keyPair = await mnemonicToPrivateKey(\n        mnemonic.split(\" \")\n    );\n    const walletContract = client.open(\n        WalletContractV5R1.create({\n            workchain: 0, // basechain\n            publicKey: keyPair.publicKey,\n        }),\n    );\n\n    // Send the mint message through the wallet\n    const seqno = await walletContract.getSeqno();\n    await walletContract.sendTransfer({\n        seqno: seqno,\n        secretKey: keyPair.secretKey,\n        // Good practice to use these modes for\n        // regular wallet transfers\n        sendMode: SendMode.IGNORE_ERRORS |\n            SendMode.PAY_GAS_SEPARATELY,\n        messages: [msg],\n    });\n}\n\nvoid main();\n```\n\nWhere\n\n- `<COLLECTION_ADDRESS>` — the collection contract address.\n- `<RECIPIENT_ADDRESS>` — the initial owner address for the new item.\n- `<ITEM_CONTENT>` — item-specific content path or key (for example, `0.json`).\n\nExplanation of body cell composition:\n\n- `.storeUint(1, 32)` — operation code `1` selects \"deploy single item\" in the [reference collection contract](/standard/tokens/nft/reference#deploy-single-item). [TEP-62](https://github.com/ton-blockchain/TEPs/blob/f10a373fcb9276ba92b225f294998a43af53dcbf/text/0062-nft-standard.md) does not specify this opcode, so in custom implementations, this can differ.\n- `.storeUint(0, 64)` — `query_id`. Used for correlating responses with requests. It has no impact on deployment logic and `0` is a commonly used placeholder in cases where no extra logic relies on it.\n- `.storeUint(nextItemIndex, 64)` — `item_index`. Index of the item to deploy, obtained from the collection's `get_collection_data` get-method. See [Return collection data](/standard/tokens/nft/reference#return-collection-data).\n- `.storeCoins(toNano(\"0.005\"))` — amount forwarded to the new item at deployment to cover its initial balance/fees. Adjust if extra item contract logic requires more.\n\nTL-B for the reference implementation\n\n```tlb\ndeploy_nft#00000001 query_id:uint64 item_index:uint64 amount:Coins content:^Cell = InternalMsgBody;\n```\n\nIn the [reference contract](/standard/tokens/nft/reference#deploy-single-item), the body for `op=1` consists of `query_id`, `item_index`, `amount`, and a reference to `content`. See the [TL-B overview](/languages/tl-b/overview).\n\n### Verify\n\n- In a block explorer, confirm the transaction for `<COLLECTION_ADDRESS>` succeeded and inspect the transaction trace to see the internal message that deployed the item.\n- To verify via code: call [`get_nft_address_by_index(<INDEX>)`](/standard/tokens/nft/reference#return-item-address-by-index) — where `<INDEX>` is the item index used in the deploy message (the `next_item_index` read from `get_collection_data`) — on the collection to obtain the item address; then call [`get_nft_data`](/standard/tokens/nft/reference#return-item-data) on the item and check that the owner is `<RECIPIENT_ADDRESS>` and the content is `<ITEM_CONTENT>`.\n\n## Deploy an item with a smart contract\n\nTo deploy an item from a smart contract, send a message from the contract to the collection contract.\n\n### Prerequisites\n\n- Enough Testnet funds on the calling contract to cover fees and attached value (for example, ≥ 0.02 TON)\n- `<COLLECTION_ADDRESS>`, `<RECIPIENT_ADDRESS>`, `<INDEX>`, `<ITEM_CONTENT>`\n- The calling contract must be the collection owner; otherwise the collection rejects deployments\n\n<Aside\n  type=\"danger\"\n  title=\"Funds and secrets\"\n>\n  This smart contract interacts with a collection contract. Run it on Testnet first to test the desired behavior.\n</Aside>\n\nThe following example is a minimal smart contract that only implements the item deployment logic. In real deployments, this is integrated into a larger flow.\n\n```tolk title=\"Tolk\"\n// SnakeString describes a (potentially long) string inside a cell;\n// short strings are stored as-is, like \"my-picture.png\";\n// long strings are nested refs, like \"xxxx\".ref(\"yyyy\".ref(\"zzzz\"))\ntype SnakeString = slice\n\nfun SnakeString.unpackFromSlice(mutate s: slice) {\n    // SnakeString can only be the last: it's \"the remainder\";\n    // for correctness, it's better to validate it has no more refs:\n    assert (s.remainingRefsCount() <= 1) throw 5;\n    val snakeRemainder = s;\n    s = createEmptySlice(); // no more left to read\n    return snakeRemainder\n}\n\nfun SnakeString.packToBuilder(self, mutate b: builder) {\n    b.storeSlice(self)\n}\n\nstruct NftItemInitAtDeployment {\n    recipientAddress: address\n    content: Cell<SnakeString>\n}\n\nstruct (0x00000001) DeployNft {\n    queryId: uint64\n    itemIndex: uint64\n    attachTonAmount: coins\n    initParams: Cell<NftItemInitAtDeployment>\n}\n\nfun onInternalMessage(in: InMessage) {\n    // The whole logic will be in `onInternalMessage`\n    // for demonstration purposes. In real deployments this should\n    // usually be gated behind authorization and other checks.\n\n    val deploy = DeployNft {\n        queryId: 0,\n        itemIndex: <INDEX>,\n        // will be sent to the item contract on deployment\n        attachTonAmount: ton(\"0.005\"),\n        initParams: NftItemInitAtDeployment {\n            recipientAddress: address(\"<RECIPIENT_ADDRESS>\"),\n            content: (\"<ITEM_CONTENT>\" as SnakeString).toCell()\n        }.toCell()\n    };\n\n    val msg = createMessage({\n        bounce: true,\n        dest: address(\"<COLLECTION_ADDRESS>\"),\n        value: ton(\"0.01\"),\n        body: deploy\n    });\n\n    msg.send(SEND_MODE_PAY_FEES_SEPARATELY);\n}\n```\n\nWhere\n\n- `<COLLECTION_ADDRESS>` — the collection contract address.\n- `<RECIPIENT_ADDRESS>` — the initial owner address for the new item.\n- `<INDEX>` — item's index. Note that obtaining the actual index on-chain is [not possible](/from-ethereum#on-chain-get-methods), so a smart contract that performs these deployments should handle that logic itself (for example, store the latest used index and increment it on each deployment).\n- `<ITEM_CONTENT>` — item-specific content path or key (for example, `0.json`).\n\nThe top of the snippet defines structs for the deploy message and can be modified depending on the NFT implementation specifics. The sending logic lives in `onInternalMessage` for simplicity. It composes a message with hard-coded example values and sends that message to the collection contract.\n\n### Verify\n\n- In a block explorer, confirm the transaction from the calling contract to `<COLLECTION_ADDRESS>` succeeded and inspect the transaction trace to see the internal message that deployed the item.\n- To verify via code: call [`get_nft_address_by_index(<INDEX>)`](/standard/tokens/nft/reference#return-item-address-by-index) on the collection to obtain the item address, then call [`get_nft_data`](/standard/tokens/nft/reference#return-item-data) on the item and check that the owner is `<RECIPIENT_ADDRESS>` and the content is `<ITEM_CONTENT>`.\n"
  },
  {
    "path": "standard/tokens/nft/how-it-works.mdx",
    "content": "---\ntitle: \"NFT: How it works\"\nsidebarTitle: \"How it works\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\nimport { Image } from '/snippets/image.jsx';\n\nCore concepts and processes behind Non‑Fungible Tokens (NFTs) in the TON Blockchain, aligned with [TEP‑62](https://github.com/ton-blockchain/TEPs/blob/1fbc23cac69723c53251f686ec90d81bf0e83443/text/0062-nft-standard.md).\n\n## Related smart contracts\n\nStandardized NFTs on TON are implemented using a set of smart contracts, including:\n\n- NFT collection smart contract\n- NFT item smart contract\n\nThe NFT standard provides only a general interaction scheme, leaving specific implementation details to developers.\n\n<Image\n  src=\"/resources/images/nft/collection_light.png\"\n  darkSrc=\"/resources/images/nft/collection_dark.png\"\n  alt=\"NFT collection\"\n/>\n\n### NFT collection\n\nThe collection is the source of truth for items. It should provide each NFT item's address, its own collection metadata, and, given an index and individual item metadata, can provide full item metadata.\n\n### NFT item\n\nFollowing TON's [contract sharding](/contract-dev/contract-sharding) approach, each NFT item is its own smart contract account. It provides the collection address, index, current owner, and individual metadata. On a valid transfer from the current owner, it updates the owner, optionally notifies the new owner, and returns excess Toncoin to the specified address.\n\n<Aside\n  type=\"caution\"\n>\n  Not every NFT that stores a collection address actually belongs to that collection. [Verify](/standard/tokens/nft/verify) that the collection returns the item's address for the item's index.\n</Aside>\n\n## Transfer NFT item\n\nThe current owner sends a transfer message to the NFT item contract. The item updates its owner field and, optionally, sends a notification and/or excess Toncoin to the specified addresses.\n\n```mermaid\nflowchart TD\n    A[Current Owner sends<br/>transfer request] --> B[NFT item updates owner field]\n    B --> C{forward_amount > 0?}\n    C -->|Yes| D[Send ownership_assigned to <br/> new owner]\n    C -->|No| E[Skip notification]\n    D --> F[Send excesses to <br/> response_destination]\n    E --> F\n```\n\nTransfer message body contains the following data:\n\n| Field                  | Type                | Description                                                              |\n| ---------------------- | ------------------- | ------------------------------------------------------------------------ |\n| `transfer`             | `uint32`            | tag equal to `0x5fcc3d14`                                                |\n| `query_id`             | `uint64`            | arbitrary request number                                                 |\n| `new_owner`            | `MsgAddress`        | address of the new owner of the NFT item                                 |\n| `response_destination` | `MsgAddress`        | optional address to receive excess Toncoin, usually the sender's address |\n| `custom_payload`       | `Maybe ^Cell`       | optional custom data                                                     |\n| `forward_amount`       | `VarUInteger 16`    | the amount of Toncoin to be sent to the new owner                        |\n| `forward_payload`      | `Either Cell ^Cell` | optional data that should be forwarded to the new owner                  |\n\n```tlb TL-B\ntransfer#5fcc3d14 query_id:uint64\n                  new_owner:MsgAddress\n                  response_destination:MsgAddress\n                  custom_payload:(Maybe ^Cell)\n                  forward_amount:(VarUInteger 16)\n                  forward_payload:(Either Cell ^Cell)\n                  = InternalMsgBody;\n```\n\nOwnership notification message body (`ownership_assigned`) contains the following data:\n\n| Field                | Type                | Description                                    |\n| -------------------- | ------------------- | ---------------------------------------------- |\n| `ownership_assigned` | `uint32`            | tag equal to `0x05138d91`                      |\n| `query_id`           | `uint64`            | should be equal to request's `query_id`        |\n| `prev_owner`         | `MsgAddress`        | address of the previous owner of this NFT item |\n| `forward_payload`    | `Either Cell ^Cell` | should be equal to request's `forward_payload` |\n\n```tlb TL-B\nownership_assigned query_id:uint64\n                   prev_owner:MsgAddress\n                   forward_payload:(Either Cell ^Cell)\n                   = InternalMsgBody;\n\n```\n\nExcess message body (`excesses`) contains the following data:\n\n| Field      | Type     | Description                             |\n| ---------- | -------- | --------------------------------------- |\n| `excesses` | `uint32` | tag equal to `0xd53276db`               |\n| `query_id` | `uint64` | should be equal to request's `query_id` |\n\n```tlb TL-B\nexcesses query_id:uint64 = InternalMsgBody;\n```\n\nThe transfer must be rejected if:\n\n1. The inbound message is not from the current owner.\n1. There are not enough coins (considering storage fee guidelines) to process the operation and send `forward_amount`.\n\n## Get static data\n\nAnyone can send a `get_static_data` message to an NFT item to request its static data (index and collection address). The item responds with `report_static_data` message using [send mode `64`](/foundations/messages/modes) (return message amount except gas fees).\n\nGet static data message body contains the following data:\n\n| Field             | Type     | Description               |\n| ----------------- | -------- | ------------------------- |\n| `get_static_data` | `uint32` | tag equal to `0x2fcb26a2` |\n| `query_id`        | `uint64` | arbitrary request number  |\n\n```tlb TL-B\nget_static_data#2fcb26a2 query_id:uint64 = InternalMsgBody;\n```\n\nReport static data message body contains the following data:\n\n| Field                | Type         | Description                                                               |\n| -------------------- | ------------ | ------------------------------------------------------------------------- |\n| `report_static_data` | `uint32`     | tag equal to `0x8b771735`                                                 |\n| `query_id`           | `uint64`     | should be equal to request's `query_id`                                   |\n| `index`              | `uint256`    | numerical index of this NFT in the collection                             |\n| `collection`         | `MsgAddress` | address of the smart contract of the collection to which this NFT belongs |\n\n```tlb TL-B\nreport_static_data#8b771735 query_id:uint64 index:uint256 collection:MsgAddress = InternalMsgBody;\n```\n\n## Best practices\n\n- Metadata referenced by each link should be permanent. If you need to change it, send a transaction that updates the reference.\n- Be mindful of TON’s asynchronous nature: on‑chain “current owner” reads may become stale by the time you act on them.\n"
  },
  {
    "path": "standard/tokens/nft/metadata.mdx",
    "content": "---\ntitle: \"How to get NFT item metadata\"\nsidebarTitle: \"Get NFT item metadata\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\nimport { Image } from '/snippets/image.jsx';\n\nNFT [metadata](/standard/tokens/metadata) is split into two parts: the collection stores collection-wide data, and the item stores item-specific data, which may not include the full metadata.\n\n<Image\n  src=\"/resources/images/nft/nft_metadata_light.png\"\n  darkSrc=\"/resources/images/nft/nft_metadata_dark.png\"\n  alt=\"Diagram showing how NFT metadata is divided between collection and item contracts\"\n/>\n\n### High level\n\nThere is a TON Center [API method](/ecosystem/api/toncenter/v3/accounts/metadata?playground=open) that retrieves NFT metadata.\n\n### Low level\n\nTo get full NFT metadata manually:\n\n1. If it is not known, resolve the NFT item address by its index from the collection using [`get_nft_address_by_index(index)`](/standard/tokens/nft/api#get-nft-address-by-index).\n1. Get the individual content from the item contract using [`get_nft_data()`](/standard/tokens/nft/api#get-nft-data).\n1. Get the full metadata from the collection contract using [`get_nft_content(index, individual_content)`](/standard/tokens/nft/api#get-nft-content).\n"
  },
  {
    "path": "standard/tokens/nft/nft-2.0.mdx",
    "content": "---\ntitle: \"NFT 2.0\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\nimport { Image } from '/snippets/image.jsx';\n\n## Concept\n\nThis section outlines the on-chain and off-chain specifications for **NFTs with obligatory royalties**.\n\n### Problem\n\nOn TON, NFTs follow [TEP-62](/standard/tokens/nft/overview) and [TEP-64](/standard/tokens/metadata); royalties are defined by [TEP-66](/standard/tokens/nft/comparison#additional%3A-royalty). To be recognized as an NFT by ecosystem products such as wallets, explorers, and indexers, a smart contract must conform to the interfaces and internal constraints defined by these specifications.\n\nTEP-66, _the NFT royalty standard_, defines the on-chain layout for royalty parameters but does not impose any rules on how royalties should be enforced across the ecosystem. **This is intentional:** introducing mandatory on-chain royalty enforcement for auctions or other market mechanisms would interfere with the foundational principles of NFTs. This would mean enforcing royalties at the cost of restricting legitimate, non-commercial transfers — such as gifting or migrating assets between personal wallets. These constraints undermine usability and conflict with the open, decentralized principles that define NFTs.\n\nThese limitations have significantly impacted the TON NFT market.\n\n### Motivation\n\nFor artists and collection creators, royalties from secondary sales are a primary source of revenue. Without a reliable way to enforce them, the initial mint becomes the only guaranteed income. As a result, some community-driven collections have been traded through Web2 platforms instead of on-chain. In such cases, royalty logic is typically bypassed, and profit distribution becomes unfair within the NFT trading ecosystem.\n\nTo ensure fair value distribution among all participants — including artists, marketplaces, and sellers — royalty enforcement must be addressed through coordinated off-chain mechanisms.\n\n### Solution\n\nThe solution for enforcing royalties while maintaining compatibility with existing services and standards involves introducing _additional mutable fields in the off-chain metadata_. The NFT contracts themselves remain unchanged; instead, the semantics of the metadata associated with each item in the collection are extended. In particular, each item includes a mutable boolean field named `royalty_violation`, along with a potentially modified image field, in addition to the existing off-chain data standard.\n\n#### Execution model\n\nThe execution model of the proposed royalty-enforcing solution includes both on-chain and off-chain components, working together to abstract blockchain complexity from ecosystem products.\n\n**1. Minting and metadata layer:** all NFTs are minted on a minting platform that combines on-chain contracts and API.\n\n- On-chain contracts handle actions like minting, burning, etc.\n- Off-chain metadata includes pack configuration and sale logic: number of items per pack, royalty rules, and mutable fields (e.g., `royalty_violation`).\n\n<Aside\n  type=\"note\"\n  title=\"Scope\"\n>\n  Refer to the [Mint platform API](https://api.getgems.io/mint-platform/docs) for detailed integration information and endpoints.\n</Aside>\n\n**2. NFT store integration:** NFT stores integrate solely through the mint API and do not interact with smart contracts directly.\n\nStores can:\n\n- Query available packs and their metadata (e.g., price, available supply)\n- Request NFT minting by attaching Toncoin on behalf of a user\n\n**3. Enforcing a mutable field:** a specific field in the off-chain metadata, such as `royalty_violation`, is updated to reflect policy changes.\n\nThese updates do not affect the smart contract but are respected by ecosystem products that rely on metadata.\n\n**4. Reindexing and propagation:** when mutable metadata changes, the Mint Platform API triggers ecosystem products and indexers to reindex the affected items.\n\nIndexers read updated metadata and expose critical flags (e.g., `royalty_violation = true`) via their APIs.\n\n<Image\n  src=\"/resources/images/nft/workflow.svg\"\n  darkSrc=\"/resources/images/nft/workflow-dark.svg\"\n  alt=\"NFT 2.0 workflow\"\n/>\n\n#### Mandatory royalty distribution\n\nIn NFT 2.0, two mandatory royalties must be paid on all primary and secondary sales:\n\n- Community fund — for ecosystem-support initiatives, including creator-support programs. For example, a program similar to [Artist in Residence](https://www.moonpay.com/newsroom/amber-vittoria-untitled) supports authors producing sticker content.\n\n  Address: `EQDo0y1Ix8Wzqms84bFjL8Vh51RPaEIYwziBBRIi1NMadXui`\n\n- Telegram fund — for future Telegram integrations involving NFT-based stickers.\n\n  Address: `EQB4ZBNOFNSIpi8Qnikm0M0PE1Hv-D-qi40J_nPyYtzA5SAX`\n\nPrimary sale:\n\n- Community fund — 5%\n- Telegram fund — 5%\n- Optional store royalty defined by store\n\nSecondary sale:\n\n- Community fund — 2.5%\n- Telegram fund — 2.5%\n- Optional store royalty defined by store\n\n#### Royalty violation marking\n\nRoyalty payment assurance works through an off-chain signaling mechanism. Suppose a user or service violates the collection's royalty policy. In that case, the corresponding NFT item is marked as **royalty violated**.\nThis status does not involve any on-chain transactions or changes to the contract state. Instead, it's reflected in the off-chain metadata by setting the `royalty_violation` field to `true`.\n\nThe examples illustrate a standard NFT and the same item when it is marked as **royalty violated**.\n\n```json\n// Standard NFT metadata\n{\n  \"name\": \"Magic Mushroom #57\",\n  \"description\": \"Hand drawing brings the NFT an artistic value, while various accessories and materials bring uniqueness and significance in our rapidly changing world.\",\n  \"image\": \"https://s.getgems.io/nft/c/62695cb92d780b7496caea3a/nft/56/629b9349e034e8e582cf6448.png\",\n  \"attributes\": [\n    {\n      \"trait_type\": \"Material\",\n      \"value\": \"Wool fabric\"\n    }\n  ]\n}\n```\n\n```json\n// Royalty violated NFT metadata\n{\n  \"name\": \"Magic Mushroom #58\",\n  \"description\": \"Hand drawing brings the NFT an artistic value, while various accessories and materials bring uniqueness and significance in our rapidly changing world.\",\n  \"image\": \"https://s.getgems.io/nft-local/b/c/687f5a964d396571109281fa/629b9349e034e8e582cf6449\",\n  \"attributes\": [\n    {\n      \"trait_type\": \"Material\",\n      \"value\": \"Wool fabric\"\n    },\n    {\n      \"trait_type\": \"Royalty violation\",\n      \"value\": \"True\"\n    }\n  ],\n  \"royalty_violation\": true\n}\n```\n\nEcosystem products are expected to **restrict functionality** for NFTs in this status. To indicate the violation in the UI, the image is _replaced with a blurred version labeled accordingly_.\n\n<Image\n  src=\"/resources/images/nft/royalty-violation-status.png\"\n  darkSrc=\"/resources/images/nft/royalty-violation-status.png\"\n  alt=\"Royalty violation status example\"\n/>\n\nIf a third-party marketplace or secondary platform offers NFTs with forced royalty trading but does not respect collection-level royalty rules, all NFT items traded on that platform are marked as royalty violated. This strictly limits their availability across the ecosystem: wallets and explorers show these items as **royalty violated** in collection views, and NFT marketplaces or stores that follow the royalty policy do not allow trading or offers for them. As a result, it is not possible to use restricted items in any service that follows this royalty policy.\n\n#### The royalty violation process\n\nThe flowchart illustrates how a royalty violation results in an NFT being flagged as `royalty_violation` and how this status is propagated through the ecosystem to user-facing interfaces.\n\n<Image\n  src=\"/resources/images/nft/violation-process.svg\"\n  darkSrc=\"/resources/images/nft/violation-process-dark.svg\"\n  alt=\"Royalty violation process\"\n/>\n\n## NFT 2.0 royalty policy\n\n### Royalty-free operations\n\nNot all NFT-related operations are subject to royalty fees. Some actions — such as ownership transfers without commercial intent — are allowed without triggering a royalty. These operations are considered part of the core NFT protocol and do not represent value-generating events.\n\n#### List of royalty-free operations\n\n- Ownership transfer without commercial intent\n- NFT item donation\n\n### Royalty-bearing operations\n\nAll operations that involve commercial intent must include royalty payments, as defined by the [TEP-66 specification](/standard/tokens/nft/comparison#additional%3A-royalty). This includes all market-based NFT trading models, such as auctions and offer mechanisms, as well as NFT-related DeFi use cases like floor perpetuals and staking.\n\n#### Retrieving royalty parameters\n\nAccording to the specification, the sales contract must retrieve royalty parameters from the collection contract and calculate payments based on that data.\n\nThe easiest way to obtain royalty parameters is by calling the `royalty_params()` get method on the main collection contract. It returns `(int numerator, int denominator, slice destination)`, where the royalty share is calculated as $\\frac{numerator}{denominator}$.\n\nFor example, if `numerator = 11` and `denominator = 1000`, the royalty share is `1.1%`. The numerator must be less than the denominator. The `destination` is a slice of type `MsgAddress`, indicating the address where the royalty should be sent.\n\nMandatory royalties are ecosystem-level fees and are not returned by `royalty_params()`. They must be applied separately.\n\n#### Marketplace responsibilities\n\n- Marketplaces that comply with the NFT 2.0 specification are expected to send `muldiv(price, numerator, denominator)` to the destination address after an NFT sale or any other successful commercial operation.\n- Marketplaces **SHOULD NOT** send royalty payments when the calculated amount is zero.\n- Marketplaces **MAY** deduct gas and message fees required to send the royalty from the royalty amount.\n\n#### Royalty message format\n\nThe TEP-66 standard does not define the body of internal messages used to deliver royalties to the `destination`. As a result, many existing contracts use different message formats. For backward compatibility, NFT 2.0 does not impose any requirements on the message body, allowing any payload to be treated as a valid royalty message.\n\nBelow is an example contract snippet written in Tolk:\n\n```tolk title=\"Tolk\"\n// You should retrieve these values by calling the collection's getter method beforehand\nstruct Storage {\n    numerator: uint16\n    denominator: uint16\n    destination: address\n}\n\n// salePrice — the total amount paid for the NFT\nfun handleRoyalty(salePrice: coins) {\n    val storage = lazy Storage.fromCell(contract.getData());\n\n    val royalty = mulDivFloor(salePrice, storage.numerator, storage.denominator);\n\n    val royaltyMsg = createMessage({\n        dest: storage.destination,\n        bounce: false,\n        value: royalty,\n    });\n\n    royaltyMsg.send(SEND_MODE_PAY_FEES_SEPARATELY);\n}\n\nfun onInternalMessage(in: InMessage) {\n    // Handle the sale\n    // and define the actual amount received\n    val salePrice = ton(\"1\");\n    handleRoyalty(salePrice);\n}\n```\n\nFor a reference implementation of royalty distribution logic, see the [open-source royalty distributor contract](https://github.com/ton-org/royalty-distributor) on GitHub.\n\n## Ecosystem products requirements\n\nNFT 2.0 is a protocol including TEP-66-compatible contracts with an additional off-chain restriction mechanism. The primary difference from other collections is the use of mutable metadata, which can change, according to royalty compliance requirements.\nIf your service caches off-chain NFT item metadata, it must be prepared to reindex affected items periodically — ideally at least once per day — to reflect any updates.\n\nAs an alternative to scheduled reindexing, services may expose a public endpoint that allows on-demand cache invalidation for specific collection items.\n\n#### Example request\n\nGET `https://{api-name}/{reindex}/{item-address}`\n\nAnyone can call this endpoint to refresh the metadata of a specific NFT item if it changes.\n\nTo comply with the NFT 2.0 specification, ecosystem products should restrict user interactions with these NFT items. All standard protocol operations involving these items should be turned off — at least at the UI level. This includes listing restricted items for sale on marketplaces, transferring them to wallets, or engaging in DeFi operations within DeFi protocols.\n\n## Ecosystem integration checklist\n\n#### Wallets\n\n- Check for the `royalty_violation` field in the metadata.\n- If `royalty_violation: true`, restrict all interactions with the item, including transfers, sales and burns.\n\n#### Explorers\n\n- Display the `royalty_violation` flag alongside other metadata fields.\n- If `royalty_violation: true`, display a warning or status label indicating that the NFT violates royalty policy.\n\n#### Marketplaces\n\n- Exclude NFTs with `royalty_violation: true` from search results.\n- Disable trading functionality for NFTs that violate the royalty policy.\n\n#### Indexers/APIs\n\n- Include the `royalty_violation` flag in your metadata response schema.\n- Provide endpoints or filters that return only NFTs with `royalty_violation: false`.\n\n## Appendix\n\n#### NFT 2.0 initial distribution process\n\nThis diagram illustrates the full sequence of actions involved in distributing NFT 2.0 items through the mint platform — from request and transaction creation to on-chain execution, indexing, and UI update.\n\n<Image\n  src=\"/resources/images/nft/nft-2.0-process.svg\"\n  darkSrc=\"/resources/images/nft/nft-2.0-process-dark.svg\"\n  alt=\"NFT 2.0 distribution process\"\n/>\n\n#### NFT 2.0 initial distribution data flow\n\nThis diagram illustrates the end-to-end data flow of NFT 2.0 item distribution through the mint platform, from the initial purchase request to on-chain execution, data propagation, and user interface updates.\n\n<Image\n  src=\"/resources/images/nft/nft-2.0-data-flow.svg\"\n  darkSrc=\"/resources/images/nft/nft-2.0-data-flow-dark.svg\"\n  alt=\"NFT 2.0 data flow\"\n/>\n\n## See also\n\n- [NFT standard: TEP-62](/standard/tokens/nft/overview)\n- [NFT royalty standard extension: TEP-66](/standard/tokens/nft/comparison#additional%3A-royalty)\n"
  },
  {
    "path": "standard/tokens/nft/overview.mdx",
    "content": "---\ntitle: \"NFT: Non-fungible token\"\nsidebarTitle: \"Overview\"\n---\n\nNon‑fungible tokens (NFTs), defined in [TEP‑62](https://github.com/ton-blockchain/TEPs/blob/0d7989fba6f2d9cb08811bf47263a9b314dc5296/text/0062-nft-standard.md), represent the digital embodiment of uniqueness within the TON ecosystem. Unlike their fungible counterparts, each NFT possesses distinct characteristics that make it irreplaceable and non‑interchangeable. This fundamental property of uniqueness enables NFTs to serve as digital certificates of authenticity for a wide array of digital and physical assets.\n\nNFTs can verify ownership of digital assets using blockchain technology. Each token carries a unique identifier and associated metadata that distinguish it from every other token. This uniqueness makes NFTs particularly valuable for representing assets where individual characteristics matter.\n\nUse cases:\n\n- Digital art\n- Real-world assets\n- Access rights\n\nThe technical implementation of NFTs in TON mirrors the distributed architecture philosophy found in [Jettons](/standard/tokens/jettons/overview). Individual item contracts represent each NFT, while collection contracts manage overall collection metadata and coordinate minting processes. This distributed approach ensures that NFT operations remain efficient and scalable even as collections grow to encompass thousands or millions of individual tokens.\n\n## Architecture and smart contracts\n\nNFTs in TON are built using a distributed smart contract architecture consisting of:\n\n- NFT collection contracts – serve as the source of truth for items, providing addresses, collection metadata, and coordinating the overall collection.\n- NFT item contracts – each NFT is represented by its own smart contract account, storing the collection address, index, current owner, and individual metadata.\n\nThis architecture ensures that each NFT operates independently while maintaining a connection to its collection.\n\n## Transfer mechanism\n\nThe current owner sends a transfer message to the NFT item contract, which updates the owner field and optionally sends notifications to the new owner along with any excess Toncoin. [This transfer flow](/standard/tokens/nft/how-it-works#transfer-nft-item) ensures atomicity while maintaining flexibility for ownership notifications and handling remaining funds.\n\n## Marketplace-ready templates\n\nTo deploy NFTs compatible with existing TON marketplaces, use contract implementations that follow the [NFT standard](/standard/tokens/nft/how-it-works).\n\nImplementations include:\n\n- [TON reference NFT contracts](https://github.com/ton-blockchain/nft-contract) – reference implementation of the TON NFT standard.\n- [Getgems NFT contracts](https://github.com/getgems-io/nft-contracts) – NFT contracts used by the Getgems marketplace.\n"
  },
  {
    "path": "standard/tokens/nft/reference.mdx",
    "content": "---\ntitle: \"NFT: reference implementation\"\nsidebarTitle: \"Reference implementation\"\n---\n\nThe NFT standard ([TEP-62](https://github.com/ton-blockchain/TEPs/blob/0d7989fba6f2d9cb08811bf47263a9b314dc5296/text/0062-nft-standard.md)) describes the required messages and get-methods. The NFT royalty standard ([TEP-66](https://github.com/ton-blockchain/TEPs/blob/0d7989fba6f2d9cb08811bf47263a9b314dc5296/text/0066-nft-royalty-standard.md)) describes a standard way to implement royalty information for NFT sales. The token data standard ([TEP-64](https://github.com/ton-blockchain/TEPs/blob/0d7989fba6f2d9cb08811bf47263a9b314dc5296/text/0064-token-data-standard.md)) describes available formats for metadata of tokens. A widely used [reference implementation](https://github.com/ton-blockchain/token-contract/tree/1182ad99413242f09925d50e70ccb7e0e09f94d4/nft) follows these standards for simple NFTs with only the essential mechanics. This page explains the reference implementation, what you can extend, and what must remain unchanged.\n\nThe [nft-contract repository](https://github.com/ton-blockchain/nft-contract) contains multiple smart contracts written in [FunC](/languages/func/overview) language, including additional ones for NFT sales. This page describes the collection and item smart contracts, as they are the only necessary ones per standard.\n\n## Collection\n\nThe full source code is in [nft-collection.fc](https://github.com/ton-blockchain/token-contract/blob/1182ad99413242f09925d50e70ccb7e0e09f94d4/nft/nft-collection.fc) file.\n\nThe TEP-62 standard only requires the implementation of get‑methods: `get_collection_data()`, `get_nft_address_by_index(int index)`, and `get_nft_content(int index, cell individual_content)`. The TEP‑66 standard also adds the `royalty_params()` get‑method, a `get_royalty_params` message for requesting royalty parameters on‑chain, and a `report_royalty_params` message for the response containing these parameters.\n\nAll other behavior is implementation‑specific. This includes any kind of modifications to the logic of minting new items, managing ownership of the collection, changing metadata, and other features. The reference implementation, for example, implements the ownership management feature and two ways of minting items: singular and batched. Both of these are outside the scope of the standards but are common and needed in most cases. These features are optional and can be removed or replaced.\n\n| Capability                                                           | Requirement                                    |\n| -------------------------------------------------------------------- | ---------------------------------------------- |\n| `get_collection_data` (get-method)                                   | Required by TEP-62                             |\n| `get_nft_address_by_index` (get-method)                              | Required by TEP-62                             |\n| `get_nft_content` (get-method)                                       | Required by TEP-62, data format follows TEP-64 |\n| `royalty_params` (get-method)                                        | Required by TEP-66                             |\n| `get_royalty_params` (inbound internal message)                      | Required by TEP-66                             |\n| `report_royalty_params` (outbound internal message)                  | Required by TEP-66                             |\n| Deploy single item, `op=1` (inbound internal message, owner-only)    | Optional                                       |\n| Deploy batch of items, `op=2` (inbound internal message, owner-only) | Optional                                       |\n| Change owner, `op=3` (inbound internal message, owner-only)          | Optional                                       |\n\nHere, `op` means a 32‑bit operation code placed at the start of an internal message body. Contracts use it to dispatch messages to different handlers. The numeric values are local to this contract; they just need to be unique within its dispatcher. See the [Messages overview](/foundations/messages/overview) for more background.\n\n### Storage\n\nThe storage scheme itself is not defined by these standards, so it can be arbitrary. The reference collection contract contains 5 fields: `owner_address`, `next_item_index`, `content`, `nft_item_code`, and `royalty_params`. Some of them are self‑explanatory, while `content` and `royalty_params` need additional explanation below.\n\nStorage loading and saving is implemented with simple functions `load_data` and `save_data`:\n\n```func\n(slice, int, cell, cell, cell) load_data() inline {\n  var ds = get_data().begin_parse();\n  return\n    (ds~load_msg_addr(), ;; owner_address\n     ds~load_uint(64), ;; next_item_index\n     ds~load_ref(), ;; content\n     ds~load_ref(), ;; nft_item_code\n     ds~load_ref()  ;; royalty_params\n     );\n}\n\n() save_data(slice owner_address, int next_item_index, cell content, cell nft_item_code, cell royalty_params) impure inline {\n  set_data(begin_cell()\n    .store_slice(owner_address)\n    .store_uint(next_item_index, 64)\n    .store_ref(content)\n    .store_ref(nft_item_code)\n    .store_ref(royalty_params)\n    .end_cell());\n}\n```\n\nThe `content` [cell](/foundations/serialization/cells) in this contract contains 2 cells in [references](/foundations/serialization/cells): `collection_content` containing metadata of the collection itself, and `common_content` containing the common prefix for individual items' metadata.\n\nThe `royalty_params` cell contains 3 values: `royalty_factor` which is a numerator, `royalty_base` which is a denominator, and `royalty_address` which is the address where royalties are sent.\n\n### Child contracts\n\nThe collection and item contracts implement a classic [parent–child pattern](/contract-dev/contract-sharding), where the collection acts as the parent and items are children. Therefore, the collection implements functionality to deploy its children, and the contract keeps the `nft_item_code` field in storage.\n\nThe contract uses helper functions to compose [`StateInit`](/foundations/messages/deploy) — roughly, the package that holds a contract’s initial code and data used to derive its address and deploy it — calculate addresses, and send deploy messages for NFT items.\n\nFirst, `calculate_nft_item_state_init` composes a `StateInit` cell of an NFT item with a given `item_index`. It composes a data cell following the expected storage schema of the item contract. Then the data and code cells are placed in a final `StateInit` cell following the format required by the TON blockchain. It uses the `store_dict` builder to encode optional references; it does not store dictionaries. This can be replaced with a more self‑explanatory [`store_maybe_ref`](/languages/func/stdlib#store-maybe-ref) builder which does the same thing. It stores a single bit `0` in a builder if the cell is null, otherwise bit `1` and a cell as a reference.\n\n```func\ncell calculate_nft_item_state_init(int item_index, cell nft_item_code) {\n  cell data = begin_cell().store_uint(item_index, 64).store_slice(my_address()).end_cell();\n  return begin_cell().store_uint(0, 2).store_dict(nft_item_code).store_dict(data).store_uint(0, 1).end_cell();\n}\n```\n\nThe `calculate_nft_item_address` function takes `state_init` composed by `calculate_nft_item_state_init`, along with `wc` (the [workchain](/foundations/glossary#workchain) for the resulting address). It calculates the address by hashing the `StateInit` and composing a [`MsgAddressInt`](/foundations/addresses/overview#internal-addresses) slice according to the format required by the TON blockchain.\n\n```func\nslice calculate_nft_item_address(int wc, cell state_init) {\n  return begin_cell().store_uint(4, 3)\n                     .store_int(wc, 8)\n                     .store_uint(cell_hash(state_init), 256)\n                     .end_cell()\n                     .begin_parse();\n}\n```\n\n`deploy_nft_item` builds the `StateInit`, derives the address, and sends the deploy message. It calls `calculate_nft_item_state_init` to compose the `StateInit`, then `calculate_nft_item_address` with `workchain()` to derive the contract's workchain (reference implementation uses `0` for [basechain](/foundations/addresses/overview#workchain-id)), and finally composes and sends the deploy message with the `StateInit` and content (using [`send_raw_message`](/languages/func/stdlib#send-raw-message)).\n\n```func\n() deploy_nft_item(int item_index, cell nft_item_code, int amount, cell nft_content) impure {\n  cell state_init = calculate_nft_item_state_init(item_index, nft_item_code);\n  slice nft_address = calculate_nft_item_address(workchain(), state_init);\n  var msg = begin_cell()\n            .store_uint(0x18, 6)\n            .store_slice(nft_address)\n            .store_coins(amount)\n            .store_uint(4 + 2 + 1, 1 + 4 + 4 + 64 + 32 + 1 + 1 + 1)\n            .store_ref(state_init)\n            .store_ref(nft_content);\n  send_raw_message(msg.end_cell(), 1); ;; pay transfer fees separately, revert on errors\n}\n```\n\nNote on `.store_uint(0x18, 6)` and `.store_uint(0x10, 6)`:\n\n- These 6 leading bits encode the start of `CommonMsgInfo` for an internal message: `int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool src:MsgAddress …` (see [message layout](/foundations/whitepapers/tblkch#3-1-7-message-layout)). Concretely, the 6 bits are:\n\n  - `tag` = `0` — selects `int_msg_info$0` (internal message info).\n  - `ihr_disabled` — set to `1` to disable IHR (Instant Hypercube Routing). IHR is a legacy delivery mode and is not used in TON; contracts should always keep it disabled. See [Hypercube routing](/foundations/shards).\n  - `bounce` — if `1`, the message will bounce back on errors during compute/action phases; if `0`, it will not bounce. We use `bounce=1` (0x18) for deploys to child items so the collection gets its funds back on failure, and `bounce=0` (0x10) for royalty replies to avoid bounces and ensure crediting wallets/uninitialized addresses. See [Bounce phase](/foundations/phases#bounce-phase).\n  - `bounced` — set to `0` in outbound messages you build. This bit is meaningful only for inbound messages: when the blockchain generates a bounce, the inbound copy has `bounced=1`. Validators construct such bounce messages themselves; your outbound value does not make a message “bounced”. In normal sends, keep it `0`.\n  - `src` — we serialize `addr_none` (the `00` tag). Validators replace it with the current contract address during the action phase, so you don’t need to spend bits storing the full source address. See [`send_raw_message`](/languages/func/stdlib#send-raw-message).\n\n  Therefore:\n\n  - `.store_uint(0x18, 6)` → `011000`: `ihr_disabled=1`, `bounce=1` (bounceable), `bounced=0`, `src=addr_none`. Used for deploy messages to child items.\n  - `.store_uint(0x10, 6)` → `010000`: `ihr_disabled=1`, `bounce=0` (non‑bounceable), `bounced=0`, `src=addr_none`. Used for replies like `report_royalty_params` to avoid bounces.\n\n  The destination comes next (`.store_slice(nft_address)`), followed by `value`, fees, timestamps, and optionally `StateInit` and body, as detailed below.\n\nNote on `.store_uint(4 + 2 + 1, 1 + 4 + 4 + 64 + 32 + 1 + 1 + 1)`:\n\n- The right‑hand argument (bit width) is the total size of the remaining header fields we serialize in one shot, in this order (mapped to the TL‑B schema):\n  - `1` — `ExtraCurrencyCollection` presence bit inside `value:CurrencyCollection` (see [`CurrencyCollection`](/foundations/whitepapers/tblkch#3-1-6-representing-collections-of-arbitrary-currencies) and the [credit phase](/foundations/whitepapers/tblkch#4-3-4-description-of-a-credit-phase)).\n  - `4` — length prefix for `ihr_fee:Grams` (encoded as `VarUInteger 16`: 4‑bit length `len` then `len` bytes; writing `0000` here encodes zero). See [`LDGRAMS`](/tvm/instructions#fa00-ldgrams).\n  - `4` — length prefix for `fwd_fee:Grams` (same `VarUInteger 16` rule; `0000` means zero). See [`LDGRAMS`](/tvm/instructions#fa00-ldgrams).\n  - `64` — `created_lt:uint64` from `CommonMsgInfo` (we write `0`; validators rewrite the actual logical time). See [message layout](/foundations/whitepapers/tblkch#3-1-7-message-layout).\n  - `32` — `created_at:uint32` from `CommonMsgInfo` (we write `0`; validators rewrite the block Unix time). See [message layout](/foundations/whitepapers/tblkch#3-1-7-message-layout).\n  - `1` — `init:(Maybe (Either StateInit ^StateInit))` presence flag (0 = no `StateInit`, 1 = present). See [message layout](/foundations/whitepapers/tblkch#3-1-7-message-layout).\n  - `1` — selector for the `Either` inside `init` (0 = inline `StateInit` follows, 1 = `^StateInit` by reference). In our case it is `1`, and `.store_ref(state_init)` follows. See [message layout](/foundations/whitepapers/tblkch#3-1-7-message-layout).\n  - `1` — selector for `body:(Either X ^X)` (0 = inline body follows, 1 = body is provided by reference). In our case it is `1`, and `.store_ref(nft_content)` follows. See [message layout](/foundations/whitepapers/tblkch#3-1-7-message-layout).\n\n- The left‑hand value `4 + 2 + 1` sets the three one‑bit selectors at the end of this header block to `1` (while earlier bits remain `0`). In order, they encode:\n  - `init` is present (`Maybe …` = 1),\n  - `init` is stored by reference (`Either StateInit ^StateInit` = 1),\n  - body is stored by reference (`Either X ^X` = 1). See [message layout](/foundations/whitepapers/tblkch#3-1-7-message-layout).\n\nThis idiom is a terse way to zero‑initialize the residual CommonMsgInfo/Message fields and set only the required selector bits, instead of writing several consecutive `.store_uint(0, …)` calls followed by individual one‑bit writes.\n\nThese three functions are used for minting new items and returning item addresses in get‑methods.\n\n### Internal messages\n\nNFT standards only require one message to be processed in a specific way: `get_royalty_params`. All other logic for processing incoming messages can be arbitrary, but this reference contract shows a good example of how it can be organized for NFTs.\n\nThe `recv_internal` function starts with incoming message parsing boilerplate:\n\n```func\n() recv_internal(cell in_msg_full, slice in_msg_body) impure {\n    if (in_msg_body.slice_empty?()) { ;; ignore empty messages\n        return ();\n    }\n    slice cs = in_msg_full.begin_parse();\n    int flags = cs~load_uint(4); ;; the `int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool` part of CommonMsgInfo\n\n    if (flags & 1) { ;; ignore all bounced messages by checking last bit of `flags` variable\n        return ();\n    }\n    slice sender_address = cs~load_msg_addr(); ;; the `src:MsgAddressInt` part of CommonMsgInfo\n    ;; ...\n}\n```\n\nThen it parses `op` and `query_id` from incoming message body, and loads the storage data:\n\n```func\n() recv_internal(cell in_msg_full, slice in_msg_body) impure {\n    ;; ...\n    int op = in_msg_body~load_uint(32);\n    int query_id = in_msg_body~load_uint(64);\n\n    var (owner_address, next_item_index, content, nft_item_code, royalty_params) = load_data();\n    ;; ...\n}\n```\n\n#### Request royalty parameters\n\nThe `get_royalty_params` message is the only inbound message handling required by TEP-66. On receipt, the contract sends a `report_royalty_params` message back to the sender with the `royalty_params` field from storage. The helper `send_royalty_params` is mostly boilerplate: it sends a [non‑bounceable](/foundations/addresses/formats) message (see [bounce behavior](/foundations/phases#bounce-phase)) with a body following the standard and carries the value of the incoming message.\n\nWhy non‑bounceable? The reply can go to any sender, including wallets or even uninitialized accounts. Making the response non‑bounceable ensures the value forwarded with `mode = 64` credits the requester even if it cannot execute code. It also avoids accidental bounces.\n\n```func\n() send_royalty_params(slice to_address, int query_id, slice data) impure inline {\n  var msg = begin_cell()\n    .store_uint(0x10, 6) ;; nobounce - int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool src:MsgAddress\n    .store_slice(to_address)\n    .store_coins(0)\n    .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)\n    .store_uint(op::report_royalty_params(), 32) ;; opcode required by standard\n    .store_uint(query_id, 64) ;; same query_id as request\n    .store_slice(data);\n  send_raw_message(msg.end_cell(), 64); ;; carry all the remaining value of the inbound message\n}\n\n() recv_internal(cell in_msg_full, slice in_msg_body) impure {\n    ;; ...\n    if (op == op::get_royalty_params()) {\n        send_royalty_params(sender_address, query_id, royalty_params.begin_parse());\n        return ();\n    }\n    ;; ...\n}\n```\n\nThe contract implements several owner-only features and verifies ownership first:\n\n```func\n() recv_internal(cell in_msg_full, slice in_msg_body) impure {\n    ;; ...\n    throw_unless(401, equal_slices(sender_address, owner_address));\n    ;; ...\n}\n```\n\nThen there are 3 features: deploy single item (opcode `1`), deploy a batch of items (opcode `2`), and change owner (opcode `3`). The chosen opcodes are arbitrary.\n\n#### Deploy single item\n\nIt parses the incoming message and expects it to contain 3 values: `item_index:uint64`, `amount:Coins`, and `content:^Cell` ([TL‑B](/languages/tl-b/overview) notation — the `^` means this field is stored in a separate referenced cell, i.e., the message carries a reference to a child [cell](/foundations/serialization/cells) that contains the content). It checks the item index to be less than or equal to the `next_item_index` from storage. Then it calls a helper function `deploy_nft_item`, which deploys the new NFT item. Lastly, if the item index equals `next_item_index`, it increments `next_item_index` to update the last item index.\n\n```func\n() recv_internal(cell in_msg_full, slice in_msg_body) impure {\n    ;; ...\n    if (op == 1) { ;; deploy new nft\n      int item_index = in_msg_body~load_uint(64);\n      throw_unless(402, item_index <= next_item_index);\n      var is_last = item_index == next_item_index;\n      deploy_nft_item(item_index, nft_item_code, in_msg_body~load_coins(), in_msg_body~load_ref());\n      if (is_last) {\n        next_item_index += 1;\n        save_data(owner_address, next_item_index, content, nft_item_code, royalty_params);\n      }\n      return ();\n    }\n    ;; ...\n}\n```\n\n#### Batch deploy items\n\nThis feature is useful when you need to deploy many NFTs at once, for example when minting some initial items. It takes a single `deploy_list` dictionary from the message where keys are item indices and values are cells containing amounts of TON to attach to deployment, and content cells, similar to the values parsed by the singular deploy feature above. It traverses the dictionary in ascending order of indices and limits the batch to ≤249 items to stay comfortably under the [action list limit](/foundations/limits#message-and-transaction-limits) of 255 actions per transaction. This reference contract chooses a lower cap than the maximum as a safety margin.\n\nThe logic is straightforward. The loop uses [`~udict::delete_get_min(64)`](/languages/func/stdlib#dict-delete-get-min) to get and delete the item with the minimum unsigned 64‑bit key. It does that on each iteration and increments `counter` each iteration to avoid exceeding the action list limit. The deployment logic is the same as for the singular deployment feature above.\n\n```func\n() recv_internal(cell in_msg_full, slice in_msg_body) impure {\n    ;; ...\n    if (op == 2) { ;; batch deploy of new nfts\n      int counter = 0;\n      cell deploy_list = in_msg_body~load_ref();\n      do {\n        var (item_index, item, f?) = deploy_list~udict::delete_get_min(64);\n        if (f?) {\n          counter += 1;\n          if (counter >= 250) { ;; Limit due to action list size\n            throw(399);\n          }\n\n          throw_unless(403 + counter, item_index <= next_item_index);\n          deploy_nft_item(item_index, nft_item_code, item~load_coins(), item~load_ref());\n          if (item_index == next_item_index) {\n            next_item_index += 1;\n          }\n        }\n      } until ( ~ f?);\n      save_data(owner_address, next_item_index, content, nft_item_code, royalty_params);\n      return ();\n    }\n    ;; ...\n}\n```\n\n#### Change owner\n\nThe last incoming message handler is for changing ownership of the collection. It parses the `new_owner` address from the incoming message body and saves contract storage with it instead of the previous `owner`.\n\n```func\n() recv_internal(cell in_msg_full, slice in_msg_body) impure {\n    ;; ...\n    if (op == 3) { ;; change owner\n      slice new_owner = in_msg_body~load_msg_addr();\n      save_data(new_owner, next_item_index, content, nft_item_code, royalty_params);\n      return ();\n    }\n    ;; ...\n}\n```\n\nFinally, if none of the conditions above are met, which means that the opcode provided in the message does not match any of the expected ones, it throws `0xffff`, which is a common exit code for unknown‑opcode errors:\n\n```func\n() recv_internal(cell in_msg_full, slice in_msg_body) impure {\n    ;; ...\n    throw(0xffff);\n}\n```\n\n### Get-methods\n\nThe collection contract implements only the get‑methods required by the standards: `get_collection_data`, `get_nft_address_by_index`, `royalty_params`, and `get_nft_content`.\n\n#### Return collection data\n\nThe get‑method `get_collection_data` returns `next_item_index` (typically the number minted if minted sequentially), collection content, and an owner address. It loads the contract storage, loads the first reference from the `content` cell (which contains the collection content), and returns those values.\n\n```func\n(int, cell, slice) get_collection_data() method_id {\n  var (owner_address, next_item_index, content, _, _) = load_data();\n  slice cs = content.begin_parse();\n  return (next_item_index, cs~load_ref(), owner_address);\n}\n```\n\n#### Return item address by index\n\nThe get‑method `get_nft_address_by_index` takes an item index and returns the item's address. It uses helper functions `calculate_nft_item_state_init` and `calculate_nft_item_address` to calculate the address.\n\n```func\nslice get_nft_address_by_index(int index) method_id {\n    var (_, _, _, nft_item_code, _) = load_data();\n    cell state_init = calculate_nft_item_state_init(index, nft_item_code);\n    return calculate_nft_item_address(workchain(), state_init);\n}\n```\n\n#### Return royalty parameters\n\nThe get‑method `royalty_params` returns royalty parameters: `numerator`, `denominator`, and `destination`, as required by the standard. These values are stored in a `royalty` cell in data, which this method parses and returns.\n\n```func\n(int, int, slice) royalty_params() method_id {\n     var (_, _, _, _, royalty) = load_data();\n     slice rs = royalty.begin_parse();\n     return (rs~load_uint(16), rs~load_uint(16), rs~load_msg_addr());\n}\n```\n\n#### Compose full item content\n\nThe get‑method `get_nft_content` takes an item index and item content, and returns full content of the item. It composes and returns a cell following the off‑chain format for metadata from the TEP‑64 standard.\n\nThis reference implementation works with an off‑chain metadata format, joining a common prefix stored in the collection contract with individual item content from the item contract. The specific way of composing the full item's content is not forced by the standard, and can be implemented in any way.\n\nSince item content in the off‑chain format is a URL pointing to a JSON with all the metadata fields, the common prefix is usually a URL to the endpoint for getting metadata for each item or a directory with all the JSON documents, for example `https://example-collection.com/items/`. Then each item can contain just the suffix of the full URL, such as `123.json`.\n\nComposing a full URL means joining these two strings, which this method does. This is the most common approach, but it's possible to implement any custom logic for composing item content, like calculating the suffix right in the get‑method from the index and allowing items to not hold any additional content.\n\nThe common prefix for content is stored as a second reference in the `content` cell from the collection's contract storage. The resulting cell is then composed with an off‑chain tag `0x01`, followed by a common prefix joined with individual content in [snake format](/standard/tokens/metadata#snake-data-encoding).\n\n```func\ncell get_nft_content(int index, cell individual_nft_content) method_id {\n  var (_, _, content, _, _) = load_data();\n  slice cs = content.begin_parse();\n  cs~load_ref();\n  slice common_content = cs~load_ref().begin_parse();\n  return (begin_cell()\n                      .store_uint(1, 8) ;; offchain tag\n                      .store_slice(common_content)\n                      .store_ref(individual_nft_content)\n          .end_cell());\n}\n```\n\n## Item\n\nThe full source code is in [nft-item.fc](https://github.com/ton-blockchain/token-contract/blob/1182ad99413242f09925d50e70ccb7e0e09f94d4/nft/nft-item.fc) file.\n\nThe TEP‑62 standard defines `transfer` and `get_static_data` messages that must be processed by the item contract, and a single `get_nft_data` get‑method that it must implement. In this contract, the reference implementation does not go beyond the requirements and only implements these three core features.\n\n| Capability                                                    | Requirement                                    |\n| ------------------------------------------------------------- | ---------------------------------------------- |\n| `get_nft_data` (get-method)                                   | Required by TEP-62, data format follows TEP-64 |\n| `transfer` (inbound internal message)                         | Required by TEP-62                             |\n| `excesses`, `ownership_assigned` (outbound internal messages) | Required by TEP-62                             |\n| `get_static_data`, `report_static_data` (internal messages)   | Required by TEP-62                             |\n\n### Storage\n\nSame as for the collection, the storage schema itself is not defined by the standard and it can be arbitrary. This contract stores only the essentials: the `index` of the item, `collection_address`, `owner_address`, and `content` with individual item content. An important consideration with this contract is that it has two states: initialized or not initialized. It is made this way to properly support deployments only by the collection contract. When the item is not initialized yet, it only has an index and collection address. Below are `load_data` and `store_data` for the item contract. Note that `load_data` also returns as the first value the boolean initialization flag, equal to `-1` if the item is initialized and `0` if not.\n\n```func\n(int, int, slice, slice, cell) load_data() {\n    slice ds = get_data().begin_parse();\n    var (index, collection_address) = (ds~load_uint(64), ds~load_msg_addr());\n    if (ds.slice_bits() > 0) { ;; initialized\n      return (-1, index, collection_address, ds~load_msg_addr(), ds~load_ref());\n    } else { ;; not initialized\n      return (0, index, collection_address, null(), null()); ;; nft not initialized yet\n    }\n}\n\n() store_data(int index, slice collection_address, slice owner_address, cell content) impure {\n    set_data(\n        begin_cell()\n            .store_uint(index, 64)\n            .store_slice(collection_address)\n            .store_slice(owner_address)\n            .store_ref(content)\n            .end_cell()\n    );\n}\n```\n\n### Internal messages\n\nThere is a boilerplate helper function for sending messages in this contract, for convenience. It composes and sends a message by taking high‑level arguments like `op` and `payload`:\n\n```func\n() send_msg(slice to_address, int amount, int op, int query_id, builder payload, int send_mode) impure inline {\n  var msg = begin_cell()\n    .store_uint(0x10, 6) ;; nobounce - int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool src:MsgAddress\n    .store_slice(to_address)\n    .store_coins(amount)\n    .store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)\n    .store_uint(op, 32)\n    .store_uint(query_id, 64);\n\n  if (~ builder_null?(payload)) {\n    msg = msg.store_builder(payload);\n  }\n\n  send_raw_message(msg.end_cell(), send_mode);\n}\n```\n\nThe `recv_internal` function begins with boilerplate code for parsing flags, the sender address, and estimating the forward fee. The forward fee estimation assumes that all outbound messages will not be larger than the inbound message, and calculates the original forward fee of the inbound message as an upper bound. The `muldiv` operation multiplying the `fwd_fee` by 3 and dividing by 2 is an outdated way of doing that, as there exists a `get_original_fwd_fee` function which mostly does the same thing (see [TVM instructions → `GETORIGINALFWDFEE`](/tvm/instructions#f83a-getoriginalfwdfee)).\n\n```func\n() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure {\n    if (in_msg_body.slice_empty?()) { ;; ignore empty messages\n        return ();\n    }\n\n    slice cs = in_msg_full.begin_parse();\n    int flags = cs~load_uint(4); ;; the `int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool` part of CommonMsgInfo\n\n    if (flags & 1) { ;; ignore all bounced messages by checking last bit of `flags` variable\n        return ();\n    }\n    slice sender_address = cs~load_msg_addr(); ;; the `src:MsgAddressInt` part of CommonMsgInfo\n\n    cs~load_msg_addr(); ;; skip `dest:MsgAddressInt`\n    cs~load_coins(); ;; skip `grams:Grams` from `value:CurrencyCollection`\n    cs~skip_bits(1); ;; skip `other:ExtraCurrencyCollection` from `value:CurrencyCollection`\n    cs~load_coins(); ;; skip ihr_fee:Grams\n    int fwd_fee = muldiv(cs~load_coins(), 3, 2); ;; use the inbound message's fwd_fee to estimate an upper bound for outbound messages\n    ;; ...\n}\n```\n\nLoad the data and handle the uninitialized state by checking that the sender is the collection contract. If so, parse the message body and save the new `content` and `owner_address`:\n\n```func\n() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure {\n    ;; ...\n    (int init?, int index, slice collection_address, slice owner_address, cell content) = load_data();\n    if (~ init?) {\n      throw_unless(405, equal_slices(collection_address, sender_address));\n      store_data(index, collection_address, in_msg_body~load_msg_addr(), in_msg_body~load_ref());\n      return ();\n    }\n    ;; ...\n}\n```\n\nParse `op` and `query_id` from the incoming message body:\n\n```func\n() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure {\n    ;; ...\n    int op = in_msg_body~load_uint(32);\n    int query_id = in_msg_body~load_uint(64);\n    ;; ...\n}\n```\n\nAnd then there are two conditions for opcodes, processing either `transfer` or `get_static_data` messages required by the standard.\n\n#### Transfer ownership\n\nThe `transfer` message's structure is defined by the standard. It must contain, apart from the opcode and `query_id`: `new_owner` (the destination address of the item transfer), `response_destination` (an address where the contract should send the remaining TON left after the transfer along with a confirmation message), `custom_payload` for extensions of the standard and additional custom logic, `forward_amount` (amount of TON to send to a new owner with the item transfer), and `forward_payload` (a cell for any arbitrary data to send to a new owner with the item transfer).\n\nThe `transfer` message handler checks whether the `sender_address` equals `owner_address`, then parses fields from the message. While parsing, it checks them for validity. The new owner's address must have a workchain equal to a constant specified in source code. This is a safety measure made to prevent troubles with differences in transaction fees between workchains.\n\nThen it checks all the TON amounts to make sure it has enough balance to complete the transfer. After that it finally completes the transfer by updating the `owner_address` field in storage. It also sends from 0 to 2 messages, depending on whether a response is required and whether there is any `forward_amount`. The `custom_payload` is ignored in this implementation.\n\nThe response message has the `excesses` opcode and only contains the original `query_id`, with its only purpose being forwarding the remaining TON value of the transfer message to some address, usually the sender address.\n\nThe `ownership_assigned` message is sent only if `forward_amount` is greater than 0. It has the `ownership_assigned` opcode and includes `query_id`, previous `owner_address`, and the `forward_payload`, which at this point in code is the only thing left in `in_msg_body` from the original transfer message. This message is often used for processing item transfers in destination smart contracts, as well as attaching comments to transfers, and attaching any TON value by specifying `forward_amount`.\n\n```func\n() transfer_ownership(int my_balance, int index, slice collection_address, slice owner_address, cell content, slice sender_address, int query_id, slice in_msg_body, int fwd_fees) impure inline {\n    throw_unless(401, equal_slices(sender_address, owner_address));\n\n    slice new_owner_address = in_msg_body~load_msg_addr();\n    force_chain(new_owner_address);\n    slice response_destination = in_msg_body~load_msg_addr();\n    in_msg_body~load_int(1); ;; this nft don't use custom_payload\n    int forward_amount = in_msg_body~load_coins();\n    throw_unless(708, slice_bits(in_msg_body) >= 1);\n\n    int rest_amount = my_balance - min_tons_for_storage();\n    if (forward_amount) {\n      rest_amount -= (forward_amount + fwd_fees);\n    }\n    int need_response = response_destination.preload_uint(2) != 0; ;; if NOT addr_none: 00\n    if (need_response) {\n      rest_amount -= fwd_fees;\n    }\n\n    throw_unless(402, rest_amount >= 0); ;; base nft spends fixed amount of gas, will not check for response\n\n    if (forward_amount) {\n      send_msg(new_owner_address, forward_amount, op::ownership_assigned(), query_id, begin_cell().store_slice(owner_address).store_slice(in_msg_body), 1);  ;; paying fees, revert on errors\n    }\n    if (need_response) {\n      force_chain(response_destination);\n      send_msg(response_destination, rest_amount, op::excesses(), query_id, null(), 1); ;; paying fees, revert on errors\n    }\n\n    store_data(index, collection_address, new_owner_address, content);\n}\n\n() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure {\n    ;; ...\n    if (op == op::transfer()) {\n      transfer_ownership(my_balance, index, collection_address, owner_address, content, sender_address, query_id, in_msg_body, fwd_fee);\n      return ();\n    }\n    ;; ...\n}\n```\n\n#### Report static data\n\nOn `get_static_data`, respond with `report_static_data` containing the item's `index` and `collection` address. This handler composes and sends a message with the index and collection address in the body.\n\n```func\n() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure {\n    ;; ...\n    if (op == op::get_static_data()) {\n      send_msg(sender_address, 0, op::report_static_data(), query_id, begin_cell().store_uint(index, 256).store_slice(collection_address), 64);  ;; carry all the remaining value of the inbound message\n      return ();\n    }\n    ;; ...\n}\n```\n\nFinally, if none of the conditions above are met, which means that the opcode provided in the message does not match any of the expected ones, it throws `0xffff`, which is a common exit code for unknown‑opcode errors:\n\n```func\n() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure {\n    ;; ...\n    throw(0xffff);\n}\n```\n\n### Get-methods\n\nThe standard only requires the `get_nft_data` get‑method.\n\n#### Return item data\n\nThe get‑method `get_nft_data` returns the `init?` flag (whether the item is initialized), `index`, `collection_address`, `owner_address`, and `individual_content`. In this implementation, it returns all the values from `load_data` as is, including the logic for setting the `init?` flag.\n\nImportantly, the `content` returned by this contract follows the format required by the collection contract, where it only includes the suffix of the URL pointing to an off‑chain JSON with metadata. But this is not forced by the standard, and the format can be arbitrary. The only requirements are that the collection's `get_nft_content` must return full content following TEP‑64, and that if the item has no collection it must return full content right away at this point, but the latter is out of scope here.\n\n```func\n(int, int, slice, slice, cell) get_nft_data() method_id {\n  (int init?, int index, slice collection_address, slice owner_address, cell content) = load_data();\n  return (init?, index, collection_address, owner_address, content);\n}\n```\n"
  },
  {
    "path": "standard/tokens/nft/sbt.mdx",
    "content": "---\ntitle: \"SBT: How it works\"\nsidebarTitle: \"SBT: How it works\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nSoul-Bound Tokens (SBTs) represent non-transferable digital credentials in the TON ecosystem. Unlike standard NFTs, SBTs are permanently bound to their owner and cannot be transferred to another address after minting. The canonical specification is defined in [TEP-85](https://github.com/ton-blockchain/TEPs/blob/c5bfe285ef91810fab02c5352593f5a1455458bf/text/0085-sbt-standard.md).\n\nThe SBT standard provides a general interaction scheme while leaving the specific implementation of related contracts to developers.\n\n## Contract data storage\n\nThe SBT standard defines what data must be stored in the contract. Each SBT contract must store the following fields:\n\n| Field                | Type         | Description                                           |\n| -------------------- | ------------ | ----------------------------------------------------- |\n| `index`              | `uint256`    | SBT identifier                                        |\n| `collection_address` | `MsgAddress` | Collection address                                    |\n| `owner`              | `MsgAddress` | Owner address                                         |\n| `content`            | `Cell`       | SBT content/metadata                                  |\n| `authority`          | `MsgAddress` | Authority address that can revoke the SBT             |\n| `revoked_at`         | `uint64`     | Revocation time in Unix format, or `0` if not revoked |\n\n<Aside type=\"note\">\n  The standard defines **what** must be stored in the contract, but does not specify **how** exactly this data should be structured in storage. Developers are free to choose their own implementation.\n</Aside>\n\n## Message layouts\n\nInteractions with SBT contracts, which are most often encountered by users and developers, are:\n\n- prove ownership: sending proof of SBT ownership to a destination contract.\n- request current owner: requesting current owner information from SBT.\n- destroy SBT: destroying the SBT contract and returning remaining balance.\n- revoke SBT: marking the SBT as revoked by authority.\n\n<Aside type=\"note\">\n  All message schemes include the `query_id` field. This field is primarily used for off-chain parsing and linking request-response pairs. The protocol itself does not require it for on-chain logic.\n</Aside>\n\n## Bound to single owner\n\nThe `owner` field is set during minting and remains immutable. The following sections describe the key operations and their message flows.\n\n## Prove ownership\n\n```mermaid\nsequenceDiagram\n  participant U as Owner\n  participant S as SBT\n  participant D as Destination\n\n  U->>S: prove_ownership\n  alt owner\n    S->>D: ownership_proof\n  else not owner\n    S-->>U: reject\n  end\n```\n\nThis message flow allows the `owner` to ask the SBT to send a proof to a destination contract confirming that they own this SBT. May include arbitrary `forward_payload` and optionally attach `content`.\n\n### Prove ownership message (inbound to SBT)\n\n```tlb title=\"TL-B\"\n;; Inbound message to SBT\nprove_ownership#04ded148 query_id:uint64 destination:MsgAddress\n  forward_payload:^Cell with_content:Bool = InternalMsgBody;\n```\n\n| Name              | Type         | Description                                               |\n| ----------------- | ------------ | --------------------------------------------------------- |\n| `query_id`        | `uint64`     | Arbitrary identifier to link request and response.        |\n| `destination`     | `MsgAddress` | Address of the destination contract to receive the proof. |\n| `forward_payload` | `Cell`       | Arbitrary data forwarded to the destination contract.     |\n| `with_content`    | `Bool`       | If `true`, attach SBT `content` to the proof.             |\n\n### Ownership proof message (SBT -> destination contract)\n\n```tlb title=\"TL-B\"\n;; SBT response to the destination contract (if checks pass)\nownership_proof#0524c7ae query_id:uint64 item_id:uint256 owner:MsgAddress\n  data:^Cell revoked_at:uint64 content:(Maybe ^Cell) = InternalMsgBody;\n```\n\n| Name         | Type         | Description                                        |\n| ------------ | ------------ | -------------------------------------------------- |\n| `query_id`   | `uint64`     | Matches the `query_id` from the request.           |\n| `item_id`    | `uint256`    | Identifier of the SBT item.                        |\n| `owner`      | `MsgAddress` | Current owner address.                             |\n| `data`       | `Cell`       | Equals `forward_payload` from the request.         |\n| `revoked_at` | `uint64`     | Revoke time if SBT is revoked, `0` otherwise.      |\n| `content`    | `Maybe Cell` | SBT content if requested with `with_content=true`. |\n\nThe transaction is rejected if the sender is not the `owner`.\n\n## Request current owner\n\nThis message flow allows any initiator to ask the SBT to send the current `owner` (and optionally the `content`) to a destination contract.\n\n```mermaid\nsequenceDiagram\n  participant I as Initiator\n  participant S as SBT\n  participant D as Destination\n\n  I->>S: request_owner\n  S->>D: owner_info\n```\n\n### Request owner message (inbound to SBT)\n\n```tlb title=\"TL-B\"\n;; Inbound message to SBT\nrequest_owner#d0c3bfea query_id:uint64 destination:MsgAddress\n  forward_payload:^Cell with_content:Bool = InternalMsgBody;\n```\n\n| Name              | Type         | Description                                              |\n| ----------------- | ------------ | -------------------------------------------------------- |\n| `query_id`        | `uint64`     | Arbitrary identifier to link request and response.       |\n| `destination`     | `MsgAddress` | Address of the destination contract to receive the info. |\n| `forward_payload` | `Cell`       | Arbitrary data forwarded to the destination contract.    |\n| `with_content`    | `Bool`       | If `true`, attach SBT `content` in the response.         |\n\n### Owner info message (SBT -> destination contract)\n\n```tlb title=\"TL-B\"\n;; SBT response to the destination contract\nowner_info#0dd607e3 query_id:uint64 item_id:uint256 initiator:MsgAddress owner:MsgAddress\n  data:^Cell revoked_at:uint64 content:(Maybe ^Cell) = InternalMsgBody;\n```\n\n| Name         | Type         | Description                                |\n| ------------ | ------------ | ------------------------------------------ |\n| `query_id`   | `uint64`     | Matches the `query_id` from the request.   |\n| `item_id`    | `uint256`    | Identifier of the SBT item.                |\n| `initiator`  | `MsgAddress` | Address of the requester.                  |\n| `owner`      | `MsgAddress` | Current owner address.                     |\n| `data`       | `Cell`       | Equals `forward_payload` from the request. |\n| `revoked_at` | `uint64`     | Revoke time if revoked, `0` otherwise.     |\n| `content`    | `Maybe Cell` | SBT content if requested.                  |\n\n## Destroy\n\nThis message flow allows the `owner` to destroy the SBT contract. This clears the `owner` and `authority` fields, and sends remaining balance back to the sender via an `excesses` message.\n\n```mermaid\nsequenceDiagram\n  participant U as Owner\n  participant S as SBT\n\n  U->>S: destroy(query_id)\n  alt owner\n    S->>S: owner = null, authority = null\n    S-->>U: excesses(query_id)\n  else not owner\n    S-->>U: reject\n  end\n```\n\n### Destroy message (inbound to SBT)\n\n```tlb title=\"TL-B\"\n;; Internal message to SBT\ndestroy#1f04537a query_id:uint64 = InternalMsgBody;\n```\n\n| Name       | Type     | Description                                        |\n| ---------- | -------- | -------------------------------------------------- |\n| `query_id` | `uint64` | Arbitrary identifier to link request and response. |\n\n### Excesses message (SBT -> sender)\n\n```tlb title=\"TL-B\"\n;; Excess returned to the sender\nexcesses#d53276db query_id:uint64 = InternalMsgBody;\n```\n\n| Name       | Type     | Description                              |\n| ---------- | -------- | ---------------------------------------- |\n| `query_id` | `uint64` | Matches the `query_id` from the request. |\n\nThe transaction is rejected if the sender is not the `owner`.\n\n## Revoke SBT\n\nThis message flow allows the `authority` to mark the SBT as revoked. Revoking twice is disallowed.\n\n```mermaid\nsequenceDiagram\n  participant A as Authority\n  participant S as SBT\n\n  A->>S: revoke(query_id)\n  alt A == authority and not revoked\n    S->>S: revoked_at = now\n  else not authority or already revoked\n    S-->>A: reject\n  end\n```\n\n### Revoke message (inbound to SBT)\n\n```tlb title=\"TL-B\"\n;; Inbound message to SBT\nrevoke#6f89f5e3 query_id:uint64 = InternalMsgBody;\n```\n\n| Name       | Type     | Description                                 |\n| ---------- | -------- | ------------------------------------------- |\n| `query_id` | `uint64` | Arbitrary identifier for off-chain parsing. |\n\nThe transaction is rejected if:\n\n- the sender is not the `authority`;\n- the SBT was already revoked.\n"
  },
  {
    "path": "standard/tokens/nft/transfer.mdx",
    "content": "---\ntitle: \"How to transfer an NFT\"\nsidebarTitle: \"How to transfer\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nNFT transfer is an operation specified in [TEP 0062](/standard/tokens/nft/how-it-works#transfer-nft-item). Its implementation must comply with this standard, and NFT item contracts must support the logic described there. The NFT transfer message is also specified and must comply with the corresponding [TL-B scheme](/standard/tokens/nft/how-it-works#transfer-nft-item). This scheme involves, among other things,\n\n- `forward_amount`: the amount of nanotons to be sent to the destination address;\n- `forward_payload`: optional custom data that should be sent to the destination address.\n\nFor the `forward_payload` field there are specific requirements:\n\n- In the case of a simple comment, `forward_payload` must starts with `0x00000000` and the comment must be contained in the remainder of the `forward_payload`. In turn, if the comment\n  - begins with the byte `0xff`, the remainder is a \"binary comment\", which should not be displayed to the end user as text (only as hex dump if necessary). The intended use of \"binary comments\" is, e.g., to contain a purchase identifier for payments in a store, to be automatically generated and processed by the store's software.\n  - does not begin with the byte `0xff`, the comment is a text one; it can be displayed \"as is\" to the end user of a wallet.\n- If `forward_payload` contains a binary message for interacting with the destination smart contract, then there are no prefixes.\n\nUse a wallet app that supports NFTs (for example, [Tonkeeper](https://tonkeeper.helpscoutdocs.com/article/47-how-to-send-nft-to-another-wallet)) and follow its guide. Alternatively, perform the transfer manually. The example below illustrates a programmatic transfer:\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  Beware that API keys and mnemonic must not be committed or shared publicly.\n\n  A better approach is to use a `.env` file that is excluded from repository with `.gitignore`. For GitHub CI purposes, consult [their documentation](https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets).\n</Aside>\n\n```typescript\nimport { WalletContractV5R1, TonClient, Address, toNano } from \"@ton/ton\";\n\nimport { mnemonicToPrivateKey } from \"@ton/crypto\";\n\nimport { AssetsSDK, createApi } from \"@ton-community/assets-sdk\";\n\nasync function main() {\n    const client = new TonClient({\n        endpoint: \"https://toncenter.com/api/v2/jsonRPC\",\n    });\n\n    const MNEMONIC = process.env.MNEMONIC as string; // set via environment\n    const keyPair = await mnemonicToPrivateKey(MNEMONIC.split(\" \"));\n\n    const wallet = WalletContractV5R1.create({\n        workchain: 0,\n        publicKey: keyPair.publicKey,\n    });\n\n    const provider = client.provider(wallet.address);\n    const sender = wallet.sender(provider, keyPair.secretKey);\n\n    const NETWORK = \"testnet\";\n    const api = await createApi(NETWORK);\n\n    const sdk = AssetsSDK.create({\n        api,\n        sender,\n    });\n\n    const NFT_ADDRESS = Address.parse(\"<NFT_ITEM_ADDR>\");\n    const nftItem = await sdk.openNftItem(NFT_ADDRESS);\n\n    const RECEIVER_ADDRESS = Address.parse(\"<RECEIVER_ADDR>\");\n    await nftItem.send(sender, RECEIVER_ADDRESS, { value: toNano(10) });\n}\n\nvoid main();\n```\n\nwhere:\n\n- `<NFT_ITEM_ADDR>` — the address of the NFT item to be transferred.\n- `<RECEIVER_ADDR>` — the address of the recipient.\n"
  },
  {
    "path": "standard/tokens/nft/verify.mdx",
    "content": "---\ntitle: \"How to verify NFT item\"\nsidebarTitle: \"How to verify NFT item\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nBecause the collection is the source of truth, verification goes through it:\n\n1. Read the NFT item index from the item contract via [get\\_nft\\_data()](/standard/tokens/nft/api#get-nft-data).\n1. Query the collection with [get\\_nft\\_address\\_by\\_index(index)](/standard/tokens/nft/api#get-nft-address-by-index).\n1. If the returned address equals the NFT item address, the item belongs to the collection.\n\n### High level\n\nThere is an [API method](/ecosystem/api/toncenter/v3/nfts/get-nft-items?playground=open) that performs this verification off‑chain with a single request. Provide the addresses of the NFT item and NFT collection:\n\n```ts TypeScript\nasync function main() {\n  const itemAddress = \"EQD3LzasMd4GAmhIEkCQ4k6LnziTqNZ6VPtRfeZKHu0Fmkho\";\n  const collectionAddress = \"EQCOtGTvX-RNSaiUavmqNcDeblB3-TloZpvYuyGOdFnfy-1N\";\n\n  const url = `https://toncenter.com/api/v3/nft/items?limit=1&address=${itemAddress}&collection_address=${collectionAddress}`;\n  const options = { method: \"GET\", body: undefined };\n\n  try {\n    const response = await fetch(url, options);\n    const data = await response.json();\n\n    if (data[\"nft_items\"].length > 0) {\n      console.log(\"✅ item in collection\");\n    } else {\n      console.log(\"❌ item not in collection\");\n    }\n  } catch (error) {\n    console.error(error);\n  }\n}\n\nmain();\n```\n\n### Low level\n\nFirst, read the NFT item index. If the collection returns the same NFT item address for that index, the item belongs to the collection.\n\n```ts TypeScript\nimport { Address, Cell } from \"@ton/ton\";\n\nasync function main() {\n  const itemAddress = \"EQD3LzasMd4GAmhIEkCQ4k6LnziTqNZ6VPtRfeZKHu0Fmkho\";\n  const collectionAddress = \"EQCOtGTvX-RNSaiUavmqNcDeblB3-TloZpvYuyGOdFnfy-1N\";\n\n  const url = \"https://toncenter.com/api/v2/runGetMethod\";\n\n  const itemPayload = {\n    address: itemAddress,\n    stack: [] as any[],\n    method: \"get_nft_data\",\n  };\n\n  const headers = {\n    \"Content-Type\": \"application/json\",\n  };\n\n  try {\n    const itemResp = await fetch(url, {\n      method: \"POST\",\n      headers,\n      body: JSON.stringify(itemPayload),\n    });\n\n    if (!itemResp.ok) {\n      throw new Error(\n        `Item request failed: ${itemResp.status} ${itemResp.statusText}`,\n      );\n    }\n\n    const itemJson: any = await itemResp.json();\n\n    const itemStack = itemJson?.result?.stack;\n    if (!Array.isArray(itemStack) || !Array.isArray(itemStack[1])) {\n      throw new Error(\"Unexpected item stack format\");\n    }\n    const hex = String(itemStack[1][itemStack[1].length - 1] ?? \"\");\n    const itemIndex = Number.parseInt(\n      hex.startsWith(\"0x\") ? hex.slice(2) : hex,\n      16,\n    );\n\n    const collectionPayload = {\n      address: collectionAddress,\n      stack: [[\"int\", itemIndex]],\n      method: \"get_nft_address_by_index\",\n    };\n\n    await new Promise((resolve) => setTimeout(resolve, 2000));\n\n    const colResp = await fetch(url, {\n      method: \"POST\",\n      headers,\n      body: JSON.stringify(collectionPayload),\n    });\n\n    if (!colResp.ok) {\n      throw new Error(\n        `Collection request failed: ${colResp.status} ${colResp.statusText}`,\n      );\n    }\n\n    const realAddress = await colResp.json();\n    console.log(\"itemIndex:\", itemIndex);\n\n    const b64 = realAddress?.result?.stack?.[0][1].bytes as string;\n    const boc = Buffer.from(b64, \"base64\");\n\n    const cell = Cell.fromBoc(boc)[0];\n    const slice = cell.beginParse();\n    const resAddress = slice.loadAddress();\n\n    if (resAddress.toString() == Address.parse(itemAddress).toString()) {\n      console.log(\"✅ item in collection\");\n    } else {\n      console.log(\"❌ item not in collection\");\n    }\n  } catch (error) {\n    console.error(error);\n  }\n}\n\nmain();\n```\n"
  },
  {
    "path": "standard/tokens/overview.mdx",
    "content": "---\ntitle: \"Token overview\"\nsidebarTitle: \"Overview\"\n---\n\nThis article compares different kinds of Tokens in TON.\n\nThe TON blockchain supports three distinct categories of digital tokens, each designed to serve different purposes within the ecosystem.\n\n- [Fungible tokens](/standard/tokens/jettons/overview) (Jettons) - this is a web3 way to create new currency on your own\n- [Non-Fungible Tokens](/standard/tokens/nft/overview) (NFTs) - like Jettons, but each token is unique and represents a distinct entity\n- [Soul-bound Tokens](/standard/tokens/nft/comparison#sbt) (SBTs) - like NFTs, but not-transferable, bound to a single owner\n\n## Comparison table\n\n| Feature              | Jettons           | NFTs                 | SBTs                  |\n| -------------------- | ----------------- | -------------------- | --------------------- |\n| **Fungibility**      | Fungible          | Non-fungible         | Non-fungible          |\n| **Transferability**  | ✅ Transferable.  | ✅ Transferable      | ❌ Non-transferable   |\n| **Divisibility**     | ✅ Divisible      | ❌ Indivisible       | ❌ Indivisible        |\n| **Primary use case** | Currency, utility | Art, collectibles    | Credentials, identity |\n| **Value type**       | Monetary value    | Unique value         | Reputational value    |\n| **Ownership model**  | Liquid ownership  | Verifiable ownership | Permanent binding     |\n| **Standard**         | TEP-0074          | TEP-0062             | TEP-0085              |\n\n## Token verification\n\n- A token is marked as \"unverified\" if it is not included in the [token asset list](https://github.com/tonkeeper/ton-assets).\n- A token may be marked as \"scam\" if it contains misleading metadata or has been reported.\n\nToken verification is managed through the public repository [`tonkeeper / ton-assets`](https://github.com/tonkeeper/ton-assets). This repository contains approved token metadata.\n\nHow verification works:\n\n1. Check whether the token address is already listed in the repository.\n1. If it is not present, submit a pull request adding its metadata to the appropriate directory.\n1. Maintainers review the submission.\n1. Once merged, the token status will be updated.\n"
  },
  {
    "path": "standard/vesting.mdx",
    "content": "---\ntitle: \"Vesting contracts\"\nsidebarTitle: \"Vesting\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\nimport { Image } from '/snippets/image.jsx';\n\nA [vesting contract](https://en.wikipedia.org/wiki/Vesting) is a financial agreement that outlines how and when an individual earns rights to certain assets over a specified period. On TON, vesting contracts enable secure, scheduled distribution of Toncoin assets with built-in staking capabilities.\n\n## What is vesting\n\nVesting is a mechanism that locks assets for a defined period and gradually releases them according to a predetermined schedule. Traditional vesting includes a cliff period where no rights are granted initially, followed by gradual vesting over time.\n\nOn TON, vesting contracts function as smart escrow services that lock Toncoin and release it according to configurable parameters. These contracts also support staking locked funds, allowing recipients to earn rewards while tokens remain locked.\n\n## How staking works with vesting\n\nWhen funds are locked in a vesting contract, they cannot be sent to arbitrary addresses until unlocked. However, the contract supports a whitelist mechanism that allows sending locked funds to specific, approved destinations—primarily for staking purposes.\n\nThe vesting sender controls which addresses can receive locked funds by adding them to a whitelist. This security measure ensures that locked funds can only move to trusted, verified contracts that support staking operations.\n\nOnce whitelisted, locked funds can be staked through various methods:\n\n- Direct validation through the system Elector\n- Single nominator pools\n- Liquid staking protocols\n- Standard nominator pools\n\nStaking rewards accumulate normally and remain accessible even while funds are locked. The vesting contract enforces restrictions only on destinations, not on the funds themselves once they are staked.\n\n## Contract capabilities\n\nA vesting contract operates with two key roles:\n\n**Vesting sender**: The entity that creates the contract and locks the funds. The sender can:\n\n- Add addresses to the whitelist at any time\n- Receive funds back to their address at any time (even if locked)\n- Cannot remove addresses from the whitelist once added\n\n**Owner**: The recipient of the vesting contract who can:\n\n- Send funds from the contract to whitelisted addresses or the sender address\n- Send unlocked funds to any address after the vesting period ends\n- Stake funds through approved methods\n\nThe contract maintains a whitelist of approved destinations. Funds can be sent to whitelisted addresses even while locked, enabling staking operations. Once unlocked, funds can be sent anywhere without restrictions.\n\n## Unlock mechanism\n\nThe vesting contract uses a time-based unlock schedule with these parameters:\n\n- **Vesting start time**: Unix timestamp when the vesting period begins\n- **Total duration**: Total vesting period in seconds (e.g., 31,104,000 for one year)\n- **Unlock period**: Time interval between releases in seconds (e.g., 2,592,000 for monthly)\n- **Cliff duration**: Initial lock period before the first release (e.g., 5,184,000 for two months)\n\nBefore the vesting start time, all funds are locked. After the start time, funds unlock proportionally according to the schedule. If a cliff period exists, nothing unlocks during that time. Once the cliff ends, funds unlock according to the formula.\n\nExample: With a total duration of 10 months, unlock period of 1 month, and total amount of 500 TON, the contract unlocks 50 TON each month. If a 3-month cliff exists, nothing unlocks for the first 3 months, then 150 TON unlocks at once, followed by 50 TON monthly.\n\nUse the `get_locked_amount(int at_time)` method to calculate how much remains locked at any specific time.\n\n<Image\n  src=\"/resources/images/vesting/vesting_chart_light.png\"\n  darkSrc=\"/resources/images/vesting/vesting_chart_dark.png\"\n  alt=\"Vesting schedule\"\n/>\n\n## Deploy and verify a vesting contract\n\nDeploying a vesting contract requires careful verification before sending funds. Follow these steps:\n\n### Step 1: Prepare recipient wallet\n\nThe vesting sender requests the recipient's TON wallet address. If the wallet is not deployed, the sender transfers 1 TON to the recipient and requests they send it back. This verifies wallet access and ensures deployment.\n\n### Step 2: Create the vesting contract\n\n1. Visit [vesting.ton.org](https://vesting.ton.org/)\n1. Enter the recipient's wallet address in the \"Address\" field\n1. Select \"Create new vesting for this user\"\n\n### Step 3: Configure vesting parameters\n\nProvide these details:\n\n- **Vesting start date**: Choose a deferred date for lockup without accumulation before the date\n- **Total amount**: Total vesting amount in TON\n- **Total vesting duration**: Duration in days (including cliff), e.g., 760 days for 2 years\n- **Cliff duration**: Period in days after vesting starts when vesting accumulates but cannot be withdrawn (zero if no cliff)\n- **Unlocking frequency**: Frequency in days (equal to total duration if no partial unlocking), e.g., 30 days for monthly\n- **In masterchain**: Check this if direct validation from the vesting wallet is required. Direct validation means participating in the blockchain's proof-of-stake consensus as a validator with a stake of 300,000 TON or more\n- **Whitelist addresses**: Add addresses for staking contracts (e.g., single nominator pool addresses)\n\nConstraints:\n\n- Total vesting duration must be divisible by unlocking frequency\n- Cliff duration must be divisible by unlocking frequency\n\n### Step 4: Deploy and verify\n\n1. Select \"Create\" to generate the vesting wallet contract (costs 0.5 TON)\n1. The vesting wallet page opens after creation\n1. Verify all parameters are correct before proceeding\n1. Share the link with the recipient so they can verify parameters\n\n### Step 5: Verify contract code hash\n\nBefore sending funds to the deployed contract, verify the contract code hash matches the official version:\n\n**Official vesting contract code hash**: `b48b531abec3b714638291f7d77ed6dc9f6a2729efca20477137374d4ae8b590`\n\nTo verify:\n\n1. Open the vesting contract address in a [block explorer]\n1. Check the contract code hash\n1. Verify it matches the official hash above\n\n<Aside\n  type=\"danger\"\n  title=\"Security: Verify code hash\"\n>\n  Never send funds to a vesting contract until the code hash is verified to match the official version. A mismatched code hash indicates a modified or malicious contract that could steal funds.\n</Aside>\n\n### Step 6: Verify parameters via get-method\n\nAfter deployment but before sending funds, verify all parameters using the `get_vesting_data()` get-method:\n\n- Confirm all time parameters match expectations\n- Verify sender and owner addresses are correct\n- Check that duration constraints are satisfied\n\nExample result on [Tonviewer](/ecosystem/explorers/tonviewer):\n\n<Image\n  src=\"/resources/images/vesting/getmethod.png\"\n  alt=\"Get-method result example on Tonviewer\"\n/>\n\n### Step 7: Send funds\n\nOnly after verification is complete, send the vesting amount to the contract address from any wallet.\n\n## Reviewing contracts for whitelist\n\nBefore adding any address to the whitelist, verify the contract is legitimate and safe:\n\n1. **Check contract verification**: Use a [block explorer] to verify the contract is verified and matches known contract code hashes\n1. **Verify contract type**: Confirm the contract is one of the supported types (single nominator pool, liquid staking protocol, etc.)\n1. **Review contract source**: If available, review the contract source code or audit reports\n1. **Check operational history**: Review the contract's transaction history for suspicious activity\n1. **Verify addresses**: Double-check addresses match official documentation from the protocol\n\nSupported whitelist destinations include:\n\n- System Elector address (`-1:3333333333333333333333333333333333333333333333333333333333333333`)\n- System Config address (`-1:5555555555555555555555555555555555555555555555555555555555555555`)\n- Single nominator pool contracts\n- Liquid staking protocol contracts (Tonstakers, Bemo)\n- Standard nominator pool contracts\n- Whales nominator pool contracts\n\nTechnically, any address can be added to the whitelist, including regular wallet addresses like wallet-v4. However, adding a wallet address defeats the purpose of vesting, as the owner would be able to withdraw locked funds immediately. Whitelist addresses should only include contracts that support staking operations and cannot be used for direct withdrawals.\n\n<Aside\n  type=\"caution\"\n  title=\"Whitelist security\"\n>\n  Once an address is added to the whitelist, it cannot be removed. Review all addresses carefully before adding them. Only add addresses from trusted, verified protocols.\n</Aside>\n\n## Sending messages via UI\n\nThe vesting contract can be managed through the [vesting.ton.org](https://vesting.ton.org/) interface:\n\n1. Open the vesting contract page using the shared link\n1. Connect the owner wallet\n1. Select \"Send from Vesting\" to create a new transaction\n1. Enter the destination address\n1. Enter the amount\n1. For staking operations, add the appropriate message body:\n\n   - Empty message for single nominator pools or Bemo\n   - Text comment \"d\" for standard nominator pools (deposit)\n   - Text comment \"w\" for standard nominator pools (withdraw)\n   - Text comment \"Stake\" for Whales pools\n   - Text comment \"Withdraw\" for Whales pools\n\n   Select the message format: Text, Base64, or HEX. Use Text for simple text comments, and Base64 or HEX for serialized BoC messages (e.g., Tonstakers deposit operations).\n1. Review and confirm the transaction\n\nThe interface handles message formatting automatically, ensuring compliance with whitelist restrictions.\n\n## Security measures\n\nVesting contracts include multiple security layers:\n\n### Whitelist restrictions\n\nMessages sent to whitelisted addresses must:\n\n- Use `send_mode == 3` only\n- Be bounceable (non-bounceable messages are rejected)\n- Include _no_ `state_init` attachments\n\n### Operation restrictions\n\nThe contract enforces specific operation codes based on the destination address:\n\n**System Elector address**:\n\n- `op::elector_new_stake` (0x4e73744b)\n- `op::elector_recover_stake` (0x47657424)\n- `op::vote_for_complaint` (0x56744370)\n- `op::vote_for_proposal` (0x566f7465)\n\n**System Config address**:\n\n- `op::vote_for_proposal` (0x566f7465)\n\n**Other whitelisted addresses**:\n\n- Empty messages (no body)\n- Text comments where the first character is \"d\", \"w\", \"D\", or \"W\"\n- Operation codes:\n  - `op::single_nominator_pool_withdraw` (0x1000)\n  - `op::single_nominator_pool_change_validator` (0x1001)\n  - `op::ton_stakers_deposit` (0x47d54391)\n  - `op::jetton_burn` (0x595f07bc)\n  - `op::ton_stakers_vote` (0x69fb306c)\n  - `op::vote_for_proposal` (0x566f7465)\n  - `op::vote_for_complaint` (0x56744370)\n\n### Lock protection\n\nThe contract reserves locked funds when sending to non-whitelisted addresses (except the sender address). This prevents accidental loss of locked funds while allowing approved staking operations.\n\n### Sender address safety\n\nFunds can always be sent back to the vesting sender address without restrictions, even if locked. This provides a safety mechanism to return funds if needed.\n\n<Aside\n  type=\"caution\"\n  title=\"Protect owner wallet\"\n>\n  Back up the recovery phrase for the owner wallet that controls the vesting contract. If access to the owner wallet is lost, control over vesting funds cannot be recovered.\n</Aside>\n\n## Staking options\n\nVesting contracts support multiple staking methods. Each method has specific requirements and limitations.\n\n### Direct staking\n\nUse the vesting contract directly as a validator wallet.\n\n**Requirements**:\n\n- Vesting contract must be deployed in masterchain\n- Elector address must be whitelisted\n\n**Steps**:\n\n1. Request whitelisting of Elector address: `-1:3333333333333333333333333333333333333333333333333333333333333333`\n\n1. [Import](/ecosystem/nodes/cpp/mytonctrl/wallet) the private key and vesting address into MyTonCtrl and use it as a standard wallet-v3.\n\n   **Important**: Direct staking does not use owner wallet contract for management. Instead, it uses the vesting contract's public key and private key directly. By default, vesting.ton.org sets the vesting contract's public key to match the owner wallet's public key. Therefore, when importing into MyTonCtrl, use the seed phrase from the owner wallet.\n\n   **Advanced**: Advanced users can deploy a vesting contract with a different public key than the owner wallet to avoid using the same seed phrase on the validator node. This requires using deployment scripts from the [vesting-contract GitHub repository](https://github.com/ton-blockchain/vesting-contract/blob/main/wrappers/VestingWallet.ts). When deploying with a custom public key, use the seed phrase corresponding to that public key when importing into MyTonCtrl.\n\n1. Adding the Config address to the whitelist is not required for basic staking operations.\n\n1. To vote on configuration proposals, request whitelisting of the Config address: `-1:5555555555555555555555555555555555555555555555555555555555555555`\n\n**Limitations**: Requires storing the vesting private key on the validator node, which increases security risk.\n\n### Single nominator pool\n\nCreate a single nominator pool and stake through it. This is the recommended approach for most users.\n\n**Advantages**:\n\n- Vesting private key does not need to be stored on the validator node\n- Pool contract handles validator interactions\n- More secure than direct staking\n\n**Steps**:\n\n1. Deploy a single nominator pool contract\n1. Request whitelisting of the pool address from the vesting sender\n1. Once whitelisted, send locked funds to the pool using [vesting.ton.org](https://vesting.ton.org/)\n   - Destination: single nominator pool address\n   - Amount: desired stake amount\n   - Body: empty message\n1. Manage staking through MyTonCtrl with the pool contract\n\nFor detailed setup instructions, see [MyTonCtrl single nominator pool mode](/ecosystem/nodes/cpp/mytonctrl/pools#single-nominator-pool-operations-single-nominator-mode).\n\n<Aside\n  type=\"tip\"\n  title=\"Staking rewards\"\n>\n  Staking rewards are distributed according to the pool's reward scheme. See [staking rewards distribution](/ecosystem/staking/overview#nominator-validator-rewards-distribution) for details on how rewards are calculated and split between validators and nominators.\n</Aside>\n\n### Liquid staking: Tonstakers\n\nStake through the Tonstakers liquid staking protocol.\n\n**Limitations**:\n\n- Recipients can return coins from the pool (exchange tokens back to Toncoin) during vesting\n- Recipients cannot transfer `tsTON` jettons to others until vesting expires\n- Recipients cannot use `tsTON` jettons in DeFi protocols until vesting expires\n- Voting rights are unavailable during vesting\n\n**Steps**:\n\n1. Request whitelisting of Tonstakers pool: `0:a45b17f28409229b78360e3290420f13e4fe20f90d7e2bf8c4ac6703259e22fa`\n\n1. Send deposit message to the pool from vesting:\n\n   - Destination: pool address above\n   - Amount: desired stake amount\n   - Body: serialized deposit message in HEX format (not a text comment)\n\n   The deposit message uses this scheme with `query_id=0`:\n\n   ```\n   tonstakers_pool_deposit#47d54391 query_id:uint64 = InternalMsgBody;\n   ```\n\n   HEX message body: `b5ee9c7201010101000e00001847d543910000000000000000`\n\n   <Aside\n     type=\"caution\"\n     title=\"Message format\"\n   >\n     This is a serialized BoC message, not a text comment. Do not insert this into the \"Comment\" field in wallet applications. Use the HEX format option in the vesting interface.\n   </Aside>\n\n   Send this message via the [vesting.ton.org](https://vesting.ton.org/) interface by selecting HEX format.\n\n1. Find the jetton wallet address:\n\n   - Open the deposit transaction in a [block explorer]\n   - Look at the transaction trace and find the newly deployed jetton wallet\n   - Verify that:\n     - The jetton wallet is verified\n     - The \"Holder address\" equals the vesting contract address\n\n   <Image\n     src=\"/resources/images/vesting/tstakers_trace.png\"\n     alt=\"Tonstakers deposit trace\"\n   />\n\n   <Image\n     src=\"/resources/images/vesting/tstakers_jwallet.png\"\n     alt=\"Tonstakers jetton wallet\"\n   />\n\n1. Request whitelisting of the jetton wallet address. This is required to withdraw the stake later.\n\n1. To withdraw (unstake), send a burn message to the jetton wallet:\n\n   - Destination: jetton wallet address (from step 3)\n   - Amount: gas fee (\\~0.5 TON)\n   - Body: burn message with operation code `op::jetton_burn` (0x595f07bc)\n\n   <Aside\n     type=\"caution\"\n     title=\"Withdrawal amount\"\n   >\n     Specify the exact amount of `tsTON` to burn. Check the `tsTON` balance in the jetton wallet before creating the burn message.\n   </Aside>\n\n   To build the burn message cell in TypeScript, use the following code:\n\n   ```typescript\n   import { beginCell, Cell, toNano } from '@ton/core';\n\n   // jetton_burn#595f07bc query_id:uint64 jetton_amount:Coins\n   //      forward_payload:(Maybe ^Cell) = InternalMsgBody;\n\n   const jettonAmount = toNano(123); // amount of tsTON to burn\n\n   const burnMessage = beginCell()\n       .storeUint(0x595f07bc, 32) // op::jetton_burn\n       .storeUint(0, 64) // query_id\n       .storeCoins(jettonAmount) // jetton_amount\n       .storeRef(Cell.EMPTY) // forward_payload (empty)\n       .endCell();\n\n   // convert to HEX for vesting.ton.org interface\n   const hexMessage = burnMessage.toBoc().toString('hex');\n   console.log(hexMessage);\n   ```\n\n   Use the HEX output in the vesting interface when sending the burn message.\n\n### Liquid staking: Bemo\n\n[Bemo](https://bemo.finance) is a liquid staking protocol in TON. When staking TON, the protocol mints `bmTON` tokens that represent the staked position and automatically accumulate rewards.\n\n**Limitations**:\n\n- The vesting contract supports only basic staking through empty messages\n- `bmTON` jettons remain locked in the vesting contract until vesting expires\n- Jettons accumulate staking rewards automatically\n- Staking and unstaking TON is possible during vesting\n- Transferring `bmTON` to others is not possible until vesting expires\n- Using `bmTON` in DeFi protocols is not possible until vesting expires\n\n**Steps**:\n\n1. Request whitelisting of Bemo v2 Financial contract: `0:92c4664f1ea6b74ed9ce0e031a9fc0843348dfe87a58faea27fcd31e1608caaa` (or `EQCSxGZPHqa3TtnODgMan8CEM0jf6HpY-uon_NMeFgjKqkEY` in user-friendly format)\n\n1. Stake TON by sending an empty message to the Financial contract:\n\n   - Destination: Financial contract address above\n   - Amount: desired stake amount (e.g., 100 TON)\n   - Body: empty message (no payload)\n\n   Use the [vesting.ton.org](https://vesting.ton.org/) interface.\n\n1. Find the `bmTON` jetton wallet address:\n\n   - Open the staking transaction in a [block explorer]\n   - Look at the transaction trace and find the newly deployed jetton wallet\n   - Verify that:\n     - It's a `bmTON` jetton wallet (should show \"bmTON\" and be verified)\n     - The \"Holder address\" equals the vesting contract address\n\n   <Image\n     src=\"/resources/images/vesting/bemo_trace.png\"\n     alt=\"Bemo staking trace\"\n   />\n\n   <Image\n     src=\"/resources/images/vesting/bemo_jwallet.png\"\n     alt=\"Bemo jetton wallet\"\n   />\n\n1. Request whitelisting of the `bmTON` jetton wallet address. This is required to withdraw the stake later.\n\n1. To withdraw (unstake), send a burn message to the `bmTON` jetton wallet:\n\n   - Destination: `bmTON` jetton wallet address (from step 3)\n   - Amount: \\~0.5 TON (for gas fees)\n   - Body: burn message with operation code `op::jetton_burn` (0x595f07bc)\n\n   <Aside\n     type=\"caution\"\n     title=\"Withdrawal amount\"\n   >\n     Specify the exact amount of `bmTON` to unstake. Check the `bmTON` balance in the jetton wallet before creating the burn message.\n   </Aside>\n\n   To build the burn message cell in TypeScript, use the following code:\n\n   ```typescript\n   import { beginCell, Cell, toNano } from '@ton/core';\n\n   // jetton_burn#595f07bc query_id:uint64 jetton_amount:Coins\n   //      forward_payload:(Maybe ^Cell) = InternalMsgBody;\n\n   const jettonAmount = toNano(100); // amount of bmTON to burn\n\n   const burnMessage = beginCell()\n       .storeUint(0x595f07bc, 32) // op::jetton_burn\n       .storeUint(0, 64) // query_id\n       .storeCoins(jettonAmount) // jetton_amount\n       .storeRef(Cell.EMPTY) // forward_payload (empty)\n       .endCell();\n\n   // convert to HEX for vesting.ton.org interface\n   const hexMessage = burnMessage.toBoc().toString('hex');\n   console.log(hexMessage);\n   ```\n\n   Use the HEX output in the vesting interface when sending the burn message.\n\n   After burning `bmTON`, TON is returned to the vesting contract after a cooldown period. Check the current cooldown on [Bemo documentation](https://docs.bemo.fi).\n\n**Alternative: Bemo v1 (deprecated)**\n\nFor Bemo v1, the process is similar:\n\n- Financial contract address: `0:cd872fa7c5816052acdf5332260443faec9aacc8c21cca4d92e7f47034d11892` (`EQDNhy-nxYFgUqzfUzImBEP67JqsyMIcyk2S5_RwNNEYku0k`)\n- It mints `stTON` instead of `bmTON`\n- The rest of the process is the same as Bemo v2\n\n### Standard nominator pools\n\nStandard nominator pools are the original TON staking pools where multiple nominators can pool their stakes together with a validator.\n\n**Requirements**:\n\n- Pool must be in basechain (workchain 0)\n- Vesting contract must be in basechain (workchain 0)\n- Pool address must be in basechain format (starts with `0:`)\n\n**Steps**:\n\n1. Request whitelisting of the nominator pool address. Ensure the pool address is in basechain format (starts with `0:`).\n\n1. Deposit stake by sending text comment \"d\" (lowercase):\n\n   - Destination: nominator pool address\n   - Amount: desired stake amount + 1 TON (deposit processing fee)\n   - Body: text comment \"d\" (lowercase)\n\n   The pool may not accept the stake if it doesn't meet the minimum requirements or if the pool is full.\n\n1. Check the pool's parameters:\n\n   - Each pool has its own `min_nominator_stake` (minimum stake amount)\n   - Each pool has `max_nominators_count` (maximum number of nominators)\n   - Deposit processing fee is typically 1 TON\n\n   Check these parameters using the pool's get-methods.\n\n1. Withdraw stake by sending text comment \"w\" (lowercase):\n\n   - Destination: the same nominator pool address\n   - Amount: small amount for network fee (1 TON is enough)\n   - Body: text comment \"w\" (lowercase)\n\n   Unspent TONs attached to the message will be returned except in very rare cases.\n\n   Withdrawal behavior depends on the pool balance:\n\n   - If there are enough Toncoin on the pool balance, withdrawal will be made immediately. All funds will be available on the pool balance when it has completed participation in the validation round but has not yet submitted a request for participation in a new round.\n   - If there are not enough Toncoin on the pool balance, a withdraw request will be created, and Toncoin will be withdrawn automatically after the end of the current validation round.\n\n   Only full withdrawal is supported. Partial withdrawal is not supported.\n\n**Limitations**:\n\n- Depositing and withdrawing stake is supported\n- Voting on configuration proposals is supported (if sender whitelists Config address)\n- Stake earns validation rewards\n- Only \"d\" and \"w\" text comments are allowed\n- The vesting contract must be in basechain (workchain 0)\n\n### Whales nominator pools\n\n[Whales nominator pools](https://tonwhales.com/staking) are community-run staking pools with a slightly different interface.\n\n**Requirements**:\n\n- Pool must be in basechain (workchain 0)\n- Vesting contract must be in basechain (workchain 0)\n- Whales pools are typically in the basechain\n\n**Steps**:\n\n1. Request whitelisting of the Whales pool address.\n\n1. Deposit stake by sending text comment \"Stake\" (capital S, case-sensitive):\n\n   - Destination: Whales pool address\n   - Amount: desired stake amount + deposit fee\n   - Body: text comment \"Stake\" (capital S, case-sensitive)\n\n   Each pool has different deposit fees and minimum stake amounts. Check the specific pool information before depositing.\n\n1. Withdraw stake by sending text comment \"Withdraw\" (capital W, case-sensitive):\n\n   - Destination: the same Whales pool address\n   - Amount: withdraw fee (check specific pool information)\n   - Body: text comment \"Withdraw\" (capital W, case-sensitive)\n\n   Withdrawal is a two-step process:\n\n   - First message creates a withdrawal request\n   - Withdrawal may be immediate\n   - If withdrawal isn't immediate, wait for the pool to process the request (typically within 18 hours or less), then send another \"Withdraw\" message to complete it\n\n**Limitations**:\n\n- Depositing and withdrawing stake is supported\n- Stake earns validation rewards\n- Deposit and withdraw fees vary by pool\n- Only \"Stake\" and \"Withdraw\" text comments are allowed (case-sensitive)\n- The vesting contract must be in basechain (workchain 0)\n\n## Sending funds back to sender\n\nAt any time, even while funds are locked, they can be sent back to the vesting sender address without restrictions. This provides a safety mechanism to return funds if staking is not desired or if issues arise.\n\nThe sender address does not need to be added to the whitelist separately—it is always allowed as a destination.\n\n## After vesting ends\n\nOnce the vesting period completes and all funds are unlocked, the contract operates without restrictions:\n\n- Funds can be sent to any address\n- No whitelist restrictions apply\n- All message types are allowed\n- The contract functions like a standard wallet\n\nUnlocked funds remain unrestricted regardless of destination, including previously whitelisted addresses.\n\n## Code hash verification\n\nThe official vesting contract code hash is:\n\n```\nb48b531abec3b714638291f7d77ed6dc9f6a2729efca20477137374d4ae8b590\n```\n\nAlways verify this code hash matches before sending funds to any vesting contract. A mismatched hash indicates a modified or malicious contract.\n\nTo verify:\n\n1. Open the contract address in a [block explorer]\n1. Navigate to the \"Code\" or \"Contract\" tab\n1. Click on \"Bytecode\", then click on \"Hex hash\"\n1. Compare the code hash with the official hash above\n1. Do not proceed if hashes do not match\n\n## See also\n\n- [Vesting contract source code](https://github.com/ton-blockchain/vesting-contract)\n- [Vesting contract technical documentation](https://github.com/ton-blockchain/vesting-contract/blob/main/README.md)\n- [Vesting contract instruction (old and low level)](https://github.com/ton-blockchain/vesting-contract/blob/main/instruction.md)\n  single-nominator-pool#run-a-single-nominator-pool-with-a-vesting-contract)\n- [Standard wallets documentation](/standard/wallets/history)\n- [Staking organization scenarios on TON](/ecosystem/staking/overview)\n\n[block explorer]: /ecosystem/explorers/overview\n"
  },
  {
    "path": "standard/wallets/comparison.mdx",
    "content": "---\ntitle: \"Comparison\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\n\n[Unlike some other blockchains](/from-ethereum), wallets in TON are represented as distinct smart contracts. They handle transaction signing, replay protection, and even gasless transfers. Different wallet versions implement different custom logic, suitable for various use cases.\n\nThis article will cover the differences between these wallets and identify the best pick for each task.\n\n## Comparison table\n\n| Feature                         | V4                  | V5                    | Highload                    | Preprocessed          | Multisig                                                        |\n| ------------------------------- | ------------------- | --------------------- | --------------------------- | --------------------- | --------------------------------------------------------------- |\n| **Seqno<sup>1</sup> based**     | ✅ Yes              | ✅ Yes                | ❌ No (`query_id` based)    | ✅ Yes                | 🟡 Has boolean flag that turns off seqno `+1` incremental check |\n| **Messages throughput**         | Up to 4 per request | Up to 255 per request | Up to 2 billion per timeout | Up to 255 per request | Up to 255 per vote                                              |\n| **Multi-owner**                 | ❌ Single owner     | ❌ Single owner       | ❌ Single owner             | ❌ Single owner       | ✅ Multiple owners                                              |\n| **Message cost**                | Standard            | Standard              | Lower                       | Lowest                | Higher (multiple signatures)                                    |\n| **Support plugins**             | ✅ Yes              | ✅ Yes                | ❌ No                       | ❌ No                 | ❌ No                                                           |\n| **Support gasless<sup>2</sup>** | ❌ No               | ✅ Yes                | ❌ No                       | ❌ No                 | ❌ No                                                           |\n| **Subwallet ID**                | ✅ Yes              | ✅ Yes                | ✅ Yes                      | ❌ No                 | ❌ No                                                           |\n\n<sup>1</sup> Seqno means \"sequential number\" - a persistent unsigned integer variable, which is incremented by 1 for each valid transaction submission. Also, sometimes it's called \"nonce\". It is a common way to implement replay protection.<br />\n<sup>2</sup> \"Gasless\" is the kind of a transaction that doesn't require native currency to pay network fees.\n\nThere is also a separate gas and performance [comparison](/standard/wallets/performance).\n\n## Use cases\n\n### Retail users\n\nIf you are new to TON and want to create your first wallet to engage with the ecosystem, **v4** and **v5** are your best choices.\n\nAll major wallet apps support both standards and implement secure cryptography to ensure users' funds are safe.\n\nIt is recommended to use the v5 wallet standard, since it's the latest and most powerful implementation to date. It supports gasless transactions and up to 255 out messages per one signed external request.\n\n**Use for**:\n\n- **Buying stablecoins**: Purchase USDT and other stable assets\n- **Trading Jettons**: Swap tokens on DEXes and participate in DeFi\n- **Daily payments**: Send and receive TON for everyday transactions\n- **NFT collecting**: Buy, sell, and store digital collectibles\n- **Staking**: Participate in TON validation and earn rewards\n- **DApp interactions**: Connect to games, social apps, and other TON applications\n- **Savings**: Store cryptocurrency for long-term holding\n\n**Key benefits:**\n\n- Simple setup with any major TON wallet app\n- Low transaction fees for everyday use\n- Battle-tested security with millions of users\n- Full ecosystem compatibility\n\nRead more:\n\n- Recommended: [Wallet v5](/standard/wallets/v5)\n- [Wallet v4](/standard/wallets/v4)\n\n### Shared custody\n\nFor experienced institutional managers and fund operators with high security demands, **Multisig wallets are your best choice** when managing institutional funds, treasury assets, or any situation requiring shared custody.\n\nMultisig wallets provide the highest level of security through distributed control:\n\n- **Shared responsibility**: No single person can move funds alone\n- **Configurable thresholds**: Set up 2-of-3, 3-of-5, or any N-of-M configuration\n- **Audit trails**: Every transaction requires multiple approvals, creating clear accountability\n- **Risk mitigation**: Protects against key compromise, insider threats, and human error\n\n**Key considerations:**\n\n- Higher transaction costs due to multiple signature verification\n- Longer processing time as multiple parties must sign\n- Requires coordination between signers for each transaction\n- More complex setup and key management procedures\n\nWhile the operational overhead is higher than that of single-signature wallets, the security benefits make multisig essential for any custodial operation handling significant assets or requiring regulatory compliance.\n\n### Payment gateways\n\nFor businesses operating payment gateways, exchanges, or services requiring high-volume transaction processing, **Highload wallets are your best choice** when handling thousands of payments and withdrawals efficiently.\n\nHighload wallets are engineered explicitly for maximum throughput and cost efficiency:\n\n- **Massive throughput**: Process up to 8,380,415 requests with up to 254 outgoing messages (total maximum of up to 2 billion outgoing messages) per timeout period\n- **Query-based processing**: Uses `query id` and `batch id` instead of seqno for better transaction submission tracking. They help discover individual transaction submissions\n\n**Use for:**\n\n- **Cryptocurrency exchanges**: Handle thousands of user withdrawals and deposits\n- **Payment processors**: Process merchant payments and payouts at scale\n- **Trading platforms**: Execute high-frequency trading operations\n\n**Key considerations:**\n\n- Requires technical expertise for proper implementation\n- More complex setup compared to standard wallets\n- Need robust monitoring and error handling systems\n\nRead more:\n\n- [Highload wallet implementation](/standard/wallets/highload)\n"
  },
  {
    "path": "standard/wallets/highload/overview.mdx",
    "content": "---\ntitle: \"Highload wallets\"\nsidebarTitle: \"Overview\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nHighload Wallets are specialized wallet contracts designed for services that need to send hundreds of transactions per second, such as cryptocurrency exchanges, payment processors, and high-volume trading platforms.\n\n## What makes them different\n\nUnlike standard wallets (v3, v4, v5) that use sequential processing with a `seqno` counter, Highload Wallets (v2 and v3) store processed request identifiers in a dictionary, enabling **parallel transaction submission** without blocking.\n\n<Aside>\n  **`seqno`** (sequence number) is a counter that increments with each transaction. Standard wallets use it for [replay protection](/standard/wallets/how-it-works#how-replay-protection-works) — each transaction must match the current `seqno` value.\n</Aside>\n\n**Standard wallet limitation:**\\\nEach transaction must wait for the previous one to complete. If you send 100 transactions, they must process sequentially: transaction 2 waits for transaction 1, transaction 3 waits for transaction 2, and so on.\n\n**Highload Wallet advantage:**\\\nYou can send 100, 1,000, or 100,000 transactions simultaneously. Each transaction uses a unique `query_id` instead of a sequential `seqno`, allowing parallel processing without conflicts.\n\n## Version history\n\n### Highload Wallet v1\n\nThe first highload wallet, using a simple `seqno` counter:\n\n- **Simple seqno-based:** Sequential processing like standard wallets\n- **Batch support:** Could send up to 255 messages per transaction\n- **Replay protection rollback:** If the action phase failed, replay protection would roll back ([learn about](#replay-protection-rollback))\n\n<Aside\n  type=\"danger\"\n>\n  **Legacy contracts:** Highload Wallet v1 and v2 are deprecated. Use Highload Wallet v3 for all new deployments.\n</Aside>\n\n### Highload Wallet v2\n\nImproved version with dictionary-based replay protection:\n\n- **Fund locking risk:** Under certain conditions, the contract could enter a state where funds become inaccessible\n- **High gas costs:** Storage updates and cleanup operations consumed excessive gas\n- **Replay protection rollback:** If the action phase failed, replay protection would roll back ([learn about](#replay-protection-rollback))\n\n<Aside\n  type=\"danger\"\n>\n  **Legacy contracts:** Highload Wallet v1 and v2 are deprecated. Use Highload Wallet v3 for all new deployments.\n</Aside>\n\n### Highload Wallet v3\n\nThe current recommended version, redesigned to solve all previous architectural problems:\n\n- **More requests:** Up to 8,380,416 unique query IDs with efficient rotation\n- **Lower gas costs:** Optimized cleanup and storage operations\n- **Maximum safety:** Architectural design prevents fund locking; bulletproof\n- **Guaranteed replay protection:** Unlike v1, v2, and standard wallets v1-v4, replay protection **never rolls back** even if the action phase fails. The two-transaction pattern ensures the `query_id` is always committed before attempting to send messages.\n\n## Highload Wallet version comparison\n\n| Feature                               | v1                 | v2                    | v3                              |\n| ------------------------------------- | ------------------ | --------------------- | ------------------------------- |\n| **Replay rollback on action failure** | ⚠️ Yes             | ⚠️ Yes                | ✅ No (two-transaction pattern) |\n| **Fund locking risk**                 | ✅ No              | ⚠️ Yes                | ✅ No                           |\n| **Gas efficiency**                    | Not optimized      | ⚠️ High cleanup costs | ✅ Optimized                    |\n| **Max batch size**                    | 255 messages       | 255 messages          | 254 messages                    |\n| **Replay protection**                 | Simple seqno       | Query ID dictionary   | Dual dictionary + timestamp     |\n| **Transaction pattern**               | Single transaction | Single transaction    | Two-transaction pattern         |\n| **Query ID space**                    | Sequential seqno   | \\~32,000              | 8,380,416 unique IDs            |\n| **Parallel submissions**              | ❌ Sequential only | ✅ Supported          | ✅ Supported                    |\n| **Status**                            | ⚠️ Deprecated      | ⚠️ Deprecated         | ✅ Recommended                  |\n\n## Replay protection rollback\n\nStandard wallets (v1-v4) and Highload wallets (v1-v2) share a fundamental problem: if the action phase fails (e.g., insufficient funds), the entire transaction rolls back, including [replay protection](/standard/wallets/how-it-works#how-replay-protection-works) marks. This causes lite-servers to retry the same message repeatedly, burning gas for a long time.\n\n**Highload v3's solution:** Uses a [two-transaction pattern](/standard/wallets/highload/v3/specification#why-internal-messages-to-self%3F) where replay protection is committed in the first transaction, and actions are performed in a separate internal transaction. This guarantees replay protection **never rolls back**, even if sending messages fails.\n\n## See also\n\n- [Highload Wallet v3](/standard/wallets/highload/v3/specification) — complete technical reference and how-to guides\n- [Highload Wallet v2](/standard/wallets/highload/v2/specification) — legacy version (deprecated)\n- [Highload Wallet v1](https://github.com/ton-blockchain/ton/blob/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/smartcont/highload-wallet-code.fc) — legacy version (deprecated)\n"
  },
  {
    "path": "standard/wallets/highload/v2/specification.mdx",
    "content": "---\ntitle: \"Highload Wallet v2 — specification\"\nsidebarTitle: \"Specification\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside\n  type=\"danger\"\n>\n  **Deprecated:** Highload Wallet v2 is a legacy contract. Use [Highload Wallet v3](/standard/wallets/highload/v3/specification) for new deployments.\n\n  This specification is maintained for reference to support existing legacy systems.\n</Aside>\n\nThis page provides a complete technical specification for Highload Wallet v2, covering storage structure, message formats, replay protection, and limitations.\n\n## What is Highload Wallet v2?\n\nHighload Wallet v2 is a specialized wallet contract designed for services that need to send many transactions in a short time. It uses dictionary-based replay protection to enable parallel transaction submission.\n\n**Key difference from standard wallets:**\\\nUnlike seqno-based wallets that require sequential transaction processing, Highload v2 stores processed request identifiers in a dictionary, enabling parallel submissions.\n\n**Replaced by:** [Highload Wallet v3](/standard/wallets/highload/v3/specification)\n\n## TL-B schema\n\n[TL-B (Type Language - Binary)](/languages/tl-b/overview) is a domain-specific language designed to describe data structures in TON. The schemas below define the binary layout of the contract's storage and external messages.\n\n### Storage structure\n\n```tlb\nstorage$_ subwallet_id:uint32 last_cleaned:uint64 public_key:bits256\n          queries:(HashmapE 64 Cell) = Storage;\n```\n\n### Query ID structure\n\n```tlb\n_ query_id:uint64 = QueryId;\n```\n\n### External message structure\n\n```tlb\n_ mode:uint8 message:^Cell = OutListNode;\n\nmsg_body$_ signature:bits512 subwallet_id:uint32 query_id:uint64\n          messages:(HashmapE 16 Cell) = ExternalInMsgBody;\n```\n\n## Storage structure\n\nThe Highload Wallet v2 contract stores four persistent fields (in this order):\n\n### `subwallet_id` (32 bits)\n\n**Purpose:**\\\nAllows a single keypair to control multiple wallets with different addresses.\n\n**How it works:**\\\nThe `subwallet_id` is part of the contract's initial state. Changing it produces a different contract address. Each external message must include the correct `subwallet_id`; mismatches result in transaction failure.\n\n---\n\n### `last_cleaned` (64 bits)\n\n**Purpose:**\\\nTimestamp (in query\\_id format) of the oldest query that was kept during the last cleanup.\n\n**How it works:**\\\nDuring each transaction, the contract removes queries older than **64 seconds** from the `queries` dictionary. The `last_cleaned` field tracks the last query ID that was removed.\n\n**Cleanup logic:**\n\n```func\nbound -= (64 << 32);  // Clean up records expired more than 64 seconds ago\n```\n\nQueries with `query_id < (now() - 64) << 32` are removed from storage.\n\n<Aside\n  type=\"caution\"\n>\n  **Gas costs:** Cleanup operations consume gas proportional to the number of expired queries. With many expired queries, cleanup can exceed the 1,000,000 gas limit, causing the transaction to fail.\n</Aside>\n\n---\n\n### `public_key` (256 bits)\n\n**Purpose:**\\\nThe Ed25519 public key is used to verify signatures on incoming external messages.\n\n**How it works:**\\\nWhen the wallet receives an external message, it verifies that the 512-bit signature was created by the holder of the private key corresponding to this public key.\n\n---\n\n### `queries` (HashmapE 64 Cell)\n\n**Purpose:**\\\nStores processed `query_id` values for replay protection.\n\n**Structure:**\n\n- **Key:** 64-bit `query_id`\n- **Value:** Cell containing metadata (typically the timestamp when processed)\n\n**How it works:**\\\nBefore processing a message, the contract checks if `query_id` exists in `queries`. If found, the message is rejected (replay attack). If not found, the `query_id` is added to `queries`, and the message is processed.\n\n<Aside\n  type=\"caution\"\n>\n  **Storage limit:** The `queries` dictionary cannot exceed 65,535 cells. If this limit is reached, the contract will fail during the action phase.\n</Aside>\n\n## External message structure\n\n### Message layout\n\n```text\nsignature:bits512\nsubwallet_id:uint32\nquery_id:uint64\nmessages:(HashmapE 16 Cell)\n```\n\n**Key point:**\\\nUnlike v3, in v2 the signature is in the **same cell** as the message body, not in a separate reference cell.\n\n### `signature` (512 bits)\n\n**Type:**\\\nEd25519 signature (512 bits).\n\n**What is signed:**\\\nThe hash of the remaining slice after the signature, containing `subwallet_id`, `query_id`, and `messages`.\n\n**From source code:**\n\n```func\nthrow_unless(35, check_signature(slice_hash(in_msg), signature, public_key));\n```\n\nThe contract uses `slice_hash()` on the message body after loading the signature.\n\n---\n\n### `subwallet_id` (32 bits)\n\n**Purpose:**\\\nIdentifies which subwallet this message targets.\n\n**Validation:**\\\nMust match the `subwallet_id` stored in contract storage.\n\n---\n\n### `query_id` (64 bits)\n\n**Purpose:**\\\nUnique identifier for replay protection and timestamp validation.\n\n**Structure:**\\\nThe 64-bit value is internally interpreted as a timestamped identifier:\n\n- High 32 bits: Unix timestamp (seconds)\n- Low 32 bits: counter within that second\n\n**Validation:**\\\nThe contract checks `query_id >= now() << 32`, ensuring the query ID is not from the past (based on the current time shifted left by 32 bits).\n\n**Total unique IDs:**\\\nApproximately **32,000** unique query IDs (limited by the cleanup mechanism and the bitmap structure).\n\n---\n\n### `messages` (HashmapE 16)\n\n**Purpose:**\\\nDictionary of messages to send in this transaction.\n\n**Structure:**\n\n- **Key:** `uint16` (message index, 0 to 65,535)\n- **Value:** `mode:uint8` + `^Cell` (reference to internal message)\n\n**How it works:**\\\nThe contract iterates through the dictionary and sends each message with its corresponding [send mode](/foundations/messages/modes):\n\n```func\nint i = -1;\ndo {\n  (i, var cs, var f) = dict.idict_get_next?(16, i);\n  if (f) {\n    var mode = cs~load_uint(8);\n    send_raw_message(cs~load_ref(), mode);\n  }\n} until (~ f);\n```\n\n**Max batch size:**\\\nUp to **255 messages** (limited by action list size, not dictionary structure).\n\n---\n\n## Replay protection mechanism\n\n### Validation sequence\n\n1. **Check query\\_id timestamp:** `query_id >= now() << 32` (exit code `35` if too old)\n1. **Check replay:** `query_id` must not be in `queries` (exit code `32` if already processed)\n1. **Check subwallet:** `subwallet_id == stored_subwallet` (exit code `34` if mismatch)\n1. **Verify signature:** Ed25519 signature verification (exit code `35` if invalid)\n1. **Mark as processed:** Add `query_id` to `queries`\n1. **Send messages:** Iterate through the message dictionary and send each message\n1. **Cleanup:** Remove queries older than 64 seconds\n\n<Aside\n  type=\"caution\"\n>\n  **Rollback issue:** Highload Wallet v2 does not use `commit()` to persist storage changes. If the compute phase fails after `accept_message()` (e.g., gas limit exceeded during cleanup) or if the action phase fails, **all changes roll back**, including replay protection. The `query_id` is not marked as processed, and lite-servers will retry the same message, burning gas repeatedly.\n\n  Highload Wallet v3 solves this with `commit()` and a two-transaction pattern. See [Why internal messages to self?](/standard/wallets/highload/v3/specification#why-internal-messages-to-self) for details.\n</Aside>\n\n---\n\n## Exit codes\n\n| Exit code | Name                           | Description                                                     | How to fix                                                      |\n| --------- | ------------------------------ | --------------------------------------------------------------- | --------------------------------------------------------------- |\n| `0`       | Success                        | Message processed successfully                                  | —                                                               |\n| `32`      | Query already executed         | The `query_id` was already processed (found in `queries`)       | Use a new, unique `query_id`                                    |\n| `34`      | Subwallet ID mismatch          | The `subwallet_id` in the message does not match storage        | Verify you are using the correct `subwallet_id` for this wallet |\n| `35`      | Invalid signature or query\\_id | Ed25519 signature verification failed, or `query_id` is too old | Check the private key and ensure `query_id >= now() << 32`      |\n\n---\n\n## Limitations and constraints\n\n### Storage size limit\n\n**Limit:**\\\nThe `queries` dictionary cannot exceed **65,535 cells**.\n\n**What happens if exceeded:**\\\nAn exception is thrown during the action phase, and the transaction fails. The failed transaction may be replayed, potentially locking funds.\n\n### Gas limit for cleanup\n\n**Limit:**\\\nTransaction gas limit is **1,000,000 gas**.\n\n**What happens if exceeded:**\\\nCleanup operations that exceed this limit will fail, preventing the contract from processing new transactions.\n\n**Recommended limits:**\n\n- Queries within expiration window: ≤ 1,000\n- Queries cleaned per transaction: ≤ 100\n\n### Query ID expiration\n\n**Expiration time:**\\\nQueries older than **64 seconds** are removed from storage during cleanup.\n\n**Effective limit:**\\\nWith the 64-second expiration window and recommended limit of ≤1,000 queries per window, the effective query ID space is approximately **32,000** unique IDs before cleanup is required.\n\n---\n\n## Get methods\n\n| Method                 | Returns          | Description                                                                               |\n| ---------------------- | ---------------- | ----------------------------------------------------------------------------------------- |\n| `processed?(query_id)` | `int`            | Returns `-1` if processed, `0` if not processed, `1` if unknown (forgotten after cleanup) |\n| `get_public_key()`     | `int` (256 bits) | Returns the Ed25519 public key                                                            |\n\n### `processed?` method details\n\n**Returns:**\n\n- `-1` (true) — the `query_id` was processed and is still stored in `queries`\n- `0` (false) — the `query_id` has not been processed yet\n- `1` (unknown) — the `query_id` is older than `last_cleaned` and was forgotten during cleanup\n\n---\n\n## Implementation\n\n**Source code:**\\\n[ton-blockchain/ton (highload-wallet-v2-code.fc)](https://github.com/ton-blockchain/ton/blob/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/smartcont/highload-wallet-v2-code.fc)\n\n**SDK wrappers:**\n\n- **Go:** [`tonutils-go`](https://github.com/xssnick/tonutils-go) — includes Highload v2 wrapper\n- **Python:** [`pytoniq`](https://github.com/yungwine/pytoniq) — includes Highload v2 wrapper\n\nFor new projects, consider using [Highload Wallet v3](/standard/wallets/highload/v3/specification) instead.\n\n---\n\n## See also\n\n- [Highload Wallet v3 specification](/standard/wallets/highload/v3/specification) — recommended version\n- [Version comparison](/standard/wallets/highload/overview#version-comparison) — v1 vs v2 vs v3\n"
  },
  {
    "path": "standard/wallets/highload/v3/create.mdx",
    "content": "---\ntitle: \"How to create Highload Wallet v3\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nThis guide shows how to create a Highload Wallet v3 instance from scratch: choose configuration parameters, generate a mnemonic, and calculate the wallet address.\n\n## Objective\n\nBy the end of this guide, you will have:\n\n- A 24-word mnemonic phrase (seed phrase) for your wallet\n- A calculated wallet address (but not yet deployed on-chain)\n- Configuration parameters: `subwalletId` and `timeout`\n\n## Prerequisites\n\n- Node.js 18+ or TypeScript environment\n- `@ton/ton`, `@ton/core`, `@ton/crypto` packages installed\n- Highload Wallet v3 wrapper and compiled contract code\n\n<Aside type=\"note\">\n  **No deployment yet:** Creating a wallet calculates its future address but does not deploy it. The wallet will auto-deploy on the first external message (when you send your first transfer).\n</Aside>\n\nThis guide uses TypeScript with the official wrapper. The same logic applies to other SDKs (Go/Python): generate or load a mnemonic, derive a keypair, choose parameters, and calculate the address.\n\n## Step 1: Set up dependencies\n\nInstall required packages:\n\n```bash\nnpm install @ton/ton @ton/core @ton/crypto\n```\n\nCopy the wrapper and contract code from the [official repository](https://github.com/ton-blockchain/highload-wallet-contract-v3):\n\n```bash\n# Clone the repository or download these files:\n# - wrappers/HighloadWalletV3.ts\n# - wrappers/HighloadQueryId.ts\n# - Compiled contract BoC (from build/ or inline hex)\n```\n\n<Aside type=\"note\">\n  **Why copy wrappers?** The official `@ton/ton` SDK does not include Highload Wallet v3 wrappers yet. Copy `HighloadWalletV3.ts` and `HighloadQueryId.ts` from the repository until SDK support is added.\n</Aside>\n\n## Step 2: Choose configuration parameters\n\nHighload Wallet v3 requires two configuration parameters at creation time:\n\n### `timeout`\n\n**Type:** `uint22` (0 to 4,194,303 seconds)\\\n**Purpose:** Validity window for external messages and cleanup cycle duration\n\nThe `timeout` determines:\n\n- How long a signed external message remains valid: `created_at` must be within `[now - timeout, now]`\n- When old processed messages rotate to `old_queries`: every `timeout` seconds\n- When `old_queries` is cleared: after `2 × timeout`\n\n**Choosing a value:**\n\n| Range              | Use case                                                                                       |\n| ------------------ | ---------------------------------------------------------------------------------------------- |\n| Short (60–300s)    | Fast certainty if message expires; lower storage costs; requires tight synchronization         |\n| Medium (1–6 hours) | Balanced; suitable for most production use                                                     |\n| Long (24+ hours)   | High tolerance for blockchain congestion; higher storage costs; slower certainty on expiration |\n\n<Aside\n  type=\"caution\"\n>\n  **Cannot be changed later:** `timeout` is part of the contract's [initial configuration](/standard/wallets/highload/v3/specification#storage-structure). Changing it would change the wallet address entirely.\n</Aside>\n\nSee [Timeout constraints](/standard/wallets/highload/v3/specification#timeout-constraints) in the specification for details.\n\n### `subwalletId`\n\n**Type:** `uint32` (0 to 4,294,967,295)\\\n**Purpose:** Isolate multiple wallets derived from the same keypair\n\nA single mnemonic can generate multiple independent wallet addresses by varying `subwalletId`. Each wallet has its own balance, state, and transaction history.\n\n<Aside\n  type=\"caution\"\n>\n  **Recommended value: `0x10ad` (4269).**\\\n  Use a `subwalletId` different from other wallet types (standard wallets v3/v4/v5 or vesting wallets) derived from the same keypair. The value `0x10ad` is recommended in the [official repository](https://github.com/ton-blockchain/highload-wallet-contract-v3) to avoid conflicts with other contracts.\n</Aside>\n\n**Why this matters:**\n\nIf you use the same `subwalletId` across different wallet types (e.g., Highload v3 and standard wallet v5), they might share the same address, causing conflicts. Using `0x10ad` ensures isolation from standard wallets.\n\nSee [Storage structure](/standard/wallets/highload/v3/specification#storage-structure) in the specification for details.\n\n## Step 3: Generate or load a mnemonic\n\nA mnemonic is your wallet's master secret. It derives the private key used to sign all transactions.\n\n### Generate a new mnemonic\n\n```typescript\nimport { mnemonicNew } from '@ton/crypto';\n\nconst mnemonic = await mnemonicNew(24); // Array of 24 words\n```\n\n### Load an existing mnemonic\n\n```typescript\nconst mnemonic = 'word1 word2 word3 ... word24'.split(' ');\n```\n\n<Aside\n  type=\"danger\"\n>\n  **Protect your mnemonic:** Anyone with access to your mnemonic can control your wallet and all funds. Store it securely (password manager, hardware wallet, encrypted storage). Never commit it to version control.\n</Aside>\n\n## Step 4: Derive the keypair\n\nConvert the mnemonic to an Ed25519 keypair:\n\n```typescript\nimport { mnemonicToPrivateKey } from '@ton/crypto';\n\nconst keyPair = await mnemonicToPrivateKey(mnemonic);\n// keyPair.publicKey  — used in contract state\n// keyPair.secretKey  — used to sign external messages\n```\n\n## Step 5: Create the wallet instance\n\nCreate a Highload Wallet v3 contract instance with your chosen parameters:\n\n```typescript\nimport { TonClient } from '@ton/ton';\nimport { Cell } from '@ton/core';\nimport { HighloadWalletV3 } from './wrappers/HighloadWalletV3';\n\n// Configuration\nconst SUBWALLET_ID = 0x10ad; // Recommended for Highload Wallets\nconst TIMEOUT = 60 * 60 * 24; // 24 hours\n\n// Compiled contract code (BoC)\nconst CODE = Cell.fromBoc(\n    Buffer.from(\n        'b5ee9c7241021001000228000114ff00f4a413f4bcf2c80b01020120020d02014803040078d020d74bc00101c060b0915be101d0d3030171b0915be0fa4030f828c705b39130e0d31f018210ae42e5a4ba9d8040d721d74cf82a01ed55fb04e030020120050a02027306070011adce76a2686b85ffc00201200809001aabb6ed44d0810122d721d70b3f0018aa3bed44d08307d721d70b1f0201200b0c001bb9a6eed44d0810162d721d70b15800e5b8bf2eda2edfb21ab09028409b0ed44d0810120d721f404f404d33fd315d1058e1bf82325a15210b99f326df82305aa0015a112b992306dde923033e2923033e25230800df40f6fa19ed021d721d70a00955f037fdb31e09130e259800df40f6fa19cd001d721d70a00937fdb31e0915be270801f6f2d48308d718d121f900ed44d0d3ffd31ff404f404d33fd315d1f82321a15220b98e12336df82324aa00a112b9926d32de58f82301de541675f910f2a106d0d31fd4d307d30cd309d33fd315d15168baf2a2515abaf2a6f8232aa15250bcf2a304f823bbf2a35304800df40f6fa199d024d721d70a00f2649130e20e01fe5309800df40f6fa18e13d05004d718d20001f264c858cf16cf8301cf168e1030c824cf40cf8384095005a1a514cf40e2f800c94039800df41704c8cbff13cb1ff40012f40012cb3f12cb15c9ed54f80f21d0d30001f265d3020171b0925f03e0fa4001d70b01c000f2a5fa4031fa0031f401fa0031fa00318060d721d300010f0020f265d2000193d431d19130e272b1fb00b585bf03',\n        'hex'\n    )\n)[0];\n\nconst client = new TonClient({\n    endpoint: 'https://testnet.toncenter.com/api/v2/jsonRPC', // This is TESTNET endpoint\n    // apiKey: 'your-api-key' // Optional: get from @tonapibot or @tontestnetapibot\n});\n\nconst wallet = client.open(\n    HighloadWalletV3.createFromConfig(\n        {\n            publicKey: keyPair.publicKey,\n            subwalletId: SUBWALLET_ID,\n            timeout: TIMEOUT,\n        },\n        CODE\n    )\n);\n```\n\n## Step 6: Get the wallet address\n\nCalculate the wallet's address:\n\n```typescript\n// Get non-bounceable address for funding\nconst address = wallet.address.toString({ bounceable: false, testOnly: true });\nconsole.log('Wallet address:', address);\n// Example (truncated): 0Q... (non-bounceable, testnet)\n```\n\nThis address is deterministic: it depends only on `CODE`, `publicKey`, `subwalletId`, and `timeout`. The same parameters always produce the same address.\n\n<Aside type=\"tip\">\n  **Why non-bounceable?** When funding a `nonexist` account, use the non-bounceable format to prevent funds from bouncing back if the account doesn't exist yet. See [Address formats](/foundations/addresses/formats) for details.\n</Aside>\n\n**Account status: [`nonexist`](/foundations/status#status-variety)**\n\nThe calculated address exists only as a deterministic value. No account exists on the blockchain yet — no balance, no code, no data.\n\n## Step 7: Fund the wallet\n\n<Aside\n  type=\"danger\"\n>\n  **Funds at risk:** You will send TON to this address. Test on testnet first. Verify the wallet address carefully — blockchain transactions cannot be reversed.\n</Aside>\n\n**Required before deployment:** Send TON to your wallet address (from Step 6) to prepare it for deployment.\n\nExternal messages (which deploy the wallet) require gas to execute. By funding the address, you transition the account from `nonexist` to `uninit` status and provide the balance needed for deployment. See [Account status](/foundations/status) for details on how account states work.\n\nSend TON using a faucet (testnet) or from another wallet (mainnet). After funding, the account transitions to `uninit` status — it has a balance and can accept external messages, but no code or data yet.\n\n## Saving wallet data\n\nFor convenience, save your wallet configuration to reuse later:\n\n```typescript\nimport * as fs from 'fs';\n\nconst walletData = {\n    mnemonic: mnemonic.join(' '),\n    address: address, // From Step 6\n    subwalletId: SUBWALLET_ID,\n    timeout: TIMEOUT,\n};\n\nfs.writeFileSync('.wallet.json', JSON.stringify(walletData, null, 2));\nconsole.log('Wallet saved to .wallet.json');\n```\n\n<Aside\n  type=\"danger\"\n>\n  **Never commit `.wallet.json`:** Add it to `.gitignore`. This file contains your mnemonic.\n</Aside>\n\n## Next steps\n\nYour wallet is ready for deployment. The wallet will auto-deploy on the first external message.\n"
  },
  {
    "path": "standard/wallets/highload/v3/send-batch-transfers.mdx",
    "content": "---\ntitle: \"How to send a batch of transfers\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside\n  type=\"danger\"\n>\n  **Funds at risk:** This guide sends real TON. Test on testnet first. Double-check recipient addresses — blockchain transactions cannot be reversed.\n</Aside>\n\nThis guide shows how to send multiple transfers in a single transaction using Highload Wallet v3. This is the main feature of the wallet, enabling up to 254 messages per transaction.\n\n## Objective\n\nBy the end of this guide, you will:\n\n- Send multiple transfers (up to 254) in a single transaction\n- Understand the two-transaction flow for batch transfers\n- Know how to calculate the compute fees for the internal transaction\n\n## Prerequisites\n\n- Completed [wallet creation](/standard/wallets/highload/v3/create) with funded balance and saved configuration in `.wallet.json`\n\n## Step 1: Load wallet configuration\n\nLoad the wallet data and create the wallet instance:\n\n```typescript\nimport { TonClient, internal, toNano, comment } from '@ton/ton';\nimport { mnemonicToPrivateKey } from '@ton/crypto';\nimport { Cell, SendMode } from '@ton/core';\nimport { HighloadWalletV3 } from './wrappers/HighloadWalletV3';\nimport { HighloadQueryId } from './wrappers/HighloadQueryId';\nimport * as fs from 'fs';\n\n// Load wallet data\nconst walletData = JSON.parse(fs.readFileSync('.wallet.json', 'utf-8'));\nconst mnemonic = walletData.mnemonic.split(' ');\nconst keyPair = await mnemonicToPrivateKey(mnemonic);\n\nconst CODE = Cell.fromBoc(Buffer.from('b5ee9c7241021001000228000114ff00f4a413f4bcf2c80b01020120020d02014803040078d020d74bc00101c060b0915be101d0d3030171b0915be0fa4030f828c705b39130e0d31f018210ae42e5a4ba9d8040d721d74cf82a01ed55fb04e030020120050a02027306070011adce76a2686b85ffc00201200809001aabb6ed44d0810122d721d70b3f0018aa3bed44d08307d721d70b1f0201200b0c001bb9a6eed44d0810162d721d70b15800e5b8bf2eda2edfb21ab09028409b0ed44d0810120d721f404f404d33fd315d1058e1bf82325a15210b99f326df82305aa0015a112b992306dde923033e2923033e25230800df40f6fa19ed021d721d70a00955f037fdb31e09130e259800df40f6fa19cd001d721d70a00937fdb31e0915be270801f6f2d48308d718d121f900ed44d0d3ffd31ff404f404d33fd315d1f82321a15220b98e12336df82324aa00a112b9926d32de58f82301de541675f910f2a106d0d31fd4d307d30cd309d33fd315d15168baf2a2515abaf2a6f8232aa15250bcf2a304f823bbf2a35304800df40f6fa199d024d721d70a00f2649130e20e01fe5309800df40f6fa18e13d05004d718d20001f264c858cf16cf8301cf168e1030c824cf40cf8384095005a1a514cf40e2f800c94039800df41704c8cbff13cb1ff40012f40012cb3f12cb15c9ed54f80f21d0d30001f265d3020171b0925f03e0fa4001d70b01c000f2a5fa4031fa0031f401fa0031fa00318060d721d300010f0020f265d2000193d431d19130e272b1fb00b585bf03', 'hex'))[0];\n\nconst client = new TonClient({\n    endpoint: 'https://testnet.toncenter.com/api/v2/jsonRPC', // This is TESTNET endpoint\n    // apiKey: 'your-api-key' // Optional: get from @tonapibot or @tontestnetapibot\n});\n\nconst wallet = client.open(\n    HighloadWalletV3.createFromConfig(\n        {\n            publicKey: keyPair.publicKey,\n            subwalletId: walletData.subwalletId,\n            timeout: walletData.timeout,\n        },\n        CODE\n    )\n);\n```\n\n## Step 2: Prepare the message batch\n\nCreate an array of messages to send:\n\n```typescript\nconst messages = [];\nfor (let i = 1; i <= 10; i++) {\n    messages.push({\n        type: 'sendMsg' as const,\n        mode: SendMode.PAY_GAS_SEPARATELY,\n        outMsg: internal({\n            to: 'EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c', // Zero address (for testing)\n            value: toNano('0.001'),\n            body: comment(`#${i}`),\n            bounce: false,\n        }),\n    });\n}\n```\n\nEach message in the batch:\n\n- **`type: 'sendMsg'`** — specifies that this is an outgoing message action\n- **`mode`** — [send mode](/foundations/messages/modes) for each individual message\n- **`outMsg`** — the internal message to send\n\n<Aside type=\"tip\">\n  **Batch limit:** You can send up to **254 messages** per transaction. This limit exists because one action slot is reserved for [`set_code` protection](/standard/wallets/highload/v3/specification#protection-against-set-code).\n</Aside>\n\n## Step 3: Send the batch\n\nSend the batch using the `sendBatch` method:\n\n```typescript\nconst queryId = HighloadQueryId.fromSeqno(17n); // Use a specific seqno\nconst createdAt = Math.floor(Date.now() / 1000) - 30; // 30 seconds ago\nconst value = toNano('0.0007024'); // Compute fee for internal receiver\n\nawait wallet.sendBatch(\n    keyPair.secretKey,\n    messages,\n    walletData.subwalletId,\n    queryId,\n    walletData.timeout,\n    createdAt,\n    value\n);\n\nconsole.log('Batch sent: 10 transfers');\nconsole.log(`Query ID: ${queryId.toSeqno()}`);\nconsole.log(`Created At: ${createdAt}`);\n```\n\n<Aside type=\"note\">\n  **Automatic deployment:** If your wallet is in `uninit` status (has a balance but no code), it will automatically deploy when processing this external message. The wallet transitions to `active` status, and the batch transfer is executed in the same transaction.\n</Aside>\n\n### Parameter explanation\n\n**`queryId`** — Unique identifier for replay protection:\n\n- Each `query_id` can only be processed once within the protection window\n- `HighloadQueryId` is a wrapper class that represents the composite `query_id` as a sequential counter\n- Use `HighloadQueryId.fromSeqno(n)` to create a specific query ID\n- Provides `getNext()` method to increment to the next unique ID\n- Total range: 8,380,416 unique IDs\n- See [Query ID structure](/standard/wallets/highload/v3/specification#query-id-structure) for details\n\n**`createdAt`** — Message timestamp for expiration:\n\n- Set to 30 seconds **before** current time: `Math.floor(Date.now() / 1000) - 30`\n- Compensates for blockchain time lag (lite-servers use last block time, not current time)\n- See [Timestamp validation](/standard/wallets/highload/v3/specification#timestamp-validation) for why this is necessary\n\n**`value`** — Compute fee for the internal transaction:\n\n- The internal receiver (Transaction 2) consumes a fixed **1,756 gas** to process the action list\n- At current gas prices, this equals \\~0.0007024 TON\n- This fee is sent to the wallet itself to cover internal message processing\n- If insufficient, the internal transaction may fail (but replay protection remains intact)\n\n<Aside\n  type=\"caution\"\n>\n  **Compute fee requirement:** The `value` parameter covers gas for the internal transaction that processes the action list. This is in addition to the gas costs of the external message itself.\n</Aside>\n\n## How it works\n\nBatch transfers use a two-transaction pattern: the external message marks the `query_id` as processed and sends an internal message to itself with the action list, then the internal transaction processes the actions and sends all outgoing messages.\n\nSee [Message sending flow](/standard/wallets/highload/v3/specification#message-sending-flow) for the complete validation sequence.\n\n## Next steps\n\nYou can send multiple batches in parallel, each with a unique `query_id`.\n\nTo verify that your batch was fully processed, see [How to verify message is processed](/standard/wallets/highload/v3/verify-is-processed).\n"
  },
  {
    "path": "standard/wallets/highload/v3/send-single-transfer.mdx",
    "content": "---\ntitle: \"How to send a single transfer\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside\n  type=\"danger\"\n>\n  **Funds at risk:** This guide sends real TON. Test on testnet first. Double-check recipient addresses — blockchain transactions cannot be reversed.\n</Aside>\n\nThis guide shows how to send a single transfer from your Highload Wallet v3.\n\n## Objective\n\nBy the end of this guide, you will:\n\n- Send a single TON transfer from your Highload Wallet v3\n- Understand how `query_id`, `created_at`, and [send modes](/foundations/messages/modes) work\n\n## Prerequisites\n\n- Completed [wallet creation](/standard/wallets/highload/v3/create) with funded balance and saved configuration in `.wallet.json`\n\n## Step 1: Load wallet configuration\n\nLoad the wallet data and create the wallet instance:\n\n```typescript\nimport { TonClient, internal, toNano } from '@ton/ton';\nimport { mnemonicToPrivateKey } from '@ton/crypto';\nimport { Cell, SendMode } from '@ton/core';\nimport { HighloadWalletV3 } from './wrappers/HighloadWalletV3';\nimport { HighloadQueryId } from './wrappers/HighloadQueryId';\nimport * as fs from 'fs';\n\n// Load wallet data\nconst walletData = JSON.parse(fs.readFileSync('.wallet.json', 'utf-8'));\nconst mnemonic = walletData.mnemonic.split(' ');\nconst keyPair = await mnemonicToPrivateKey(mnemonic);\n\nconst CODE = Cell.fromBoc(Buffer.from('b5ee9c7241021001000228000114ff00f4a413f4bcf2c80b01020120020d02014803040078d020d74bc00101c060b0915be101d0d3030171b0915be0fa4030f828c705b39130e0d31f018210ae42e5a4ba9d8040d721d74cf82a01ed55fb04e030020120050a02027306070011adce76a2686b85ffc00201200809001aabb6ed44d0810122d721d70b3f0018aa3bed44d08307d721d70b1f0201200b0c001bb9a6eed44d0810162d721d70b15800e5b8bf2eda2edfb21ab09028409b0ed44d0810120d721f404f404d33fd315d1058e1bf82325a15210b99f326df82305aa0015a112b992306dde923033e2923033e25230800df40f6fa19ed021d721d70a00955f037fdb31e09130e259800df40f6fa19cd001d721d70a00937fdb31e0915be270801f6f2d48308d718d121f900ed44d0d3ffd31ff404f404d33fd315d1f82321a15220b98e12336df82324aa00a112b9926d32de58f82301de541675f910f2a106d0d31fd4d307d30cd309d33fd315d15168baf2a2515abaf2a6f8232aa15250bcf2a304f823bbf2a35304800df40f6fa199d024d721d70a00f2649130e20e01fe5309800df40f6fa18e13d05004d718d20001f264c858cf16cf8301cf168e1030c824cf40cf8384095005a1a514cf40e2f800c94039800df41704c8cbff13cb1ff40012f40012cb3f12cb15c9ed54f80f21d0d30001f265d3020171b0925f03e0fa4001d70b01c000f2a5fa4031fa0031f401fa0031fa00318060d721d300010f0020f265d2000193d431d19130e272b1fb00b585bf03', 'hex'))[0];\n\nconst client = new TonClient({\n    endpoint: 'https://testnet.toncenter.com/api/v2/jsonRPC', // This is TESTNET endpoint\n    // apiKey: 'your-api-key' // Optional: get from @tonapibot or @tontestnetapibot\n});\n\nconst wallet = client.open(\n    HighloadWalletV3.createFromConfig(\n        {\n            publicKey: keyPair.publicKey,\n            subwalletId: walletData.subwalletId,\n            timeout: walletData.timeout,\n        },\n        CODE\n    )\n);\n```\n\n## Step 2: Prepare the transfer message\n\nCreate an internal message with the transfer details:\n\n```typescript\nconst internalMessage = internal({\n    to: 'EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c', // Zero address (for testing)\n    value: toNano('0.01'),\n    bounce: false,\n});\n```\n\nThis example uses the zero address for testing. Replace it with your actual destination address.\n\n<Aside\n  type=\"caution\"\n>\n  **No state-init support:** Highload Wallet v3 cannot send messages containing [`StateInit`](/foundations/messages/deploy) using this method.\n\n  If you need to deploy a contract (send a message with `StateInit`), use [batch transfers](/standard/wallets/highload/v3/send-batch-transfers) with an action list instead. See [Limitations and constraints](/standard/wallets/highload/v3/specification#limitations-and-constraints) in the specification for details.\n</Aside>\n\n## Step 3: Send the transfer\n\nSend the transfer using the `sendExternalMessage` method:\n\n```typescript\nconst createdAt = Math.floor(Date.now() / 1000) - 30; // 30 seconds ago\nconst queryId = new HighloadQueryId(); // Represents query_id as a seqno\n\nawait wallet.sendExternalMessage(keyPair.secretKey, {\n    message: internalMessage,\n    mode: SendMode.PAY_GAS_SEPARATELY,\n    query_id: queryId,\n    createdAt: createdAt,\n    subwalletId: walletData.subwalletId,\n    timeout: walletData.timeout,\n});\n\nconsole.log('Transfer sent');\n```\n\n<Aside type=\"note\">\n  **Automatic deployment:** If your wallet is in `uninit` status (has a balance but no code), it will automatically deploy when processing this external message. The wallet transitions to `active` status, and the transfer is executed in the same transaction.\n</Aside>\n\n### Parameter explanation\n\n**`query_id`** — Unique identifier for replay protection:\n\n- Each `query_id` can only be processed once within the protection window\n- `HighloadQueryId` is a wrapper class that represents the composite `query_id` as a sequential counter\n- Provides `getNext()` method to increment to the next unique ID\n- Total range: 8,380,416 unique IDs\n- See [Query ID structure](/standard/wallets/highload/v3/specification#query-id-structure) for details\n\n**`createdAt`** — Message timestamp for expiration:\n\n- Set to 30 seconds **before** current time: `Math.floor(Date.now() / 1000) - 30`\n- Compensates for blockchain time lag (lite-servers use last block time, not current time)\n- See [Timestamp validation](/standard/wallets/highload/v3/specification#timestamp-validation) for why this is necessary\n\n## Next steps\n\nYour wallet is fully operational. You can send multiple transfers in parallel or batch multiple messages in one transaction.\n\nTo verify that your message, see [How to verify message is processed](/standard/wallets/highload/v3/verify-is-processed).\n"
  },
  {
    "path": "standard/wallets/highload/v3/specification.mdx",
    "content": "---\ntitle: \"Highload Wallet v3 — specification\"\nsidebarTitle: \"Specification\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\nimport { Image } from '/snippets/image.jsx';\n\nThis page provides a complete technical specification for Highload Wallet v3, covering storage structure, message formats, replay protection, limitations, and security mechanisms.\n\n## Objective\n\nUnderstand the internal architecture, data structures, and operational mechanics of Highload Wallet v3. This reference page explains how the wallet processes high-throughput transaction flows securely.\n\n<Aside type=\"tip\">\n  For practical usage, see [How-to guides](/standard/wallets/highload/v3/create).\n</Aside>\n\n## What is Highload Wallet v3?\n\nHighload Wallet v3 is a specialized wallet smart contract designed for services that need to send many transactions in a short time (e.g., cryptocurrency exchanges, payment processors).\n\n**Key difference from standard wallets:**\\\nUnlike seqno-based wallets (v3, v4, v5) that require sequential transaction processing, Highload v3 stores processed request identifiers in a dictionary, enabling **parallel transaction submission** without blocking.\n\n**Compared to Highload v2:**\\\nv3 solves architectural issues that could lock funds in v2 and consumes less gas during operations.\n\n---\n\n## TL-B schema\n\n[TL-B (Type Language - Binary)](/languages/tl-b/overview) is a domain-specific language designed to describe data structures in TON. The schemas below define the binary layout of the contract's storage, external messages, and internal messages.\n\n### Storage structure\n\n```tlb\nstorage$_ public_key:bits256 subwallet_id:uint32 old_queries:(HashmapE 13 ^Cell)\n          queries:(HashmapE 13 ^Cell) last_clean_time:uint64 timeout:uint22\n          = Storage;\n```\n\n### Query ID structure\n\n```tlb\n_ shift:uint13 bit_number:(## 10) { bit_number >= 0 } { bit_number < 1023 } = QueryId;\n```\n\n### External message structure\n\n```tlb\n_ {n:#} subwallet_id:uint32 message_to_send:^Cell send_mode:uint8 query_id:QueryId\n  created_at:uint64 timeout:uint22 = MsgInner;\n\nmsg_body$_ {n:#} signature:bits512 ^(MsgInner) = ExternalInMsgBody;\n```\n\n### Internal message structure (for batch transfers)\n\n```tlb\ninternal_transfer#ae42e5a4 {n:#} query_id:uint64 actions:^(OutList n) = InternalMsgBody n;\n```\n\n<Aside type=\"note\">\n  `internal_transfer` is used when the wallet sends a message to itself with an action list for batch transfers. The opcode `0xae42e5a4` is derived from `crc32('internal_transfer n:# query_id:uint64 actions:^OutList n = InternalMsgBody n')`.\n\n  The canonical TL-B schemas are maintained in the [highload-wallet-contract-v3 repository](https://github.com/ton-blockchain/highload-wallet-contract-v3).\n</Aside>\n\nBelow, each field is explained in detail.\n\n---\n\n## Storage structure\n\nThe Highload Wallet v3 contract stores six persistent fields:\n\n### `public_key` (256 bits)\n\n**Purpose:**\\\nAn Ed25519 public key is used to verify signatures on incoming external messages.\n\n**How it works:**\\\nWhen the wallet receives an external message, it verifies that the 512-bit signature was created by the holder of the private key corresponding to this public key.\n\n<Aside\n  type=\"caution\"\n>\n  The public key is not the wallet address. The address is [derived](/foundations/addresses/derive) from the contract's [`StateInit`](/foundations/messages/deploy).\n</Aside>\n\n---\n\n### `subwallet_id` (32 bits)\n\n**Purpose:**\\\nAllows a single keypair to control multiple wallets with different addresses.\n\n**How it works:**\\\nThe `subwallet_id` is part of the contract's initial state. Changing it produces a different contract address (because the address is a hash of code + data). Each external message must include the correct `subwallet_id`; mismatches result in exit code `34`.\n\n**Common use case:**\\\nOne private key manages multiple \"virtual\" wallets for organizational or accounting purposes.\n\n**Recommendation:**\\\nUse `subwallet_id: 0x10ad` (4269) to avoid conflicts with other wallet types (standard wallets or vesting wallets) derived from the same keypair. See [How to create Highload Wallet v3](/standard/wallets/highload/v3/create) for details.\n\n---\n\n### `old_queries` (HashmapE 13 ^Cell)\n\n**Purpose:**\\\nStores previously processed `query_id` values during rotation cycles.\n\n**Structure:**\\\nHashmap with 13-bit keys, where each key holds a bitmap of processed query IDs.\n\n**Usage:**\\\nProvides a second layer of replay protection. During cleanup, `queries` → `old_queries`, creating a double timeout window.\n\n**Details:** See [Replay protection mechanism](#replay-protection-mechanism).\n\n---\n\n### `queries` (HashmapE 13 ^Cell)\n\n**Purpose:**\\\nStores recently processed `query_id` values to prevent replay attacks.\n\n**Structure:**\\\nHashmap with 13-bit keys, where each key holds a bitmap of processed query IDs.\n\n**Usage:**\\\nWhen a message arrives, the contract checks if its `query_id` is already marked in `queries` or `old_queries`. If found, the message is rejected as a replay attempt.\n\n**Details:** See [Replay protection mechanism](#replay-protection-mechanism).\n\n---\n\n### `last_clean_time` (64 bits)\n\n**Purpose:**\\\nUnix timestamp (in seconds) of the last cleanup operation.\n\n**Usage:**\\\nTracks when the contract last rotated `queries` → `old_queries`. Cleanup triggers when `current_time >= last_clean_time + timeout`.\n\n**Details:** See [Replay protection mechanism](#replay-protection-mechanism).\n\n---\n\n### `timeout` (22 bits)\n\n**Purpose:**\\\nDefines the validity window (in seconds) for external messages.\n\n**Usage:**\\\nMessages are valid if `created_at > now() - timeout` and `created_at <= now()`. If expired or from the future, the contract rejects them with exit code `35`.\n\n<Aside type=\"note\">\n  22 bits allows timeout values up to \\~4,194,303 seconds (\\~48.6 days).\n</Aside>\n\n**Details:**\n\n- [Replay protection mechanism](#replay-protection-mechanism) — how timeout is used\n- [Timeout constraints](#timeout-constraints) — choosing the right value\n\n---\n\n## Replay protection mechanism\n\nHighload v3 uses a dual-hashmap system (`queries` and `old_queries`) combined with timestamps to prevent replay attacks.\n\n### Storage structure for replay protection\n\nThe contract stores processed `query_id` values in two hashmaps:\n\n**`old_queries` (HashmapE 13 ^Cell):**\n\n- Hashmap with 13-bit keys\n- Each key corresponds to `shift` (13 bits from query\\_id)\n- Each value is a cell containing a bitmap of processed `bit_number` values\n- Stores previously processed query IDs from the last rotation cycle\n- Provides extended protection during rotation\n\n**`queries` (HashmapE 13 ^Cell):**\n\n- Same structure as `old_queries` — hashmap with 13-bit keys\n- Each key corresponds to `shift = query_id >> 10`\n- Each value is a cell containing a bitmap of processed `bit_number` values\n- Stores recently processed query IDs\n\n### How query\\_id is checked\n\nWhen an external message arrives, the contract:\n\n1. Extracts `query_id` from the message\n1. Splits it into components:\n   - `shift = query_id >> 10` (13 bits, range 0–8191)\n   - `bit_number = query_id & 1023` (10 bits, range 0–1022)\n1. Checks if bit `bit_number` is set in `queries[shift]`:\n   - If found → reject with exit code `36`\n1. Checks if bit `bit_number` is set in `old_queries[shift]`:\n   - If found → reject with exit code `36`\n1. If not found in either → mark the bit in `queries[shift]` and proceed\n\n**Why a hashmap structure?**\\\nEnables [parallel transaction submission](#what-is-highload-wallet-v3) — multiple messages can be sent simultaneously without waiting for sequential confirmation.\n\n### Rotation mechanism\n\nWhen `current_time >= last_clean_time + timeout`, the contract performs cleanup:\n\n1. `old_queries := queries` — move current queries to old\n1. `queries := {}` — clear current queries hashmap\n1. `last_clean_time := current_time` — update timestamp\n\n**Additional cleanup:**\\\nIf `current_time >= last_clean_time + (2 × timeout)` (i.e., no cleanup for twice the timeout period), the contract also clears `old_queries` completely to prevent unbounded storage growth.\n\n**Why two hashmaps?**\\\nThis provides a **double timeout window** for replay protection:\n\n- A `query_id` is protected for at least `timeout` seconds in `queries`\n- After rotation, it remains in `old_queries` for another `timeout` period before deletion\n- Total protection window: between `timeout` and `2 × timeout`\n\n**Benefit:**\\\nPrevents replay attacks even if messages arrive near the rotation boundary.\n\n### Timestamp validation\n\nThe `created_at` timestamp combined with `timeout` ensures that even very old messages (beyond the rotation window) are rejected. This creates a time-based boundary for message validity:\n\n```text\nThe message is valid if:\n  created_at > now() - timeout  // Not too old\n  created_at <= now()           // Not from future\nOtherwise: reject with exit code 35\n```\n\n<Aside\n  type=\"caution\"\n>\n  **Time lag consideration:** When a lite-server receives an external message, the contract executes `now()` which returns the timestamp of the **last processed block**, not the current system time. Due to network latency and block processing time, this timestamp is typically 5-30 seconds behind your system clock.\n\n  **Best practice:** Set `created_at` to 30-60 seconds **before** the current time to ensure the message passes validation:\n\n  ```typescript\n  const createdAt = Math.floor(Date.now() / 1000) - 30;  // 30 seconds ago\n  ```\n\n  If `created_at` equals your current system time, it may appear to be \"from the future\" when validated on-chain, causing the transaction to fail with exit code `35`.\n</Aside>\n\n### Uniqueness guarantee\n\n<Aside type=\"note\">\n  Highload v3 will never execute multiple external messages containing the same `query_id` and `created_at` — by the time it forgets any given `query_id`, the `created_at` condition will prevent execution of such a message. This effectively makes `query_id` and `created_at` together the \"primary key\" of a transfer request for Highload v3.\n</Aside>\n\n### Why internal messages to self?\n\nHighload v3 uses a unique **internal message to self** pattern for a critical security reason related to TON's transaction phases.\n\n**The problem with standard external message wallets:**\n\nIn TON, transaction processing includes several phases. Two phases are critical for understanding this problem:\n\n1. **Compute phase** — executes smart contract code, updates storage\n1. **Action phase** — performs actions (sends messages)\n\nIf the action phase fails (e.g., insufficient funds for outgoing messages), the **entire transaction is rolled back**, including all storage changes made in the compute phase.\n\nFor standard wallets that process external messages and send outgoing messages directly, this creates a problem: if you mark a message as \"processed\" in the compute phase but the action phase then fails (e.g., due to insufficient balance or invalid message), the rollback will **undo the replay protection**. Since the message was never marked as processed, lite-servers will keep retrying the same external message again and again, **burning gas on each attempt** for a long time or until the wallet runs out of funds.\n\n**Highload v3's solution:**\n\nHighload v3 uses a two-step approach with **internal messages**:\n\n1. **Transaction 1 (external message):** Only marks `query_id` as processed and sends an **internal message to itself**\n1. **Transaction 2 (internal message):** Processes the internal message and sends actual outgoing transfers\n\nEven if Transaction 2 fails in the action phase, Transaction 1 has already succeeded, and its storage changes (replay protection) cannot be rolled back. The `query_id` remains marked as processed, preventing replay attacks.\n\nThis architecture solves a fundamental problem present in all standard external message wallets, including seqno-based wallets and earlier highload designs.\n\n---\n\n## External message structure\n\nExternal messages sent to Highload v3 have a specific layout.\n\n### Message layout\n\n```text\nsignature:bits512\n^[ subwallet_id:uint32\n   message_to_send:^Cell\n   send_mode:uint8\n   query_id:QueryId\n   created_at:uint64\n   timeout:uint22 ]\n```\n\n**Key point:**\\\nThe signature is in the **root cell** (512 bits); all other parameters are in a **reference cell** (`MsgInner`).\n\n<Aside type=\"tip\">\n  **Gas optimization:** This structure saves \\~500 gas units during signature verification. If the signature were in the same cell as the message body, the contract would need to use `slice_hash()` (which rebuilds the cell internally, costing extra gas) instead of simply taking `cell_hash()` of the reference.\n</Aside>\n\n---\n\n### `signature` (512 bits)\n\n**Type:**\\\nEd25519 signature (512 bits).\n\n**What is signed:**\\\nThe hash of the reference cell (`MsgInner`) containing `subwallet_id`, `message_to_send`, `send_mode`, `query_id`, `created_at`, and `timeout`.\n\n**Validation:**\\\nThe contract verifies the signature using:\n\n```func\ncheck_signature(hash(ref_cell), signature, public_key)\n```\n\n**On failure:**\\\nExit code `33`.\n\n**Link:** [Ed25519 signature scheme](https://en.wikipedia.org/wiki/EdDSA#Ed25519)\n\n---\n\n### `subwallet_id` (32 bits)\n\n**Purpose:**\\\nIdentifies which subwallet this message targets.\n\n**Validation:**\\\nMust match the `subwallet_id` stored in contract storage.\n\n**On mismatch:**\\\nExit code `34`.\n\n---\n\n### `query_id` (composite structure)\n\nThe `query_id` follows the `QueryId` TL-B structure and is split into two parts:\n\n- **`shift`** (uint13, 13 bits): high-order bits (range 0 to 8191)\n- **`bit_number`** (## 10): low-order bits with constraints `{ bit_number >= 0 } { bit_number < 1023 }` (range 0 to 1022)\n\n**Total range:**\\\n`2^13 × 1023 = 8,380,416` possible unique query IDs.\n\n**How it maps to the hashmap:**\n\n```text\nhashmap_key = shift (13 bits)\nbit_index = bit_number (10 bits)\n```\n\nThe contract checks if bit `bit_number` is set in the cell stored at `hashmap[shift]`.\n\n**Recommendation:**\\\nIncrement `query_id` sequentially using a counter-based strategy.\n\n---\n\n### `created_at` (64 bits)\n\n**Purpose:**\\\nUnix timestamp (seconds) when the external message was created.\n\n**Validation:**\\\nThe contract performs two checks:\n\n```func\ncreated_at > now() - timeout  // Message not too old\ncreated_at <= now()           // Message not from future\n```\n\n**On failure:**\\\nExit code `35`.\n\n**Why it matters:**\\\nPrevents replay of expired messages. Even if a `query_id` is eventually forgotten, stale messages are rejected based on `created_at`. See [Timestamp validation](#timestamp-validation) for important time lag considerations.\n\n---\n\n### `timeout` (22 bits)\n\n**Purpose:**\\\nDefines the message validity window (in seconds).\n\n**Validation:**\\\nMust match the `timeout` value stored in contract storage.\n\n**On mismatch:**\\\nExit code `38`.\n\n<Aside type=\"note\">\n  22 bits allows timeout values up to \\~4.8 million seconds (\\~55 days).\n</Aside>\n\n---\n\n### `send_mode` (8 bits)\n\n**Purpose:**\\\nSpecifies the [send mode](/foundations/messages/modes) for the internal message.\n\n**Link:** [send\\_raw\\_message modes](/languages/func/stdlib#send-raw-message)\n\n---\n\n### `message_to_send` (reference cell)\n\n**Structure:**\\\nA serialized internal message stored in a reference cell.\n\n**Validation (exit code 37):**\n\nThe contract validates `message_to_send` **after committing storage** to prevent action phase errors. The following checks are performed:\n\n1. **Must be internal message:**\\\n   First bit must be `0` (`int_msg_info$0`, not `ext_msg_info$10`)\n\n1. **Source address must be none:**\\\n   The `src` field must be `addr_none` (empty address)\n\n1. **State-init must not be present:**\\\n   State-init validation is too expensive in gas and is rarely needed. For contract deployment, use the [batch transfer pattern](/standard/wallets/highload/v3/send-batch-transfers) with an action list\n\n1. **Bounced messages are ignored:**\\\n   If the `bounced` flag is set, the message is silently ignored (no error)\n\n<Aside\n  type=\"caution\"\n>\n  **Why validate after commit:**\\\n  Validation occurs after `commit()` to ensure replay protection is saved even if the message structure is invalid. This prevents the same external message from being retried infinitely by lite-servers.\n</Aside>\n\n**Critical limitation:**\\\nHighload v3 can send **only ONE internal message** per external message. For batch transfers, use the [internal\\_transfer pattern](#single-message-per-external) with an action list (up to 254 messages).\n\n---\n\n## Message sending flow\n\nHighload v3 uses a two-transaction pattern to safely send messages:\n\n<Image\n  src=\"/resources/images/wallets/msg_flow_light.png\"\n  darkSrc=\"/resources/images/wallets/msg_flow_dark.png\"\n  alt=\"Message sending flow\"\n/>\n\n<Aside type=\"note\">\n  **Why two transactions?**\n\n  This pattern ensures that replay protection is never rolled back, even if the actual message sending fails due to insufficient funds or other action phase errors. Transaction 1 commits the `query_id` to storage before any outgoing messages are attempted in Transaction 2.\n\n  **Critical detail:** Message validation (step 9) happens **after commit** (step 8) to prevent infinite retries of invalid messages by lite-servers.\n</Aside>\n\nSee [Single message per external](#single-message-per-external) for details on this limitation and the batch transfer workaround.\n\n---\n\n## Exit codes\n\n| Exit code | Name                   | Description                                                                | How to fix                                                                      |\n| --------- | ---------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |\n| `0`       | Success                | Message processed successfully                                             | —                                                                               |\n| `33`      | Invalid signature      | Ed25519 signature verification failed                                      | Check that the private key is correct and the message hash is computed properly |\n| `34`      | Subwallet ID mismatch  | The `subwallet_id` in the message does not match storage                   | Verify you are using the correct `subwallet_id` for this wallet                 |\n| `35`      | Invalid created\\_at    | Message timestamp is invalid (too old or from the future)                  | Ensure `created_at > now() - timeout` and `created_at <= now()`                 |\n| `36`      | Query already executed | The `query_id` was already processed (found in `queries` or `old_queries`) | Use a new, unique `query_id`                                                    |\n| `37`      | Invalid message        | The `message_to_send` structure is invalid or cannot be processed          | Verify the message cell structure and contents                                  |\n| `38`      | Invalid timeout        | The `timeout` in the message does not match storage timeout                | Verify you are using the correct `timeout` value for this wallet                |\n\n---\n\n## Limitations and constraints\n\n### Single message per external\n\n**Limitation:**\\\nEach external message can trigger **only one** outgoing internal message directly.\n\n**Why this limitation?**\\\nManually validating message structure is expensive in gas costs. The contract validates only the single `message_to_send` reference to keep gas consumption predictable and low.\n\n**Why no state-init support?**\\\nState-init validation is complex and gas-intensive, while deploying contracts from a highload wallet is rarely needed. The feature was intentionally excluded to reduce gas costs.\n\n**Workaround for batch transfers:**\\\nSend an internal message to the wallet itself with opcode `0xae42e5a4` (`internal_transfer`) and an action list containing up to **254 outgoing messages** (not 255, because one action slot is reserved for [`set_code` protection](#protection-against-set-code)).\n\n**How to implement:** [Send batch transfers](/standard/wallets/highload/v3/send-batch-transfers)\n\n---\n\n### Query ID space limitations\n\nHighload v3 supports up to **8,380,416 unique query IDs** (see [`query_id` structure](#query-id-composite-structure) for details).\n\n**Impact on throughput:**\\\nIf you send messages faster than `timeout`, you may exhaust available query IDs. After `timeout`, old IDs can be reused.\n\n**Recommended strategy:**\\\nUse a counter-based approach, incrementing `query_id` for each message.\n\n---\n\n### Timeout constraints\n\nThe `timeout` value affects message validity, storage costs, and operational behavior:\n\n**Message validity:**\\\nMessages are valid for `timeout` seconds after `created_at`. Expired messages are rejected with exit code 35.\n\n**Storage costs:**\\\nProcessed `query_id` values remain in storage for up to `2 × timeout` (across `queries` and `old_queries` hashmaps). Longer timeouts increase storage size and costs.\n\n**Operational impact:**\n\n- Short timeout (seconds/minutes): Fast expiration certainty, but messages may expire during network congestion\n- Long timeout (hours): Messages survive congestion, but slow failure detection and higher storage costs\n\n---\n\n### Gas consumption\n\nGas costs vary depending on the number of outgoing messages sent:\n\n| Operation    | Transaction 1 (external) | Transaction 2 (internal) | Total |\n| ------------ | ------------------------ | ------------------------ | ----- |\n| 1 message    | TBD                      | TBD                      | TBD   |\n| 10 messages  | TBD                      | TBD                      | TBD   |\n| 254 messages | TBD                      | TBD                      | TBD   |\n\n**What affects gas costs:**\n\nGas consumption depends **only** on the number of entries in `queries` and `old_queries` hashmaps. Cleanup/rotation operations are highly optimized and add minimal overhead (unlike Highload v2).\n\n**Forward fees:**\n\nThe two-transaction pattern means forward fees are spent **twice**: first when sending the external message (outside → external), then when the wallet sends an internal message to itself (external → internal). This makes Highload v3 approximately **2× more expensive in forward fees** compared to single-transaction wallets like v5.\n\nForward fees scale with:\n\n- Number of outgoing messages\n- Size and complexity of message content\n\n---\n\n## Get methods\n\nHighload Wallet v3 provides several read-only methods for monitoring and verification.\n\n| Method                             | Returns          | Description                                                                   |\n| ---------------------------------- | ---------------- | ----------------------------------------------------------------------------- |\n| `get_public_key()`                 | `int` (256 bits) | Returns the stored public key                                                 |\n| `get_subwallet_id()`               | `int` (32 bits)  | Returns the subwallet ID                                                      |\n| `get_timeout()`                    | `int`            | Returns the current timeout value (stored as uint22)                          |\n| `get_last_clean_time()`            | `int` (64 bits)  | Returns the Unix timestamp of the last cleanup                                |\n| `processed?(query_id, need_clean)` | `(int, int)`     | Checks if `query_id` was processed; optionally indicates if cleanup is needed |\n\n### `processed?` method details\n\n**Parameters:**\n\n- `query_id` (int): The query ID to check.\n- `need_clean` (int): If non-zero, also return whether cleanup is due.\n\n**Returns:**\n\n- First int: `-1` if processed, `0` if not.\n- Second int: `-1` if cleanup is needed, `0` otherwise.\n\n**Use case:**\\\nBefore sending a message, check if a `query_id` was already used to avoid replay errors.\n\n**Link:** [How to verify if a message is processed](/standard/wallets/highload/v3/verify-is-processed)\n\n---\n\n## Protection against `set_code`\n\n**Why this protection is needed:**\n\nThe contract uses `set_actions(actions)` to execute arbitrary actions from the internal message (this allows sending batch transfers). However, leaving the ability to execute `set_code` actions would be unsafe — it creates a risk of **accidentally changing the contract code**.\n\n**How the protection works:**\n\nIn `recv_internal` (Transaction 2), after extracting the action list from the internal message, the contract executes:\n\n```func\ncell old_code = my_code();\nset_actions(actions);      // Apply action list from message\nset_code(old_code);        // Immediately restore original code\n```\n\nThis pattern **prevents any `set_code` action in the action list from taking effect**. Even if an action list accidentally contains a `set_code` instruction, the final `set_code(old_code)` call overwrites it, ensuring the contract code remains unchanged.\n\n**Action list limitation:**\\\nBecause the contract calls `set_code(old_code)` as a protection mechanism, one action slot is consumed. This is why the maximum number of outgoing messages in a batch is **254** (not 255) — one slot is reserved for the `set_code` protection.\n\n---\n\n## Implementation\n\n**Source code:** [`ton-blockchain/highload-wallet-contract-v3`](https://github.com/ton-blockchain/highload-wallet-contract-v3)\n\n**SDK wrappers:**\n\n- **Go:** [`tonutils-go`](https://github.com/xssnick/tonutils-go) — includes Highload v3 wrapper\n- **Python:** [`pytoniq`](https://github.com/yungwine/pytoniq) — includes Highload v3 wrapper\n- **TypeScript/JavaScript:** Copy wrappers from the [official repository](https://github.com/ton-blockchain/highload-wallet-contract-v3/tree/main/wrappers)\n\n**Tests and examples:** See the [tests/](https://github.com/ton-blockchain/highload-wallet-contract-v3/tree/main/tests) directory in the repository for reference implementation and usage patterns.\n\n**Link:** [How-to guides](/standard/wallets/highload/v3/create)\n\n---\n\n## See also\n\n- [How to create Highload Wallet v3](/standard/wallets/highload/v3/create)\n- [How to send single transfer](/standard/wallets/highload/v3/send-single-transfer)\n- [How to send batch transfers](/standard/wallets/highload/v3/send-batch-transfers)\n- [How to verify if a message is processed](/standard/wallets/highload/v3/verify-is-processed)\n"
  },
  {
    "path": "standard/wallets/highload/v3/verify-is-processed.mdx",
    "content": "---\ntitle: \"How to verify message is processed\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nThis guide shows how to verify that a transfer (single or batch) was fully processed across both transactions.\n\n## Objective\n\nBy the end of this guide, you will:\n\n- Verify that both transactions (external and internal) succeeded\n- Calculate how many messages were successfully sent\n- Detect partial failures in batch transfers\n\n## Prerequisites\n\n- Completed [wallet creation](/standard/wallets/highload/v3/create) with funded balance\n- Sent at least one transfer (single or batch)\n- Know the `query_id` and `created_at` values used in the transfer\n\n## Verification overview\n\nHighload Wallet v3 uses a two-transaction pattern. To verify full processing, you need to check both transactions:\n\n1. **External transaction (Transaction 1):** Validates the message and marks `query_id` as processed\n1. **Internal transaction (Transaction 2):** Processes the action list and sends outgoing messages\n\nEven if `processed?` returns `true`, the internal transaction may have failed. Full verification requires checking both transactions.\n\nSee [Message sending flow](/standard/wallets/highload/v3/specification#message-sending-flow) for the complete two-transaction pattern.\n\n## Helper functions\n\nCreate helper functions for transaction search and parsing:\n\n```typescript\nimport { TonClient } from '@ton/ton';\nimport { Cell, Transaction, Address } from '@ton/core';\n\n// Retry helper for network requests\nasync function retry<T>(fn: () => Promise<T>, options: { retries: number; delay: number }): Promise<T> {\n    let lastError: Error | undefined;\n    for (let i = 0; i < options.retries; i++) {\n        try {\n            return await fn();\n        } catch (e) {\n            if (e instanceof Error) lastError = e;\n            await new Promise((resolve) => setTimeout(resolve, options.delay));\n        }\n    }\n    throw lastError;\n}\n\n// Parse external message to extract query_id and created_at\nfunction parseExternalMessageBody(body: Cell) {\n    try {\n        const inner = body.refs[0]!.beginParse();\n        inner.skip(32 + 8); // Skip subwalletId and mode\n        const queryId = inner.loadUintBig(23);\n        const createdAt = inner.loadUint(64);\n        \n        return { queryId, createdAt };\n    } catch (e) {\n        return null;\n    }\n}\n\n// Generic transaction finder with pagination\nasync function findTransaction(\n    client: TonClient,\n    address: Address,\n    predicate: (tx: Transaction) => boolean\n): Promise<Transaction | null> {\n    let lt: string | undefined = undefined;\n    let hash: string | undefined = undefined;\n    \n    while (true) {\n        const transactions = await retry(\n            () => client.getTransactions(address, {\n                hash,\n                lt,\n                limit: 20,\n                archival: true,\n            }),\n            { delay: 1000, retries: 3 }\n        );\n        \n        if (transactions.length === 0) return null;\n        \n        const found = transactions.find(predicate);\n        if (found) return found;\n        \n        const last = transactions.at(-1)!;\n        lt = last.lt.toString();\n        hash = last.hash().toString('base64');\n    }\n}\n```\n\n## Step 1: Set up and check if processed\n\nLoad wallet configuration and check if the `query_id` was marked as processed:\n\n```typescript\nimport { mnemonicToPrivateKey } from '@ton/crypto';\nimport { HighloadWalletV3 } from './wrappers/HighloadWalletV3';\nimport { HighloadQueryId } from './wrappers/HighloadQueryId';\nimport * as fs from 'fs';\n\n// Load wallet data\nconst walletData = JSON.parse(fs.readFileSync('.wallet.json', 'utf-8'));\nconst keyPair = await mnemonicToPrivateKey(walletData.mnemonic.split(' '));\n\nconst CODE = Cell.fromBoc(Buffer.from('b5ee9c7241021001000228000114ff00f4a413f4bcf2c80b01020120020d02014803040078d020d74bc00101c060b0915be101d0d3030171b0915be0fa4030f828c705b39130e0d31f018210ae42e5a4ba9d8040d721d74cf82a01ed55fb04e030020120050a02027306070011adce76a2686b85ffc00201200809001aabb6ed44d0810122d721d70b3f0018aa3bed44d08307d721d70b1f0201200b0c001bb9a6eed44d0810162d721d70b15800e5b8bf2eda2edfb21ab09028409b0ed44d0810120d721f404f404d33fd315d1058e1bf82325a15210b99f326df82305aa0015a112b992306dde923033e2923033e25230800df40f6fa19ed021d721d70a00955f037fdb31e09130e259800df40f6fa19cd001d721d70a00937fdb31e0915be270801f6f2d48308d718d121f900ed44d0d3ffd31ff404f404d33fd315d1f82321a15220b98e12336df82324aa00a112b9926d32de58f82301de541675f910f2a106d0d31fd4d307d30cd309d33fd315d15168baf2a2515abaf2a6f8232aa15250bcf2a304f823bbf2a35304800df40f6fa199d024d721d70a00f2649130e20e01fe5309800df40f6fa18e13d05004d718d20001f264c858cf16cf8301cf168e1030c824cf40cf8384095005a1a514cf40e2f800c94039800df41704c8cbff13cb1ff40012f40012cb3f12cb15c9ed54f80f21d0d30001f265d3020171b0925f03e0fa4001d70b01c000f2a5fa4031fa0031f401fa0031fa00318060d721d300010f0020f265d2000193d431d19130e272b1fb00b585bf03', 'hex'))[0];\n\nconst client = new TonClient({ \n    endpoint: 'https://testnet.toncenter.com/api/v2/jsonRPC', // This is TESTNET endpoint\n    // apiKey: 'your-api-key' // Optional: get from @tonapibot or @tontestnetapibot\n});\n\nconst highloadWallet = HighloadWalletV3.createFromConfig(\n    {\n        publicKey: keyPair.publicKey,\n        subwalletId: walletData.subwalletId,\n        timeout: walletData.timeout,\n    },\n    CODE\n);\nconst wallet = client.open(highloadWallet);\n\n// The query_id and created_at from your transfer\nconst queryId = HighloadQueryId.fromSeqno(17n);\nconst createdAt = 1759878156; // Your actual created_at timestamp\n\n// Check if processed\nconst isProcessed = await wallet.getProcessed(queryId);\nif (!isProcessed) {\n    console.log('❌ Query not processed');\n    return;\n}\nconsole.log('✓ Query marked as processed');\n```\n\n<Aside type=\"note\">\n  **What `processed?` tells you:** This GET method only confirms that the `query_id` was marked as processed in the wallet's storage. It does **not** confirm that the internal transaction succeeded or that messages were sent.\n\n  See [`processed?` method](/standard/wallets/highload/v3/specification#processed%3F-method-details) in the specification for details.\n</Aside>\n\n## Step 2: Find and verify external transaction\n\nSearch transaction history to find the external transaction by `query_id` and `created_at`:\n\n```typescript\n// Find external transaction by query_id + created_at\nasync function findHighloadExternalTransaction(\n    client: TonClient,\n    walletAddress: Address,\n    queryId: HighloadQueryId,\n    createdAt: number\n): Promise<Transaction | null> {\n    const targetQueryId = queryId.getQueryId();\n    \n    return findTransaction(client, walletAddress, (tx) => {\n        if (tx.inMessage?.info.type !== 'external-in') return false;\n        if (!tx.inMessage.body) return false;\n        \n        const parsed = parseExternalMessageBody(tx.inMessage.body);\n        if (!parsed) return false;\n        \n        return parsed.queryId === targetQueryId && parsed.createdAt === createdAt;\n    });\n}\n\nconst externalTx = await findHighloadExternalTransaction(\n    client,\n    highloadWallet.address,\n    queryId,\n    createdAt\n);\n\nif (!externalTx) {\n    console.log('❌ External transaction not found');\n    return;\n}\n\n// Verify external transaction compute phase\nif (externalTx.description.type !== 'generic') {\n    console.log('❌ Invalid transaction');\n    return;\n}\n\nconst externalCompute = externalTx.description.computePhase;\nif (!externalCompute.success || externalCompute.exitCode !== 0) {\n    console.log(`❌ External transaction failed: exit code ${externalCompute.exitCode}`);\n    return;\n}\n\nconsole.log('✓ External transaction succeeded');\n```\n\nIf the external transaction failed, see [Exit codes](/standard/wallets/highload/v3/specification#exit-codes) for troubleshooting.\n\n## Step 3: Find and verify internal transaction\n\nFollow the transaction chain to find and verify Transaction 2:\n\n```typescript\n// Find internal transaction by prevTransactionLt\nasync function findHighloadInternalTransaction(\n    client: TonClient,\n    walletAddress: Address,\n    externalLt: string\n): Promise<Transaction | null> {\n    return findTransaction(client, walletAddress, (tx) => \n        tx.prevTransactionLt.toString() === externalLt\n    );\n}\n\n// Check for outgoing messages\nif (externalTx.outMessagesCount === 0) {\n    console.log('❌ No outgoing messages from external transaction');\n    return;\n}\n\n// Find the internal transaction\nconst internalTx = await findHighloadInternalTransaction(\n    client,\n    highloadWallet.address,\n    externalTx.lt.toString()\n);\n\nif (!internalTx || internalTx.description.type !== 'generic') {\n    console.log('❌ Internal transaction not found');\n    return;\n}\n\n// Verify compute phase\nif (internalTx.description.computePhase.type !== 'vm') {\n    console.log('❌ Compute phase skipped');\n    return;\n}\n\nconst internalCompute = internalTx.description.computePhase;\nif (!internalCompute.success || internalCompute.exitCode !== 0) {\n    console.log(`❌ Internal transaction failed: exit code ${internalCompute.exitCode}`);\n    return;\n}\n\n// Verify action phase\nif (!internalTx.description.actionPhase) {\n    console.log('❌ No action phase in internal transaction');\n    return;\n}\n\nconst action = internalTx.description.actionPhase;\nif (!action.success) {\n    console.log(`❌ Action phase failed: result code ${action.resultCode}`);\n    return;\n}\n\nconsole.log('✓ Internal transaction succeeded');\n```\n\n<Aside type=\"note\">\n  **Transaction linking:** The external transaction creates an outgoing message with `outMsg.createdLt`. The internal transaction that processes this message has `prevTransactionLt` equal to the external transaction's `lt`. This creates a verifiable chain between the two transactions.\n</Aside>\n\n## Step 4: Calculate sent messages\n\nCalculate how many messages were successfully sent:\n\n```typescript\n// Calculate messages sent (total actions - 1 for set_code)\nconst messageActions = action.totalActions - 1;\nconst messagesSent = action.messagesCreated;\nconst messagesFailed = action.skippedActions;\n\nif (messagesFailed > 0) {\n    console.log(`✅ Sent ${messagesSent}/${messageActions} messages (${messagesFailed} failed)`);\n} else {\n    console.log(`✅ Sent ${messagesSent}/${messageActions} messages`);\n}\n```\n\n<Aside\n  type=\"caution\"\n>\n  **Partial failures:** Even if the action phase succeeds overall, some individual messages may fail. Check `skippedActions` to detect partial failures. If `skippedActions > 0`, some messages in the batch were not sent.\n\n  The `totalActions - 1` calculation accounts for the [`set_code` protection](/standard/wallets/highload/v3/specification#protection-against-set-code) action.\n</Aside>\n\n## Expected outputs\n\n### Full success\n\n```text\n✓ Query marked as processed\n✓ External transaction succeeded\n✓ Internal transaction succeeded\n✅ Sent 10/10 messages\n```\n\n### Partial success\n\n```text\n✓ Query marked as processed\n✓ External transaction succeeded\n✓ Internal transaction succeeded\n✅ Sent 8/10 messages (2 failed)\n```\n\n### External transaction failure\n\n```text\n✓ Query marked as processed\n❌ External transaction failed: exit code 35\n```\n\nThe `query_id` is marked as processed, but the transaction failed during validation. See [Exit codes](/standard/wallets/highload/v3/specification#exit-codes) for troubleshooting.\n\n### Internal transaction failure\n\n```text\n✓ Query marked as processed\n✓ External transaction succeeded\n❌ Internal transaction failed: exit code 9\n```\n\nTransaction 1 succeeded (replay protection applied), but Transaction 2 failed. The `query_id` cannot be reused.\n\n### Action phase failure\n\n```text\n✓ Query marked as processed\n✓ External transaction succeeded\n❌ Action phase failed: result code 37\n```\n\nBoth transactions were executed, but the action phase failed to send messages.\n\n## Next steps\n\nYou can now verify any transfer to ensure it was fully processed. This is especially important for batch transfers where partial failures can occur.\n"
  },
  {
    "path": "standard/wallets/history.mdx",
    "content": "---\ntitle: \"Wallets history\"\nsidebarTitle: \"History\"\n---\n\nimport { Aside } from '/snippets/aside.jsx'\n\nYou may have heard about different versions of wallets on TON Blockchain. But what do these versions actually mean, and how do they differ?\n\nIn this article, we will explore the various versions and modifications of TON wallets.\n\n## Common concept\n\nWe should first understand that wallets are not a specific entity in the TON ecosystem. They are still just smart contracts consisting of code and data, and in that sense, are equal to any other actor (i.e., smart contract) in TON.\n\nRead more about [differences](/from-ethereum).\n\nLike your own custom smart contract, or any other one, wallets can receive external and internal messages, send internal messages and logs, and provide `get methods`.\nSo the question is: what functionality do they provide, and how do they differ between versions?\n\nYou can consider each wallet version as a smart contract implementation providing a standard external interface, allowing different external clients to interact with the wallets in the same way. You can find these implementations in FunC and Fift languages in the main TON monorepo:\n\n- [`ton/crypto/smartcont/`](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/)\n\n## Basic wallets\n\n### Wallet contract hashes\n\nHere, you can find the current hashes of the wallet contract code versions.\nFor detailed specifications of each wallet contract, please refer to the sections further down this page.\n\n| Contract version    | Hash                                                               |\n| ------------------- | ------------------------------------------------------------------ |\n| [V1 R1](#wallet-v1) | `a0cfc2c48aee16a271f2cfc0b7382d81756cecb1017d077faaab3bb602f6868c` |\n| [V1 R2](#wallet-v1) | `d4902fcc9fad74698fa8e353220a68da0dcf72e32bcb2eb9ee04217c17d3062c` |\n| [V1 R3](#wallet-v1) | `587cc789eff1c84f46ec3797e45fc809a14ff5ae24f1e0c7a6a99cc9dc9061ff` |\n| [V2 R1](#wallet-v2) | `5c9a5e68c108e18721a07c42f9956bfb39ad77ec6d624b60c576ec88eee65329` |\n| [V2 R2](#wallet-v2) | `fe9530d3243853083ef2ef0b4c2908c0abf6fa1c31ea243aacaa5bf8c7d753f1` |\n| [V3 R1](#wallet-v3) | `b61041a58a7980b946e8fb9e198e3c904d24799ffa36574ea4251c41a566f581` |\n| [V3 R2](#wallet-v3) | `84dafa449f98a6987789ba232358072bc0f76dc4524002a5d0918b9a75d2d599` |\n| [V4 R1](#wallet-v4) | `64dd54805522c5be8a9db59cea0105ccf0d08786ca79beb8cb79e880a8d7322d` |\n| [V4 R2](#wallet-v4) | `feb5ff6820e2ff0d9483e7e0d62c817d846789fb4ae580c878866d959dabd5c0` |\n| [V5 R1](#wallet-v5) | `20834b7b72b112147e1b2fb457b84e74d1a30f04f737d4f62a668e9552d2b72f` |\n\n**Note:** These hashes can also be found in the explorers.\n\n### Wallet V1\n\nThis is the simplest one. It only allows you to send four transactions at a time and doesn't check anything besides your signature and seqno.\n\nWallet source code:\n\n- [`ton/crypto/smartcont/new-wallet.fif`](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/new-wallet.fif)\n\nThis version isn't even used in regular apps because it has some major issues:\n\n- No easy way to retrieve the seqno and public key from the contract.\n- No `valid_until` check, so you can't be sure that the transaction won't be confirmed too late.\n\nThe first issue was fixed in `V1R2` and `V1R3`. The `R` stands for **revision**. Usually, revisions are just minor updates that only add get methods; you can find all of those in the changes history of [`new-wallet.fif`](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/new-wallet.fif). Hereinafter, we will consider only the latest revisions.\n\nNevertheless, because each subsequent version inherits the functionality of the previous one, we should still stick to it, as this will help us with later versions.\n\n#### Official code hashes\n\n| Contract version | Hash                                                               |\n| ---------------- | ------------------------------------------------------------------ |\n| V1 R1            | `a0cfc2c48aee16a271f2cfc0b7382d81756cecb1017d077faaab3bb602f6868c` |\n| V1 R2            | `d4902fcc9fad74698fa8e353220a68da0dcf72e32bcb2eb9ee04217c17d3062c` |\n| V1 R3            | `587cc789eff1c84f46ec3797e45fc809a14ff5ae24f1e0c7a6a99cc9dc9061ff` |\n\n#### Persistent memory layout\n\n- `seqno`: 32-bit long sequence number.\n- `public-key`: 256-bit long public key.\n\n#### External message body layout\n\n1. Data:\n   - `signature`: 512-bit long Ed25519 signature.\n   - `msg-seqno`: 32-bit long sequence number.\n   - `(0-4) mode`: up to four 8-bit long integers defining sending mode for each message.\n1. Up to 4 references to cells containing messages.\n\nAs you can see, the main functionality of the wallet is to provide a safe way to communicate with TON Blockchain from the outside world. The `seqno` mechanism protects against replay attacks, and the `Ed25519 signature` provides authorized access to wallet functionality. The payload data consists of up to 4 references to cells and the corresponding number of modes, which will be directly transferred to the `send_raw_message` method.\n\n<Aside>\n  Note that the wallet doesn't provide any validation for internal messages you send through it. It is the programmer's (i.e., the external client's) responsibility to serialize the data according to the internal message layout.\n</Aside>\n\n#### Exit codes\n\n| Exit code | Description                                      |\n| --------- | ------------------------------------------------ |\n| 33        | `seqno` check failed, replay protection occurred |\n| 34        | `Ed25519 signature` check failed                 |\n| 0         | Standard successful execution exit code.         |\n\n#### Get methods\n\n1. `int seqno()` returns current stored seqno.\n1. `int get_public_key()` returns the current stored public key.\n\n### Wallet V2\n\nWallet source code:\n\n- [`ton/crypto/smartcont/wallet-code.fc`](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/wallet-code.fc)\n\n<Aside>\n  Originally in FunC; compiled to Fift assembly; later optimized `get methods`. \\\n  Final Fift source: [`ton/crypto/smartcont/new-wallet-v2.fif`](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/new-wallet-v2.fif).\n</Aside>\n\nThis version introduces the `valid_until` parameter, which is used to set a time limit for a transaction in case you don't want it to be confirmed too late. This version also does not have a get method for the public key, which was added in `V2R2`.\n\nAll differences compared to the previous version are a consequence of adding the `valid_until` functionality. A new exit code was added: `35`, marking the failure of the `valid_until` check. Additionally, a new Unix time field has been added to the external message body layout, setting the time limit for the transaction. All get methods remain the same.\n\n#### Official code hashes\n\n| Contract version | Hash                                                               |\n| ---------------- | ------------------------------------------------------------------ |\n| V2 R1            | `5c9a5e68c108e18721a07c42f9956bfb39ad77ec6d624b60c576ec88eee65329` |\n| V2 R2            | `fe9530d3243853083ef2ef0b4c2908c0abf6fa1c31ea243aacaa5bf8c7d753f1` |\n\n#### External message body layout\n\n1. Data:\n   - `signature`: 512-bit long Ed25519 signature.\n   - `msg-seqno`: 32-bit long sequence number.\n   - `valid-until`: 32-bit long Unix time integer.\n   - `(0-4) mode`: up to four 8-bit integers defining the sending mode for each message.\n1. Up to 4 references to cells containing messages.\n\n### Wallet V3\n\nThis version introduces the `subwallet_id` parameter, which allows you to create multiple wallets using the same public key (so you can have only one seed phrase and multiple wallets). As before, `V3R2` only adds the get method for the public key.\n\nWallet source code:\n\n- [`ton/crypto/smartcont/wallet3-code.fc`](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/wallet3-code.fc)\n\n<Aside>\n  Originally in FunC; compiled to Fift assembly; later optimized `get methods`. \\\n  Final Fift source: [`ton/crypto/smartcont/wallet-v3-code.fif`](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/wallet-v3-code.fif).\n</Aside>\n\nEssentially, `subwallet_id` is just a number added to the contract state when it’s deployed. Since the contract address in TON is a hash of its state and code, the wallet address will change with a different `subwallet_id`. This version is the most widely used right now. It covers most use cases and remains clean, simple, and mostly the same as previous versions. All get methods remain the same.\n\n#### Official code hashes\n\n| Contract version | Hash                                                               |\n| ---------------- | ------------------------------------------------------------------ |\n| V3 R1            | `b61041a58a7980b946e8fb9e198e3c904d24799ffa36574ea4251c41a566f581` |\n| V3 R2            | `84dafa449f98a6987789ba232358072bc0f76dc4524002a5d0918b9a75d2d599` |\n\n#### Persistent memory layout\n\n- `seqno`: 32-bit sequence number.\n- `subwallet_id`: 32-bit subwallet ID.\n- `public_key`: 256-bit public key.\n\n#### External message body layout\n\n1. Data:\n   - `signature`: 512-bit Ed25519 signature.\n   - `subwallet_id`: 32-bit subwallet ID.\n   - `msg-seqno`: 32-bit sequence number.\n   - `valid-until`: 32-bit Unix time integer.\n   - `(0-4) mode`: up to four 8-bit integers defining the sending mode for each message.\n1. Up to 4 references to cells containing messages.\n\n#### Exit codes\n\n| Exit code | Description                                                             |\n| --------- | ----------------------------------------------------------------------- |\n| 33        | `seqno` check failed; replay protection triggered                       |\n| 34        | `subwallet_id` does not match the stored one                            |\n| 35        | `valid_until` check failed; transaction confirmation attempted too late |\n| 35        | `Ed25519 signature` check failed                                        |\n| 0         | Standard successful execution exit code.                                |\n\n<Aside>\n  In V3, exit code `35` is intentionally re-used for two checks. This is not a typo. In V4 they are split: `35` = signature check failed; `36` = `valid_until` check failed.\n</Aside>\n\n### Wallet V4\n\n**Why V4 was created**: V4 was developed to introduce plugin functionality, allowing third-party smart contracts to interact with wallets in a controlled manner. This enabled features like automated payments, subscriptions, and complex DApp integrations while maintaining security through an allowlist system.\n\nRead about this standard iteration on its dedicated page: [V4 wallet standard](/standard/wallets/v4).\n\n### Wallet V5\n\n**Why V5 was created**: V5 was developed by the Tonkeeper team to address the growing need for gasless transactions, improved extensibility, and better user experience. It adds support for owner-signed internal messages, enabling gasless transactions where users can pay fees in tokens like USDt instead of Toncoin.\n\nIt is the most modern wallet version at the moment, aimed at replacing V4 and allowing arbitrary extensions.\n\nRead more:\n\n- [V5 wallet standard](/standard/wallets/v5)\n- [How to interact with V5 wallet](/standard/wallets/v5-api)\n\n## Special wallets\n\nSometimes the functionality of basic wallets isn't enough. That's why there are several types of specialized wallets: `high-load`, `lockup`, and `restricted`.\n\nLet's have a look at them.\n\n### Highload wallets\n\nWhen working with many messages in a short period, there is a need for a special wallet called a Highload Wallet. Read [the article](/standard/wallets/highload) for more information.\n\n### Lockup wallet\n\nIf you, for some reason, need to lock coins in a wallet for some time without the possibility of withdrawing them before that time passes, have a look at the lockup wallet.\n\nIt allows you to set the time until which you won't be able to withdraw anything from the wallet. You can also customize it by setting unlock periods so that you will be able to spend some coins during these set periods.\n\nFor example, you can create a wallet that will hold 1 million coins with a total vesting time of 10 years. Set the cliff duration to one year, so the funds will be locked for the first year after the wallet is created. Then, you can set the unlock period to one month, so `1'000'000 Toncoin / 120 months = ~8333 Toncoin` will unlock every month.\n\nWallet source code:\n\n- [ton-blockchain/lockup-wallet-contract](https://github.com/ton-blockchain/lockup-wallet-contract)\n\n### Restricted wallet\n\nThis wallet's function is to act like a regular wallet, but restrict transfers to only one pre-defined destination address. You can set the destination when you create this wallet, and then you'll only be able to transfer funds from it to that address. But note that you can still transfer funds to validation contracts, so you can run a validator with this wallet.\n\nWallet source code:\n\n- [EmelyanenkoK/nomination-contract/restricted-wallet](https://github.com/EmelyanenkoK/nomination-contract/tree/master/restricted-wallet)\n\n## Conclusion\n\nAs you can see, there are many different versions of wallets in TON. For new deployments, prefer `V5`. Use `V3R2` or `V4R2` only for legacy compatibility or specific constraints. You can also use one of the special wallets if you want additional functionality like periodic unlocking of funds.\n\n## See also\n\n- [Sources of basic wallets](https://github.com/ton-blockchain/ton/tree/master/crypto/smartcont)\n- [More technical description of versions](https://github.com/toncenter/tonweb/blob/master/src/contract/wallet/WalletSources.md)\n- [Wallet V4 sources and detailed description](https://github.com/ton-blockchain/wallet-contract)\n- [Lockup wallet sources and detailed description](https://github.com/ton-blockchain/lockup-wallet-contract)\n- [Restricted wallet sources](https://github.com/EmelyanenkoK/nomination-contract/tree/master/restricted-wallet)\n- [Gasless transactions on TON](https://medium.com/@buidlingmachine/gasless-transactions-on-ton-75469259eff2)\n"
  },
  {
    "path": "standard/wallets/how-it-works.mdx",
    "content": "---\ntitle: \"How TON wallets work\"\nsidebarTitle: \"How they work\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nWallets are often the entry point of transactions in TON. See [external messages](/foundations/whitepapers/ton#2-4-6-external-messages%2C-or-messages-from-nowhere).\n\n### General principle\n\nA wallet smart contract stores two critical variables — the public key and the sequence number (`seqno`). Together, they secure the wallet.\n\nUsing the public key, the contract verifies that the request comes from the wallet owner; using `seqno`, it protects against replayed transactions (see [How replay protection works](#how-replay-protection-works)).\n\n## Why wallet contracts don't store a `balance` field\n\nIn TON, an account's balance is not stored inside the smart contract's persistent data. It is a part of the protocol-level account state, maintained by validators and updated automatically when value is received/sent and when fees are paid.\n\nTherefore, a wallet contract does not and should not keep a separate `balance` variable in storage. Doing so would be redundant and could drift out of sync with the actual account state.\n\nFrom outside, the balance is exposed via RPC and blockchain explorers as part of the public account state.\n\n## How ownership verification works\n\nWallet contracts use the Ed25519 signature scheme.\nYou generate a private key (keep it safe) and a public key (stored in the contract; readable by anyone).\n\n<Aside\n  type=\"caution\"\n  title=\"Important\"\n>\n  The public key is not the wallet address. The address is [derived](/foundations/addresses/derive) from the contract's [`StateInit`](/foundations/messages/deploy).\n</Aside>\n\nAn external message is sent to the contract (containing a 512‑bit signature and the desired payload). Ed25519 verifies that the provided signature matches the hash of the message.\n\n## How replay protection works\n\n<Aside\n  type=\"note\"\n  title=\"Why do we need replay protection?\"\n>\n  Imagine Alice has 100 TON. Alice sends 10 Toncoin to Bob as a gift. Bob, being sneaky, forwards an identical message to Alice's wallet and would receive another 10 TON — unless the wallet prevents replays.\n</Aside>\n\nEach transaction carries a counter value (in our case, `seqno`) that must be unique and strictly increasing for every outgoing transaction. Because `seqno` changes, the message hash changes as well, making it impossible to reuse a previous signature.\n\n### Role of `valid_until`\n\n`valid_until` is a Unix timestamp embedded into the wallet’s signing message. The wallet rejects any external message if the current time exceeds this value. This limits the lifetime of a signature and prevents an attacker from replaying a captured message indefinitely.\n\nIt also makes retries safe: a client may re-send the same signed message until the deadline; after it expires, the client must re-sign with a new `valid_until`. Combined with `seqno` equality (the contract accepts only the exact current `seqno` and increments it on success), this provides robust replay protection.\n\n## Subwallet ID\n\n`subwallet_id` is a 32‑bit identifier tied to a wallet instance. It is set at wallet creation time and is included in the signing message. On each external call, the wallet verifies that the provided `subwallet_id` matches its own; otherwise, the message is rejected.\n\nBy varying `subwallet_id`, you can deploy multiple independent wallet contracts controlled by the same public key, each with its own address and `seqno`. This is useful for separating accounts, environments, or business lines while keeping a single keypair.\n\n<Aside\n  type=\"caution\"\n  title=\"Important\"\n>\n  Changing `subwallet_id` creates a different wallet address. Funds are not shared across subwallets even if they use the same public key.\n</Aside>\n"
  },
  {
    "path": "standard/wallets/interact.mdx",
    "content": "---\ntitle: \"How to interact with wallet\"\nsidebarTitle: \"How to interact\"\n---\n\nimport { Aside } from '/snippets/aside.jsx'\n\nCreating a wallet involves several steps\n\n- Generate a mnemonic; wallet will be still in [`nonexist`](/foundations/status#status-variety) status.\n- Derive the public key and the wallet address out of it.\n- Put some funds to the address; wallet account will move to [`uninit`](/foundations/status#status-variety) status.\n- Deploy code of wallet contract to that address; account will move to [`active`](/foundations/status#status-variety) status.\n\n## Derive wallet address\n\nThe following algorithm is used by wallet apps, and has to be replicated if the same wallet address should be generated programmatically.\n\nA wallet account's address is [derived](/foundations/addresses/derive) from [`StateInit`](/foundations/messages/deploy) that stores in its `data` field two values:\n\n- `public_key`, dependent on the [mnemonic](/standard/wallets/mnemonics);\n- `wallet_id`, a special [salt-like](https://en.wikipedia.org/wiki/Salt_\\(cryptography\\)) field, dependent on the wallet contract type and the `network_id`.\n\n<Aside type=\"note\">\n  Sometimes `wallet_id` is also called `subwallet_id` in some of the libraries and documentation. They mean the same thing.\n</Aside>\n\nThis means that the mnemonic alone does not determine an address uniquely: `wallet_id` has to be known to compute the address.\n\n### Default `wallet_id` values\n\n| Network | [V4R2](/standard/wallets/v4) | [V5](/standard/wallets/v5) |\n| ------- | ---------------------------- | -------------------------- |\n| Mainnet | `0x29a9a317` (698983191)     | `0x7FFFFF11` (2147483409)  |\n| Testnet | `0x29a9a317` (698983191)     | `0x7FFFFFFD` (2147483645)  |\n\nFor Wallet V4R2 `wallet_id` is defined as first 4 bytes from TON mainnet blockchain initial state hash. There is no specific logic why this number was chosen, community needed some default value and this one works well enough.\n\nFor Wallet V5, `wallet_id` is different between Mainnet and Testnet for security reasons. There will be different wallet addresses for different networks with the same mnemonic. This prevents replaying transactions from testnet on mainnet, and ensuing loss of funds. The `wallet_id` value is obtained from\n\n- `network_id`: `-239` for mainnet, `-3` for testnet,\n- `wallet_version`: currently always `0`,\n- `subwallet_number`: `0` by default,\n- `workchain`: `0` for basechain\n\nby the following algorithm:\n\n```ts\ntype WalletIdV5 = {\n    // currently always 0\n    readonly walletVersion: number;\n    // -239 for mainnet, -3 for testnet\n    readonly networkGlobalId: number;\n    // 0 for basechain\n    readonly workchain: number;\n    // 0 for the first wallet with this mnemonic\n    readonly subwalletNumber: number;\n}\n\nexport function storeWalletIdV5(walletId: WalletIdV5) {\n    return (builder: Builder) => {\n        builder.storeInt(walletId.networkGlobalId, 32);\n        builder.storeInt(walletId.workchain, 8);\n        builder.storeUint(walletId.walletVersion, 8);\n        builder.storeUint(walletId.subwalletNumber, 32);\n    }\n}\n```\n\n<Aside type=\"note\">\n  Algorithm here is presented for educational purposes, in most cases there is no need to reimplement it. Use the existing implementation from TON SDKs instead.\n</Aside>\n\n### Examples\n\nThe following examples use wrappers for wallet contracts from the [`@ton/ton`](https://github.com/ton-org/ton) TypeScript SDK.\n\n#### Wallet V4R2\n\n```ts expandable\nimport { mnemonicToPrivateKey } from '@ton/crypto';\nimport { WalletContractV4 } from '@ton/ton';\n\n// 12‑ or 24‑word mnemonic (space‑separated)\nconst mnemonic = 'bread table ...';\n\n// async function for await\nconst main = async () => {\n    const keyPair = await mnemonicToPrivateKey(\n        mnemonic.split(' ')\n    );\n    const walletContractV4 = WalletContractV4.create({\n        workchain: 0,\n        publicKey: keyPair.publicKey,\n        // this magic number is default wallet_id for V4R2 wallet contract\n        walletId: 0x29a9a317,\n    });\n    console.log(walletContractV4.address);\n}\n\nvoid main();\n```\n\n#### Wallet V5\n\n```ts expandable\nimport { mnemonicToPrivateKey } from '@ton/crypto';\nimport { WalletContractV5R1 } from '@ton/ton';\n\n// 12‑ or 24‑word mnemonic (space‑separated).\nconst mnemonic = 'foo bar baz ...';\n\n// async function for await\nconst main = async () => {\n    const keyPair = await mnemonicToPrivateKey(\n        mnemonic.split(' '),\n    );\n\n    // testnet\n    const testnetV5Wallet = WalletContractV5R1.create({\n        walletId: {\n            networkGlobalId: -3,\n        },\n        publicKey: keyPair.publicKey,\n        workchain: 0,\n    });\n\n    console.log(testnetV5Wallet.address);\n\n    // mainnet\n    const mainnetV5Wallet = WalletContractV5R1.create({\n        walletId: {\n            networkGlobalId: -239,\n        },\n        publicKey: keyPair.publicKey,\n        workchain: 0,\n    });\n\n    console.log(mainnetV5Wallet.address);\n};\n\nvoid main();\n```\n\nThis wallet contract instance can be used to [send messages](/standard/wallets/v5-api) to the blockchain.\n\n## Comments\n\nWallet apps can attach short human-readable notes — commonly called _comments_ — to outgoing internal messages. On-chain they are just message bodies with a specific layout that ecosystem agreed to interpret as text.\n\n### Comment format\n\n- The first 32 bits of the incoming message body must be the opcode `0x00000000`. This value signals that the rest of the payload should be treated as a comment.\n- The remaining bytes are UTF-8 encoded text. Wallet apps should tolerate invalid or empty strings — many senders emit messages without a comment or with zero-length payloads.\n- When parsing, always inspect the opcode before assuming a text comment. If the opcode differs, fall back to handling other contract-specific payloads.\n\nBecause comments ride inside ordinary internal messages, the format works identically for:\n\n- native Toncoin transfers between wallets;\n- [Jetton transfers](/standard/tokens/jettons/api#forward-payload-formats), where the wallet forwards an internal message to the token wallet along with the comment payload;\n- [NFT transfers](/standard/tokens/nft/api#forward-payload-formats), where the comment travels in the same forwarding message that moves the ownership record.\n\n### Attaching a comment when sending\n\nTo include a comment in an outgoing transfer, construct an internal message body that starts with `0x00000000` and append the UTF-8 bytes of the note YOU want to share. Most wallet libraries expose helpers for this, but the underlying steps are:\n\n1. Allocate a cell.\n1. Store the 32-bit zero opcode.\n1. Store the text as a [byte string](/standard/tokens/metadata#snake-data-encoding) (UTF-8 encoded).\n1. Send the internal message along with the desired Toncoin, [Jettons](/standard/tokens/jettons/how-it-works), or [NFT](/standard/tokens/nft/how-it-works) payload.\n\nReceivers that follow the convention will display the decoded text to the user. Contracts that do not recognize the opcode will simply ignore it or treat the message body as opaque data, so comments are backward-compatible with existing transfers.\n\n### Example: Sending a comment with `@ton/core`\n\n```ts\nimport { Cell, beginCell } from '@ton/core';\n\nfunction createCommentCell(comment: string): Cell {\n    return beginCell()\n        // opcode for comment\n        .storeUint(0, 32)\n        // UTF-8 encoded text in snake encoding\n        .storeStringTail(comment)\n        .endCell();\n}\n```\n"
  },
  {
    "path": "standard/wallets/lockup.mdx",
    "content": "---\ntitle: \"Lockup wallet\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nLockup wallet is a specialized wallet contract that locks funds until a specified time. The [repository](https://github.com/ton-blockchain/lockup-wallet-contract) contains two implementations with different unlocking mechanisms.\n\n## Universal Lockup Wallet\n\n[Universal Lockup Wallet](https://github.com/ton-blockchain/lockup-wallet-contract/tree/c2c9f73394853780621e6215410a95475ac7cf4f/universal) implements time-based fund locking with allowlist functionality. All funds unlock simultaneously when the time restrictions expire.\n\nSource code: [`universal/uni-lockup-wallet.fc`](https://github.com/ton-blockchain/lockup-wallet-contract/blob/c2c9f73394853780621e6215410a95475ac7cf4f/universal/uni-lockup-wallet.fc)\n\n### Use cases\n\nEscrow services. Lock funds until conditions are met, with allowlist of valid recipients.\n\n### Persistent memory layout\n\n```tlb\nstorage$_\n  seqno:uint32\n  subwallet_id:uint32\n  public_key:uint256\n  config_public_key:uint256\n  allowed_destinations:(PfxHashmapE 267 ^Cell)\n  total_locked_value:Coins\n  locked:HashmapE 32 Coins\n  total_restricted_value:Coins\n  restricted:HashmapE 32 Coins\n  = Storage;\n```\n\n- `seqno`: 32-bit sequence number for replay protection.\n- `subwallet_id`: 32-bit wallet identifier.\n- `public_key`: 256-bit Ed25519 public key for signing external messages (wallet operations).\n- `config_public_key`: 256-bit Ed25519 public key for signing internal messages that add locked funds. This separation allows a third party to initialize and fund the lockup wallet without having access to spend the funds.\n- `allowed_destinations`: Prefix dictionary of allowlisted destination addresses (uses `pfxdict_get?` for prefix matching).\n- `total_locked_value`: Total amount of locked funds (unrestricted destinations).\n- `locked`: Dictionary mapping unlock timestamps to locked amounts.\n- `total_restricted_value`: Total amount of restricted funds (allowlist-only).\n- `restricted`: Dictionary mapping unlock timestamps to restricted amounts.\n\n### Message layout\n\n#### External message body layout\n\n- `signature`: 512-bit Ed25519 signature.\n- `subwallet_id`: 32-bit subwallet identifier.\n- `valid_until`: 32-bit Unix timestamp.\n- `msg_seqno`: 32-bit sequence number.\n- Message list: References to messages to send.\n\nThe contract unlocks expired funds, reserves locked amounts using `raw_reserve(effectively_locked, 2)`, and sends messages. Each message is sent with its specified mode, but if mode is not 2, it's forced to mode 3 (pay fees separately, ignore errors).\n\n#### Internal message body layout\n\nInternal messages with `op = 0x82eaf9c4` (`rwallet_op`) allow adding locked funds:\n\n```tlb\nrwallet_op#82eaf9c4\n  signature:(## 512)\n  cmd:(## 32)\n  only_restrict:(## 1)\n  timestamp:(## 32)\n  = InternalMsgBody;\n```\n\nMessage requirements:\n\n- Must carry ≥1 TON value.\n- Contain valid signature from `config_public_key`.\n- `cmd` must be `0x373aa9f4` (`restricted_transfer`).\n- `only_restrict`: Flag determining lock type: `1` for restricted funds, `0` for locked funds.\n- `timestamp`: Unix timestamp for unlock.\n\n<Aside type=\"note\">\n  Internal messages with other opcodes from allowlisted addresses are silently ignored.\n</Aside>\n\n### Get methods\n\n1. `int seqno()` returns current sequence number.\n1. `int wallet_id()` returns current subwallet ID.\n1. `int get_public_key()` returns stored public key.\n1. `(int, int, int) get_balances_at(int time)` returns balance, restricted value, and locked value at specified time.\n1. `(int, int, int) get_balances()` returns current balance, restricted value, and locked value.\n1. `int check_destination(slice destination)` returns whether destination address is allowlisted.\n\n<Aside type=\"note\">\n  There is no get-method for `config_public_key`. This is by design — the configuration key is only used internally for adding locked funds.\n</Aside>\n\n### Exit codes\n\n| Exit code | Description                                       |\n| --------- | ------------------------------------------------- |\n| 31        | Signature verification failed (`wrong_signature`) |\n| 32        | Config signature verification failed              |\n| 33        | Message value too small (\\< 1 TON)                |\n| 34        | Sequence number mismatch (`wrong_seqno`)          |\n| 35        | Subwallet ID mismatch (`wrong_subwallet_id`)      |\n| 36        | Message expired (`replay_protection`)             |\n| 40        | Unknown operation code (`unknown_op`)             |\n| 41        | Unknown command (`unknown_cmd`)                   |\n\n## Vesting Wallet\n\n[Vesting Wallet](https://github.com/ton-blockchain/lockup-wallet-contract/tree/c2c9f73394853780621e6215410a95475ac7cf4f/vesting) implements gradual fund unlocking over time with an optional cliff period. The funds unlock linearly according to a vesting schedule.\n\nAvailable through [web interface](https://toncenter.github.io/lockup-sender). [Source code](https://github.com/ton-blockchain/lockup-wallet-contract/blob/c2c9f73394853780621e6215410a95475ac7cf4f/vesting/vesting-lockup-wallet.fc).\n\n### Use cases\n\nEmployee token vesting. Lock employee tokens with vesting schedule (e.g., 4 years with 1-year cliff).\n\n### Persistent memory layout\n\n```tlb\nstorage$_\n  stored_seqno:uint32\n  stored_subwallet:uint32\n  public_key:uint256\n  start_time:uint64\n  total_duration:uint32\n  unlock_period:uint32\n  cliff_duration:uint32\n  total_amount:Coins\n  allow_elector:Bool\n  = Storage;\n```\n\n- `stored_seqno`: 32-bit sequence number (replay protection).\n- `stored_subwallet`: 32-bit wallet identifier.\n- `public_key`: 256-bit Ed25519 public key for signing external messages.\n- `start_time`: 64-bit Unix timestamp when vesting begins.\n- `total_duration`: 32-bit total vesting duration in seconds.\n- `unlock_period`: 32-bit period between unlocks in seconds.\n- `cliff_duration`: 32-bit cliff period before first unlock.\n- `total_amount`: Total amount subject to vesting.\n- `allow_elector`: Boolean flag that bypasses vesting restrictions for transfers to [Elector](/foundations/system#elector) and [Config](/foundations/system#config) contracts.\n\n### Message layout\n\n#### External message body layout\n\n- `signature`: 512-bit Ed25519 signature.\n- `subwallet_id`: 32-bit subwallet identifier.\n- `valid_until`: 32-bit Unix timestamp.\n- `msg_seqno`: 32-bit sequence number.\n- Optional: One message reference. If present, mode MUST be 3 (pay fees separately, ignore errors).\n\nThe contract calculates locked amount based on vesting schedule:\n\n- Before `start_time + cliff_duration`: All funds locked.\n- During vesting: Linear unlock based on `unlock_period`.\n- After `start_time + total_duration`: All funds unlocked.\n\nWhen `allow_elector` is enabled, vesting restrictions are bypassed for transfers to system contracts (see `allow_elector` field description above).\n\n#### Internal message body layout\n\nInternal messages are ignored (no operations performed).\n\n### Get methods\n\n1. `int seqno()` returns current sequence number.\n1. `int get_public_key()` returns stored public key.\n1. `int get_locked_amount(int now_time)` returns locked amount at specified time.\n1. `(int, int, int, int, int, int) get_lockup_data()` returns `(start_time, total_duration, unlock_period, cliff_duration, total_amount, allow_elector)`.\n\n### Exit codes\n\n| Exit code | Description                                      |\n| --------- | ------------------------------------------------ |\n| 33        | Sequence number mismatch                         |\n| 34        | Subwallet ID mismatch                            |\n| 35        | Signature verification failed                    |\n| 36        | Message expired (`valid_until` check failed)     |\n| 37        | Invalid number of message references             |\n| 38        | Invalid send mode (must be 3 if message present) |\n"
  },
  {
    "path": "standard/wallets/mnemonics.mdx",
    "content": "---\ntitle: \"Mnemonics\"\nsidebarTitle: \"Mnemonics\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n\n## Key pair \n\nTON Blockchain uses asymmetric cryptography, such as the [Ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519) signature scheme.\n\nThere are multiple ways to derive a key pair from a mnemonic. Below is the most common approach in TON.\n\n<Aside>\n  Some apps in the TON ecosystem may use a different derivation method, eventually producing an Ed25519-conformant key pair.\n</Aside>\n\n## Key pair from a mnemonic\n\nTo transform a mnemonic phrase into a key pair, a `seed` is first derived using [PBKDF2](https://en.wikipedia.org/wiki/PBKDF2), and the key pair is then derived from that `seed`.\n\nPBKDF2 has [five input parameters](https://en.wikipedia.org/wiki/PBKDF2#Key_derivation_process): `PRF`, `Password`, `Salt`, `c`, and `dkLen`. Each of those parameters is assigned a concrete value.\n\nThe most commonly used values are:\n\n| Parameter  | Description | Value\n| :--------- | :---------- | :----\n| `PRF`      | Pseudo-random function of two parameters | [HMAC‑SHA512](https://en.wikipedia.org/wiki/HMAC)\n| `Password` | Master password from which a derived key is generated | `\"\"`\n| `Salt`     | Sequence of bits, known as a [cryptographic salt](https://en.wikipedia.org/wiki/Salt_(cryptography)) | `\"TON default seed\"`\n| `c`        | Number of iterations desired | 100000\n| `dkLen`    | Desired bit-length of the derived key | 64\n\n### Generate a key pair \n\n```ts title=\"TypeScript\"\nimport { mnemonicToPrivateKey, mnemonicNew } from \"@ton/crypto\";\n\n// Replace with your own persisted mnemonic phrase (see note below).\nconst mnemonicArray = await mnemonicNew();\n\n// derive private and public keys from the mnemonic\nconst keyPair = await mnemonicToPrivateKey(mnemonicArray); \n\nconsole.log(\"Public Key: \" + keyPair.publicKey.toString('hex'));\nconsole.log(\"Private Key: \" + keyPair.secretKey.toString('hex'));\n```\n\nThe private key is needed to sign messages, and the public key is stored in the wallet's smart contract. When new external messages arrive on that smart contract, the public key would be used to check the authenticity of the messages signed using the corresponding private key.\n\n<Aside type=\"caution\" title=\"Important\">\n  Save the generated mnemonic seed phrase. If you need deterministic behavior during development, print and reuse the exact phrase so the wallet derives the same key pair on every run.\n</Aside>\n\n## Mnemonic validation \n\n1. Check that all the words are from the list of [BIP-39](https://github.com/ton-org/ton-crypto/blob/c3435833a0da52a96f674c352c4c6f91fcc07f6d/src/mnemonic/wordlist.ts#L9). \n2. If a password is used: the first byte of the derived `seed` computed with `c = 1` and `salt = 'TON fast seed version'` must equal `0`.\n3. If no password is used: the first byte of the derived `seed` computed with `c = floor(100000/256) = 390` and `salt = 'TON seed version'` must equal `1`.\n\nRandom mnemonic phrases are generated until PBKDF2 yields a seed whose first byte matches the expected version (0 for the 'fast seed' parameters, 1 for the 'seed version' parameters); then a valid mnemonic is returned.\n\n### Generate a mnemonic\n\n```ts title=\"TypeScript\"\nimport { mnemonicNew } from \"@ton/crypto\";\n\nconst mnemonicArray = await mnemonicNew(); \nconsole.log(mnemonicArray); \n```"
  },
  {
    "path": "standard/wallets/performance.mdx",
    "content": "---\ntitle: \"Performance benchmark\"\nmode: \"wide\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\"\n\nThe following benchmarks compare gas consumption and throughput across different wallet versions when sending multiple messages. These measurements help determine the most cost-effective wallet for specific use cases.\n\nThe benchmarks measure the gas consumed by the wallet contract itself, including `fwd_fee` and gas costs. The final transaction fee may vary depending on the destination address and message processing requirements. Each benchmark includes theoretical and real-time measurements: theoretically, messages can be sent every 3-5 seconds when a new block appears, but in practice, messages can be sent every 12-14 seconds due to network conditions and block confirmation times.\n\n<Aside type=\"note\">\n  The complete benchmark source code and test suite are available in the [`docs-examples` GitHub repository](https://github.com/ton-org/docs-examples/tree/9-wallet-bench/standard/wallets/comparison).\n</Aside>\n\n<Aside\n  type=\"danger\"\n>\n  Preprocessed Wallet V2 is shown separately because it is a community implementation and not an official TON standard. Users assume all risks when using this wallet implementation. Always verify the contract code and understand the security implications before use.\n</Aside>\n\n### Sending TONs\n\n#### 1 Messages\n\n|   Wallet Version   | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :----------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n| **Wallet V2R1** ✅ |    **Best** |    **Best** |        1 |     2,769 |   2,769 |       0.0017108 |     0.0017108 |           13s |              4s |\n|     Wallet V2R2    |      +2.78% |      +1.80% |        1 |     2,846 |   2,846 |       0.0017416 |     0.0017416 |           13s |              4s |\n|     Wallet V3R1    |      +5.34% |      +3.46% |        1 |     2,917 |   2,917 |       0.0017700 |     0.0017700 |           13s |              4s |\n|     Wallet V3R2    |      +8.12% |      +5.26% |        1 |     2,994 |   2,994 |       0.0018008 |     0.0018008 |           13s |              4s |\n|     Wallet V4R2    |     +19.46% |     +12.60% |        1 |     3,308 |   3,308 |       0.0019264 |     0.0019264 |           13s |              4s |\n|     Wallet V5R1    |     +78.36% |     +56.34% |        1 |     4,939 |   4,939 |       0.0026748 |     0.0026748 |           13s |              4s |\n| Highload Wallet V3 |    +187.32% |    +187.14% |        1 |     7,956 |   7,956 |       0.0049124 |     0.0049124 |           13s |              4s |\n\n**Preprocessed Wallet V2**\n\n|     Wallet Version     | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :--------------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n| Preprocessed Wallet V2 |     -44.49% |     -18.98% |        1 |     1,537 |   1,537 |       0.0013860 |     0.0013860 |           13s |              4s |\n\n#### 4 Messages\n\n|   Wallet Version   | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :----------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n| **Wallet V2R1** ✅ |    **Best** |    **Best** |        1 |     4,695 |   1,173 |       0.0030908 |     0.0007727 |           13s |              4s |\n|     Wallet V2R2    |      +1.70% |      +0.99% |        1 |     4,772 |   1,193 |       0.0031216 |     0.0007804 |           13s |              4s |\n|     Wallet V3R1    |      +3.15% |      +1.91% |        1 |     4,843 |   1,210 |       0.0031500 |     0.0007875 |           13s |              4s |\n|     Wallet V3R2    |      +4.85% |      +2.91% |        1 |     4,920 |   1,230 |       0.0031808 |     0.0007952 |           13s |              4s |\n|     Wallet V4R2    |     +11.50% |      +6.97% |        1 |     5,234 |   1,308 |       0.0033064 |     0.0008266 |           13s |              4s |\n|     Wallet V5R1    |     +51.06% |     +39.53% |        1 |     7,090 |   1,772 |       0.0043128 |     0.0010782 |           13s |              4s |\n| Highload Wallet V3 |     +69.56% |    +109.25% |        1 |     7,956 |   1,989 |       0.0064676 |     0.0016169 |           13s |              4s |\n\n**Preprocessed Wallet V2**\n\n|     Wallet Version     | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :--------------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n| Preprocessed Wallet V2 |     -67.26% |     -29.99% |        1 |     1,537 |     384 |       0.0021636 |     0.0005409 |           13s |              4s |\n\n#### 200 Messages\n\n|       Wallet Version      | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :-----------------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n|        Wallet V2R1        |   +2907.69% |     +42.99% |       50 |   234,750 |   1,173 |       0.1545400 |   0.000772700 |       10m 50s |          3m 20s |\n|        Wallet V2R2        |   +2958.97% |     +44.41% |       50 |   238,600 |   1,193 |       0.1560800 |   0.000780400 |       10m 50s |          3m 20s |\n|        Wallet V3R1        |   +3002.56% |     +45.73% |       50 |   242,150 |   1,210 |       0.1575000 |   0.000787500 |       10m 50s |          3m 20s |\n|        Wallet V3R2        |   +3053.84% |     +47.15% |       50 |   246,000 |   1,230 |       0.1590400 |   0.000795200 |       10m 50s |          3m 20s |\n|        Wallet V4R2        |   +3253.84% |     +52.96% |       50 |   261,700 |   1,308 |       0.1653200 |   0.000826600 |       10m 50s |          3m 20s |\n|        Wallet V5R1        |   +1792.30% |      +3.01% |        1 |   147,622 |     738 |       0.1113288 |   0.000556644 |           13s |              4s |\n| **Highload Wallet V3** ✅ |    **Best** |    **Best** |        1 |     7,956 |      39 |       0.1080740 |   0.000540370 |           13s |              4s |\n\n**Preprocessed Wallet V2**\n\n|     Wallet Version     | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :--------------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n| Preprocessed Wallet V2 |     -82.05% |     -50.99% |        1 |     1,537 |       7 |       0.0529668 |   0.000264834 |           13s |              4s |\n\n#### 1000 Messages\n\n|       Wallet Version      | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :-----------------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n|        Wallet V2R1        |   +3683.87% |     +44.18% |      250 | 1,173,750 |   1,173 |       0.7727000 |   0.000772700 |       54m 10s |         16m 40s |\n|        Wallet V2R2        |   +3748.38% |     +45.61% |      250 | 1,193,000 |   1,193 |       0.7804000 |   0.000780400 |       54m 10s |         16m 40s |\n|        Wallet V3R1        |   +3803.22% |     +46.94% |      250 | 1,210,750 |   1,210 |       0.7875000 |   0.000787500 |       54m 10s |         16m 40s |\n|        Wallet V3R2        |   +3867.74% |     +48.37% |      250 | 1,230,000 |   1,230 |       0.7952000 |   0.000795200 |       54m 10s |         16m 40s |\n|        Wallet V4R2        |   +4119.35% |     +54.23% |      250 | 1,308,500 |   1,308 |       0.8266000 |   0.000826600 |       54m 10s |         16m 40s |\n|        Wallet V5R1        |   +2264.51% |      +3.46% |        4 |   733,888 |     733 |       0.5545152 |   0.000554515 |           52s |             16s |\n| **Highload Wallet V3** ✅ |    **Best** |    **Best** |        4 |    31,689 |      31 |       0.5359220 |   0.000535922 |           13s |              4s |\n\n**Preprocessed Wallet V2**\n\n|     Wallet Version     | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :--------------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n| Preprocessed Wallet V2 |     -80.64% |     -50.79% |        4 |     6,148 |       6 |       0.2637072 |   0.000263707 |           52s |             16s |\n\n### Sending Comment\n\n#### 1 Messages\n\n|   Wallet Version   | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :----------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n| **Wallet V2R1** ✅ |    **Best** |    **Best** |        1 |     2,769 |   2,769 |       0.0017620 |     0.0017620 |           13s |              4s |\n|     Wallet V2R2    |      +2.78% |      +1.74% |        1 |     2,846 |   2,846 |       0.0017928 |     0.0017928 |           13s |              4s |\n|     Wallet V3R1    |      +5.34% |      +3.35% |        1 |     2,917 |   2,917 |       0.0018212 |     0.0018212 |           13s |              4s |\n|     Wallet V3R2    |      +8.12% |      +5.10% |        1 |     2,994 |   2,994 |       0.0018520 |     0.0018520 |           13s |              4s |\n|     Wallet V4R2    |     +19.46% |     +12.23% |        1 |     3,308 |   3,308 |       0.0019776 |     0.0019776 |           13s |              4s |\n|     Wallet V5R1    |     +78.36% |     +54.71% |        1 |     4,939 |   4,939 |       0.0027260 |     0.0027260 |           13s |              4s |\n| Highload Wallet V3 |    +187.32% |    +184.60% |        1 |     7,956 |   7,956 |       0.0050148 |     0.0050148 |           13s |              4s |\n\n**Preprocessed Wallet V2**\n\n|     Wallet Version     | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :--------------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n| Preprocessed Wallet V2 |     -44.49% |     -18.43% |        1 |     1,537 |   1,537 |       0.0014372 |     0.0014372 |           13s |              4s |\n\n#### 4 Messages\n\n|   Wallet Version   | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :----------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n| **Wallet V2R1** ✅ |    **Best** |    **Best** |        1 |     4,695 |   1,173 |       0.0032956 |     0.0008239 |           13s |              4s |\n|     Wallet V2R2    |      +1.70% |      +0.93% |        1 |     4,772 |   1,193 |       0.0033264 |     0.0008316 |           13s |              4s |\n|     Wallet V3R1    |      +3.15% |      +1.79% |        1 |     4,843 |   1,210 |       0.0033548 |     0.0008387 |           13s |              4s |\n|     Wallet V3R2    |      +4.85% |      +2.73% |        1 |     4,920 |   1,230 |       0.0033856 |     0.0008464 |           13s |              4s |\n|     Wallet V4R2    |     +11.50% |      +6.54% |        1 |     5,234 |   1,308 |       0.0035112 |     0.0008778 |           13s |              4s |\n|     Wallet V5R1    |     +51.06% |     +37.07% |        1 |     7,090 |   1,772 |       0.0045176 |     0.0011294 |           13s |              4s |\n| Highload Wallet V3 |     +69.56% |    +108.67% |        1 |     7,956 |   1,989 |       0.0068772 |     0.0017193 |           13s |              4s |\n\n**Preprocessed Wallet V2**\n\n|     Wallet Version     | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :--------------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n| Preprocessed Wallet V2 |     -67.26% |     -28.13% |        1 |     1,537 |     384 |       0.0023684 |     0.0005921 |           13s |              4s |\n\n#### 200 Messages\n\n|     Wallet Version     | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :--------------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n|       Wallet V2R1      |   +2907.69% |     +35.54% |       50 |   234,750 |   1,173 |       0.1647800 |   0.000823900 |       10m 50s |          3m 20s |\n|       Wallet V2R2      |   +2958.97% |     +36.81% |       50 |   238,600 |   1,193 |       0.1663200 |   0.000831600 |       10m 50s |          3m 20s |\n|       Wallet V3R1      |   +3002.56% |     +37.97% |       50 |   242,150 |   1,210 |       0.1677400 |   0.000838700 |       10m 50s |          3m 20s |\n|       Wallet V3R2      |   +3053.84% |     +39.24% |       50 |   246,000 |   1,230 |       0.1692800 |   0.000846400 |       10m 50s |          3m 20s |\n|       Wallet V4R2      |   +3253.84% |     +44.41% |       50 |   261,700 |   1,308 |       0.1755600 |   0.000877800 |       10m 50s |          3m 20s |\n|   **Wallet V5R1** ✅   |   +1792.30% |    **Best** |        1 |   147,622 |     738 |       0.1215688 |   0.000607844 |           13s |              4s |\n| **Highload Wallet V3** |    **Best** |      +5.74% |        1 |     7,956 |      39 |       0.1285540 |   0.000642770 |           13s |              4s |\n\n**Preprocessed Wallet V2**\n\n|     Wallet Version     | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :--------------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n| Preprocessed Wallet V2 |     -82.05% |     -48.00% |        1 |     1,537 |       7 |       0.0632068 |   0.000316034 |           13s |              4s |\n\n#### 1000 Messages\n\n|     Wallet Version     | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :--------------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n|       Wallet V2R1      |   +3683.87% |     +36.02% |      250 | 1,173,750 |   1,173 |       0.8239000 |   0.000823900 |       54m 10s |         16m 40s |\n|       Wallet V2R2      |   +3748.38% |     +37.29% |      250 | 1,193,000 |   1,193 |       0.8316000 |   0.000831600 |       54m 10s |         16m 40s |\n|       Wallet V3R1      |   +3803.22% |     +38.46% |      250 | 1,210,750 |   1,210 |       0.8387000 |   0.000838700 |       54m 10s |         16m 40s |\n|       Wallet V3R2      |   +3867.74% |     +39.73% |      250 | 1,230,000 |   1,230 |       0.8464000 |   0.000846400 |       54m 10s |         16m 40s |\n|       Wallet V4R2      |   +4119.35% |     +44.91% |      250 | 1,308,500 |   1,308 |       0.8778000 |   0.000877800 |       54m 10s |         16m 40s |\n|   **Wallet V5R1** ✅   |   +2264.51% |    **Best** |        4 |   733,888 |     733 |       0.6057152 |   0.000605715 |           52s |             16s |\n| **Highload Wallet V3** |    **Best** |      +5.38% |        4 |    31,689 |      31 |       0.6383220 |   0.000638322 |           13s |              4s |\n\n**Preprocessed Wallet V2**\n\n|     Wallet Version     | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :--------------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n| Preprocessed Wallet V2 |     -80.64% |     -48.01% |        4 |     6,148 |       6 |       0.3149072 |   0.000314907 |           52s |             16s |\n\n### Sending Jettons\n\n#### 1 Messages\n\n|   Wallet Version   | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :----------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n| **Wallet V2R1** ✅ |    **Best** |    **Best** |        1 |     2,769 |   2,769 |       0.0021012 |     0.0021012 |           13s |              4s |\n|     Wallet V2R2    |      +2.78% |      +1.46% |        1 |     2,846 |   2,846 |       0.0021320 |     0.0021320 |           13s |              4s |\n|     Wallet V3R1    |      +5.34% |      +2.81% |        1 |     2,917 |   2,917 |       0.0021604 |     0.0021604 |           13s |              4s |\n|     Wallet V3R2    |      +8.12% |      +4.28% |        1 |     2,994 |   2,994 |       0.0021912 |     0.0021912 |           13s |              4s |\n|     Wallet V4R2    |     +19.46% |     +10.26% |        1 |     3,308 |   3,308 |       0.0023168 |     0.0023168 |           13s |              4s |\n|     Wallet V5R1    |     +78.36% |     +45.87% |        1 |     4,939 |   4,939 |       0.0030652 |     0.0030652 |           13s |              4s |\n| Highload Wallet V3 |    +187.32% |    +170.94% |        1 |     7,956 |   7,956 |       0.0056932 |     0.0056932 |           13s |              4s |\n\n**Preprocessed Wallet V2**\n\n|     Wallet Version     | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :--------------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n| Preprocessed Wallet V2 |     -44.49% |     -15.45% |        1 |     1,537 |   1,537 |       0.0017764 |     0.0017764 |           13s |              4s |\n\n#### 4 Messages\n\n|   Wallet Version   | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :----------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n| **Wallet V2R1** ✅ |    **Best** |    **Best** |        1 |     4,695 |   1,173 |       0.0046524 |     0.0011631 |           13s |              4s |\n|     Wallet V2R2    |      +1.70% |      +0.66% |        1 |     4,772 |   1,193 |       0.0046832 |     0.0011708 |           13s |              4s |\n|     Wallet V3R1    |      +3.15% |      +1.27% |        1 |     4,843 |   1,210 |       0.0047116 |     0.0011779 |           13s |              4s |\n|     Wallet V3R2    |      +4.85% |      +1.93% |        1 |     4,920 |   1,230 |       0.0047424 |     0.0011856 |           13s |              4s |\n|     Wallet V4R2    |     +11.50% |      +4.63% |        1 |     5,234 |   1,308 |       0.0048680 |     0.0012170 |           13s |              4s |\n|     Wallet V5R1    |     +51.06% |     +26.26% |        1 |     7,090 |   1,772 |       0.0058744 |     0.0014686 |           13s |              4s |\n| Highload Wallet V3 |     +69.56% |    +106.14% |        1 |     7,956 |   1,989 |       0.0095908 |     0.0023977 |           13s |              4s |\n\n**Preprocessed Wallet V2**\n\n|     Wallet Version     | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :--------------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n| Preprocessed Wallet V2 |     -67.26% |     -19.92% |        1 |     1,537 |     384 |       0.0037252 |     0.0009313 |           13s |              4s |\n\n#### 200 Messages\n\n|     Wallet Version     | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :--------------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n|       Wallet V2R1      |   +2907.69% |     +22.81% |       50 |   234,750 |   1,173 |       0.2326200 |   0.001163100 |       10m 50s |          3m 20s |\n|       Wallet V2R2      |   +2958.97% |     +23.62% |       50 |   238,600 |   1,193 |       0.2341600 |   0.001170800 |       10m 50s |          3m 20s |\n|       Wallet V3R1      |   +3002.56% |     +24.37% |       50 |   242,150 |   1,210 |       0.2355800 |   0.001177900 |       10m 50s |          3m 20s |\n|       Wallet V3R2      |   +3053.84% |     +25.18% |       50 |   246,000 |   1,230 |       0.2371200 |   0.001185600 |       10m 50s |          3m 20s |\n|       Wallet V4R2      |   +3253.84% |     +28.50% |       50 |   261,700 |   1,308 |       0.2434000 |   0.001217000 |       10m 50s |          3m 20s |\n|   **Wallet V5R1** ✅   |   +1792.30% |    **Best** |        1 |   147,622 |     738 |       0.1894088 |   0.000947044 |           13s |              4s |\n| **Highload Wallet V3** |    **Best** |     +39.50% |        1 |     7,956 |      39 |       0.2642340 |   0.001321170 |           13s |              4s |\n\n**Preprocessed Wallet V2**\n\n|     Wallet Version     | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :--------------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n| Preprocessed Wallet V2 |     -82.05% |     -30.81% |        1 |     1,537 |       7 |       0.1310468 |   0.000655234 |           13s |              4s |\n\n#### 1000 Messages\n\n|     Wallet Version     | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :--------------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n|       Wallet V2R1      |   +3683.87% |     +23.09% |      250 | 1,173,750 |   1,173 |       1.1631000 |   0.001163100 |       54m 10s |         16m 40s |\n|       Wallet V2R2      |   +3748.38% |     +23.90% |      250 | 1,193,000 |   1,193 |       1.1708000 |   0.001170800 |       54m 10s |         16m 40s |\n|       Wallet V3R1      |   +3803.22% |     +24.65% |      250 | 1,210,750 |   1,210 |       1.1779000 |   0.001177900 |       54m 10s |         16m 40s |\n|       Wallet V3R2      |   +3867.74% |     +25.47% |      250 | 1,230,000 |   1,230 |       1.1856000 |   0.001185600 |       54m 10s |         16m 40s |\n|       Wallet V4R2      |   +4119.35% |     +28.79% |      250 | 1,308,500 |   1,308 |       1.2170000 |   0.001217000 |       54m 10s |         16m 40s |\n|   **Wallet V5R1** ✅   |   +2264.51% |    **Best** |        4 |   733,888 |     733 |       0.9449152 |   0.000944915 |           52s |             16s |\n| **Highload Wallet V3** |    **Best** |     +39.34% |        4 |    31,689 |      31 |       1.3167220 |   0.001316722 |           13s |              4s |\n\n**Preprocessed Wallet V2**\n\n|     Wallet Version     | Gas delta % | Fee delta % | Requests | Total Gas | Gas/Msg | Total Fee (TON) | Fee/Msg (TON) | Real Time (s) | Theory Time (s) |\n| :--------------------: | ----------: | ----------: | -------: | --------: | ------: | --------------: | ------------: | ------------: | --------------: |\n| Preprocessed Wallet V2 |     -80.64% |     -30.77% |        4 |     6,148 |       6 |       0.6541072 |   0.000654107 |           52s |             16s |\n"
  },
  {
    "path": "standard/wallets/preprocessed-v2/interact.mdx",
    "content": "---\ntitle: \"How to interact with Preprocessed Wallet V2\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside\n  type=\"caution\"\n  title=\"Community implementation\"\n>\n  This wallet is a community-created implementation. Use at your own risk. Always test thoroughly on testnet before using with real funds.\n</Aside>\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  This guide sends real TON. Test on testnet first. Double-check recipient addresses — blockchain transactions cannot be reversed.\n</Aside>\n\nThis guide shows how to deploy Preprocessed Wallet V2 and send transfers.\n\n<Aside type=\"tip\">\n  For technical details, see [Preprocessed Wallet V2 specification](/standard/wallets/preprocessed-v2/specification).\n</Aside>\n\n## Objective\n\nBy the end of this guide, you will:\n\n- Create a Preprocessed Wallet V2 instance from scratch\n- Deploy the wallet on-chain\n- Send single and batch transfers\n\n## Prerequisites\n\n- Node.js 18+ or TypeScript environment\n- `@ton/ton`, `@ton/core`, `@ton/crypto` packages installed\n- Preprocessed Wallet V2 wrapper and compiled contract code\n\nThis guide uses TypeScript with the official wrapper. The same logic applies to other SDKs (Go/Python): generate or load a mnemonic, derive a keypair, and calculate the address.\n\n## Step 1: Set up dependencies\n\nInstall required packages:\n\n```bash\nnpm install @ton/ton @ton/core @ton/crypto\n```\n\nCopy the wrapper and contract code from the [official repository](https://github.com/pyAndr3w/ton-preprocessed-wallet-v2):\n\n```bash\n# Clone the repository or download this file:\n# - typescript/wrappers/PreprocessedWalletV2.ts\n```\n\n<Aside\n  type=\"note\"\n  title=\"Why copy wrappers?\"\n>\n  The official `@ton/ton` SDK does not include Preprocessed Wallet V2 wrappers yet. Copy `PreprocessedWalletV2.ts` from the repository until SDK support is added.\n</Aside>\n\n## Step 2: Generate or load a mnemonic\n\nA mnemonic is your wallet's master secret. It derives the private key used to sign all transactions.\n\n### Generate a new mnemonic\n\n```typescript\nimport { mnemonicNew } from '@ton/crypto';\n\nconst mnemonic = await mnemonicNew(24); // Array of 24 words\n```\n\n### Load an existing mnemonic\n\n```typescript\nconst mnemonic = 'word1 word2 word3 ... word24'.split(' ');\n```\n\n<Aside\n  type=\"danger\"\n  title=\"Protect your mnemonic\"\n>\n  Anyone with access to your mnemonic can control your wallet and all funds. Store it securely (password manager, hardware wallet, encrypted storage). Never commit it to version control.\n</Aside>\n\n## Step 3: Derive the keypair\n\nConvert the mnemonic to an Ed25519 keypair:\n\n```typescript\nimport { mnemonicToPrivateKey } from '@ton/crypto';\n\nconst keyPair = await mnemonicToPrivateKey(mnemonic);\n// keyPair.publicKey  — used in contract state\n// keyPair.secretKey  — used to sign external messages\n```\n\n## Step 4: Create the wallet instance\n\nCreate a Preprocessed Wallet V2 contract instance:\n\n```typescript\nimport { TonClient } from '@ton/ton';\nimport { Cell } from '@ton/core';\nimport { Wallet, walletCode } from './wrappers/PreprocessedWalletV2';\n\n// Compiled contract code (BoC)\nconst CODE = walletCode; // Already included in the wrapper\n\nconst client = new TonClient({\n    endpoint: 'https://testnet.toncenter.com/api/v2/jsonRPC', // This is TESTNET endpoint\n    // apiKey: 'your-api-key' // Optional: get from @tonapibot or @tontestnetapibot\n});\n\nconst wallet = client.open(\n    Wallet.createFromPublicKey(keyPair.publicKey)\n);\n```\n\n## Step 5: Get the wallet address\n\nCalculate the wallet's address:\n\n```typescript\n// Get non-bounceable address for funding\nconst address = wallet.address.toString({ bounceable: false, testOnly: true });\nconsole.log('Wallet address:', address);\n// Example (truncated): 0Q... (non-bounceable, testnet)\n```\n\nThis address is deterministic: it depends only on `CODE` and `publicKey`. The same parameters always produce the same address.\n\n<Aside\n  type=\"tip\"\n  title=\"Why non-bounceable?\"\n>\n  When funding a `nonexist` account, use the non-bounceable format to prevent funds from bouncing back if the account doesn't exist yet. See [Address formats](/foundations/addresses/formats) for details.\n</Aside>\n\n**Account status: [`nonexist`](/foundations/status#status-variety)**\n\nThe calculated address exists only as a deterministic value. No account exists on the blockchain yet — no balance, no code, no data.\n\n---\n\n## Step 6: Fund the wallet\n\n<Aside\n  type=\"danger\"\n  title=\"Funds at risk\"\n>\n  You will send TON to this address. Test on testnet first. Verify the wallet address carefully — blockchain transactions cannot be reversed.\n</Aside>\n\n**Required before deployment:** Send TON to your wallet address (from Step 5) to prepare it for deployment.\n\nExternal messages (which deploy the wallet) require gas to execute. By funding the address, you transition the account from `nonexist` to `uninit` status and provide the balance needed for deployment. See [Account statuses](/foundations/status) for details on how account states work.\n\nSend TON using a faucet (testnet) or from another wallet (mainnet). After funding, the account transitions to `uninit` status — it has a balance and can accept external messages, but no code or data yet.\n\n---\n\n## Step 7: Send messages\n\n<Aside\n  type=\"note\"\n  title=\"Automatic deployment\"\n>\n  The wallet will auto-deploy on the first external message. No separate deployment step is needed.\n</Aside>\n\n### Send single transfers\n\n```typescript\nimport { Address, toNano } from '@ton/ton';\nimport { beginCell } from '@ton/core';\n\n// Get current sequence number\nconst currentSeqno = Number(await wallet.getSeqno());\n\n// Send a single transfer\nawait wallet.sendTransfers(keyPair, [{\n    to: Address.parse('EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c'), // Zero address for testing\n    value: toNano('0.01'),\n    bounce: false\n}], currentSeqno);\n\nconsole.log('Transfer sent');\n```\n\n### Send batch transfers\n\n```typescript\nimport { Address, toNano, comment } from '@ton/ton';\n\n// Get current sequence number\nconst currentSeqno = Number(await wallet.getSeqno());\n\n// Create multiple transfers with similar structure\nconst transfers = [];\nfor (let i = 0; i < 5; i++) {\n    transfers.push({\n        to: Address.parse('EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c'),\n        value: toNano('0.01'),\n        body: comment(`#${i}`)\n    });\n}\n\n// Send batch transfers\nawait wallet.sendTransfers(keyPair, transfers, currentSeqno);\n\nconsole.log('Batch transfers sent');\n```\n\n<Aside\n  type=\"note\"\n  title=\"Maximum actions\"\n>\n  reprocessed Wallet V2 supports up to 255 actions per transaction. This is the maximum number of out actions supported by TON blockchain.\n</Aside>\n"
  },
  {
    "path": "standard/wallets/preprocessed-v2/specification.mdx",
    "content": "---\ntitle: \"Preprocessed Wallet V2 — specification\"\nsidebarTitle: \"Specification\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n<Aside\n  type=\"caution\"\n  title=\"Community implementation\"\n>\n  This wallet is a community-created implementation. Use at your own risk. Always test thoroughly on testnet before using with real funds.\n</Aside>\n\nThis page provides a complete technical specification for Preprocessed Wallet V2, covering storage structure, message formats, replay protection, limitations, and implementation details.\n\n## Objective\n\nUnderstand the internal architecture, data structures, and operational mechanics of Preprocessed Wallet V2. This reference page explains how the wallet processes batch transactions efficiently with minimal gas consumption.\n\n<Aside type=\"tip\">\n  For practical usage, see [How-to guides](/standard/wallets/preprocessed-v2/interact).\n</Aside>\n\n## What is Preprocessed Wallet V2?\n\nPreprocessed Wallet V2 is a wallet smart contract designed for efficiency with minimal code complexity. It provides low transaction costs while maintaining the ability to send up to 255 actions in a single transaction.\n\n**Key difference from standard wallets:**\\\nPreprocessed V2 enables batch transaction processing with up to 255 actions per message, making it suitable for services that need to send multiple payments efficiently.\n\n**Optimization focus:**\\\nPreprocessed V2 prioritizes gas efficiency and simplicity, making it suitable for applications that need batch processing with minimal overhead.\n\n**Gas consumption:**\\\nThe wallet consumes 1537 gas units per transaction.\n\n## TL-B schema\n\n[TL-B (Type Language - Binary)](/languages/tl-b/overview) is a domain-specific language designed to describe data structures in TON. The schemas below define the binary layout of the contract's storage and external messages.\n\n### Storage structure\n\n```tlb\nstorage$_ pub_key:bits256 seq_no:uint16 = Storage;\n```\n\n### External message structure\n\n```tlb\n_ {n:#} valid_until:uint64 seq_no:uint16 actions:^(OutList n) { n <= 255 } = MsgInner n;\n\nmsg_body$_ {n:#} sign:bits512 ^(MsgInner n) = ExtInMsgBody n;\n```\n\n<Aside type=\"note\">\n  The canonical TL-B schemas are maintained in the [ton-preprocessed-wallet-v2 repository](https://github.com/pyAndr3w/ton-preprocessed-wallet-v2).\n</Aside>\n\nBelow, each field is explained in detail.\n\n## Storage structure\n\nThe Preprocessed Wallet V2 contract stores two persistent fields:\n\n### `pub_key` (256 bits)\n\n**Purpose:**\\\nAn Ed25519 public key is used to verify signatures on incoming external messages.\n\n**How it works:**\\\nWhen the wallet receives an external message, it verifies that the 512-bit signature was created by the holder of the private key corresponding to this public key.\n\n<Aside\n  type=\"caution\"\n>\n  The public key is not the wallet address. The address is [derived](/foundations/addresses/derive) from the contract's [`StateInit`](/foundations/messages/deploy).\n</Aside>\n\n### `seq_no` (16 bits)\n\n**Purpose:**\\\nPrevents replay attacks by ensuring each message has a unique sequence number.\n\n**How it works:**\\\nEach external message must contain the correct `seq_no` that matches the current value stored in the contract. After successful processing, the sequence number is incremented (with modulo 2^16 to prevent overflow).\n\n**Range:** 0 to 65535 (wraps from 65535 to 0)\n\n**Size optimization:**\\\nThe sequence number is limited to 16 bits (instead of 32 bits used in other wallets) to minimize storage size and message size, reducing gas costs.\n\n**Protection mechanism:**\\\nEven if an attacker intercepts an old message, they cannot replay it because the sequence number will no longer match the current value in storage.\n\n**Wrap‑around note:**\\\nSee [Replay protection mechanism](#replay-protection-mechanism) for guidance on wrap‑around and `valid_until` windows.\n\n## External message structure\n\nExternal messages sent to Preprocessed Wallet V2 have a specific layout.\n\n### Message layout\n\n```text\nsign:bits512\n^[ valid_until:uint64\n   seq_no:uint16\n   actions:^(OutList n) ]\n```\n\n**Key point:**\\\nThe signature is in the root cell (512 bits); all other parameters are in a reference cell (`MsgInner`).\n\n<Aside\n  type=\"tip\"\n  title=\"Gas optimization\"\n>\n  This structure saves gas units during signature verification. If the signature were in the same cell as the message body, the contract would need to use `slice_hash()` (which rebuilds the cell internally, costing extra gas) instead of simply taking `cell_hash()` of the reference.\n</Aside>\n\n---\n\n### `sign` (512 bits)\n\n**Type:**\\\nEd25519 signature (512 bits).\n\n**What is signed:**\\\nThe hash of the reference cell (`MsgInner`) containing `valid_until`, `seq_no`, and `actions`.\n\n**Validation:**\\\nThe contract verifies the signature using:\n\n```func\ncheck_signature(hash(ref_cell), signature, public_key)\n```\n\n**On failure:**\\\nExit code `35`.\n\n**Link:** [Ed25519 signature scheme](https://en.wikipedia.org/wiki/EdDSA#Ed25519)\n\n---\n\n### `valid_until` (64 bits)\n\n**Purpose:**\\\nUnix timestamp (seconds) when the external message expires.\n\n**Validation:**\\\nThe contract performs a single check:\n\n```func\nnow() > valid_until  // Message expired\n```\n\n**On failure:**\\\nExit code `34`.\n\n**Why it matters:**\\\nPrevents replay of expired messages. If `now() > valid_until`, the message is considered expired and rejected.\n\n**Recommendation:**\\\nSet `valid_until` to 1 minute (60 seconds) from message creation time.\n\n---\n\n### `seq_no` (16 bits)\n\n**Purpose:**\\\nExpected sequence number for this message.\n\n**Validation:**\\\nMust match the current `seq_no` stored in contract storage.\n\n**On mismatch:**\\\nExit code `33`.\n\n### `actions` (reference cell)\n\n**Structure:**\\\nA serialized `OutList` containing up to 255 actions to execute.\n\n**Validation:**\\\nNo validation.\n\n**Supported actions:**\nAll standard TVM actions are supported without restrictions:\n\n- `action_send_msg` — Send messages\n- `action_set_code` — Update contract code\n- `action_reserve_currency` — Reserve currency\n- `action_change_library` — Change library\n\n<Aside\n  type=\"danger\"\n  title=\"Critical security warning\"\n>\n  Preprocessed Wallet V2 does not protect against `action_set_code` actions. If you accidentally include a `set_code` action in your message, the wallet contract code will be changed, potentially making your funds inaccessible. Always verify your action lists before sending.\n</Aside>\n\n**Maximum actions:** 255 (maximum number of out actions in TON)\n\n## Replay protection mechanism\n\nPreprocessed Wallet V2 uses sequence numbers and time-based expiration to prevent replay attacks.\n\n### Sequence number protection\n\n**How it works:**\n\n1. Each message must contain the correct `seq_no`\n1. After successful processing, `seq_no` is incremented\n1. Old messages with incorrect sequence numbers are rejected\n\n**Overflow protection:**\n\n- Uses modulo 2^16 operation: `(seq_no + 1) % 65536`\n- Wraps from 65535 to 0\n\n### Time-based expiration\n\n**How it works:**\n\n1. Each message includes `valid_until` timestamp\n1. Messages are rejected if `now() > valid_until`\n1. Prevents replay of expired messages\n\n**Recommended expiration:**\n\n- 1 minute (60 seconds) for most use cases\n- Shorter for high-frequency operations\n- Longer for batch operations with network delays\n\n### Wrap‑around and validity window\n\nWhen `seq_no` wraps (65535 → 0), previously sent messages that used the same numeric `seq_no` remain non‑applicable if their `valid_until` has already expired. Safety relies on the dual check: current `seq_no` equality and unexpired `valid_until`.\n\nDo not set `valid_until` excessively far in the future. A very long validity window increases the chance that, after wrap‑around, an old message with the same `seq_no` is still valid. Keep the window short (for example, ≤ 60 seconds) unless you have a specific operational reason.\n\n### Signature verification\n\n**How it works:**\n\n1. All messages must be signed with the wallet's private key\n1. Signature covers the entire message content (hash of `MsgInner`)\n1. Prevents unauthorized message creation\n\n## Exit codes\n\n| Exit code | Name                      | Description                                        | How to fix                                                                      |\n| --------- | ------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------- |\n| `0`       | Success                   | Message processed successfully                     | —                                                                               |\n| `33`      | Incorrect sequence number | The `seq_no` in the message does not match storage | Use the correct `seq_no` from contract storage                                  |\n| `34`      | Message expired           | The `valid_until` timestamp has passed             | Ensure `valid_until >= now()` when creating the message                         |\n| `35`      | Invalid signature         | Ed25519 signature verification failed              | Check that the private key is correct and the message hash is computed properly |\n\n## Limitations and constraints\n\n### Maximum actions per transaction\n\n**Limitation:**\\\nEach external message can trigger up to 255 actions.\n\n**Why this limitation?**\\\n255 is the maximum number of out actions supported by TON blockchain. This is a fundamental limitation of the TVM execution environment.\n\n**Impact:**\\\nSuitable for batch operations with up to 255 actions per transaction.\n\n<Aside\n  type=\"note\"\n  title=\"Sequential processing\"\n>\n  Preprocessed Wallet V2 uses sequential `seq_no` processing. This means you must wait for each transaction to complete before sending the next one.\n</Aside>\n\n## Implementation\n\n### Source code\n\n- Repository: - [pyAndr3w/ton-preprocessed-wallet-v2](https://github.com/pyAndr3w/ton-preprocessed-wallet-v2)\n\n## See also\n\n- [How to interact with Preprocessed Wallet V2](/standard/wallets/preprocessed-v2/interact)\n"
  },
  {
    "path": "standard/wallets/restricted.mdx",
    "content": "---\ntitle: \"Restricted wallet\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\nimport { Image } from '/snippets/image.jsx';\n\n<Aside\n  type=\"danger\"\n  title=\"Security warning\"\n>\n  Restricted Wallet is unmaintained and has unresolved security issues.\n</Aside>\n\nRestricted Wallet is a specialized wallet contract that restricts transfers to predefined owner address, and some operations with Elector and Config contracts. It is used in [Single Nominator](https://github.com/orbs-network/single-nominator) project to securely hold a validator stake and participate in elections without a risk of stealing funds from it.\n\n## What makes it different\n\nUnlike standard wallets that allow transfers to any address, Restricted Wallet implements address-based restrictions that limit where funds can be sent.\n\n**Standard wallet behavior:**\\\nYou can send funds to any valid address.\n\n**Restricted Wallet behavior:**\\\nYou can only send funds to the predefined owner address or do operations with [Elector](/foundations/system#elector) (new stake, recover stake request, new complaint, and vote for a complaint) and [Config](/foundations/system#config) (vote for specific proposal to change config) contracts.\n\n## How it works\n\n<Image\n  src=\"/resources/images/wallets/restricted.png\"\n  darkSrc=\"/resources/images/wallets/restricted.png\"\n  alt=\"Single Nominator Architecture\"\n/>\n\n### Allowed actions\n\n1. Send a message to the owner of this wallet.\n1. Send \"vote for a configuration proposal\" message to the [Config contract](/foundations/system#config).\n1. Send \"new stake\", \"recover stake request\", \"new complaint\", or \"vote for a complaint\" messages to the [Elector contract](/foundations/system#elector).\n\nIt is allowed to use [message modes](/languages/func/stdlib#send-raw-message) 128, 64, 2, and 1. Mode 2 (ignore errors) is always enabled when sending messages from this wallet.\n\n## Implementation\n\n### Source code\n\n- Repository: [EmelyanenkoK/nomination-contract/restricted-wallet](https://github.com/EmelyanenkoK/nomination-contract/tree/master/restricted-wallet)\n"
  },
  {
    "path": "standard/wallets/v4.mdx",
    "content": "---\ntitle: \"Wallet V4\"\nsidebarTitle: \"V4\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\nimport { Image } from '/snippets/image.jsx';\n\nThis version retains all the functionality of the previous versions and introduces plugins.\n\nPlugins enable developers to implement custom logic that integrates with wallet functionality. When a plugin is installed on a wallet through a signed transaction, it can force wallet to send internal message with predefined opcode (`0xf06c7567`) and any available Toncoin amount to specified addresses. Plugins are separate smart contracts that can implement their own custom logic.\n\nHere you can view [wallet V4 source code](https://github.com/ton-blockchain/wallet-contract).\n\n## Plugins\n\n<Aside\n  type=\"danger\"\n>\n  Installing third-party plugins can be dangerous and may lead to wallet drainage. Only install plugins from trusted sources and ensure you understand their functionality before installation.\n</Aside>\n\n<Aside\n  type=\"caution\"\n>\n  Due to security reasons mentioned above, it is not possible to install plugins using [TonConnect](/ecosystem/ton-connect/overview).\n</Aside>\n\nPlugins are essentially other smart contracts on TON that developers are free to implement as they wish. In relation to the wallet, they are simply addresses of smart contracts stored in a dictionary in the wallet's persistent memory. These plugins are allowed to request funds and remove themselves from the \"allowed list\" by sending internal messages to the wallet.\n\n### Plugin interaction flow\n\n```mermaid\nsequenceDiagram\n    participant Owner\n    participant V4 as V4 Wallet\n    participant Plugin as Plugin Contract\n\n    Owner->>V4: External message: Install plugin X\n    Note over V4: Plugin X added to allowlist\n\n    Plugin->>V4: Internal message: Request funds\n    Note over V4: Verify sender is in allowlist\n    V4->>Plugin: Transfer funds\n\n    Note over Plugin, V4: Plugin can also remove itself\n    Plugin->>V4: Internal message: Remove from allowlist\n    Note over V4: Plugin X removed from allowlist\n```\n\n## Persistent memory layout\n\nHere we will break down wallet V4 storage structure.\n\n```tlb\ncontract_state$_\n  seqno:(## 32)\n  wallet_id:(## 32)\n  public_key:(## 256)\n  plugins:(HashmapE 256 int1) = ContractState;\n```\n\n- `seqno`: 32-bit long sequence number.\n- `wallet_id`: 32-bit long wallet\\_id. This is a number that allows you to create multiple wallets with the same private key but different addresses.\n- `public_key`: 256-bit long public key.\n- `plugins`: dictionary containing plugins (may be empty).\n\n<Aside type=\"tip\">\n  Default value for wallet\\_id is `698983191` in V4, it is a partial hash of TON Mainnet zero state.\n</Aside>\n\n## Receiving internal messages\n\nAll previous versions of wallets had a straightforward implementation for receiving internal messages. They simply accepted incoming funds from any sender, ignoring the internal message body if present, or in other words, they had an empty `recv_internal` method. However, as mentioned earlier, the fourth version of the wallet introduces two additional available operations. Let's take a look at the internal message body layout:\n\n- `opcode` (optional): 32-bit long operation code. This is an optional field. Any message containing less than 32 bits in the message body, an incorrect opcode, or a sender address that isn't registered as a plugin will be considered a simple transfer, similar to previous wallet versions.\n- `query_id`: 64-bit long integer. This field has no effect on the smart contract's behavior; it is used to track chains of messages between contracts.\n\n1. opcode = `0x706c7567`, request funds operation.\n   - `amount`: [Coins](/tvm/instructions#fa02-stgrams) amount of requested Toncoin.\n   - `extra_currencies`: dictionary containing the amount of requested extra currencies (may be empty).\n1. opcode = `0x64737472`, request removal of the plugin that sent this message from the allowed list.\n\nTL-B for plugin operations:\n\n```tlb\nrequest_funds#706c7567\n  amount:Coins\n  extra_currencies:ExtraCurrencyCollection = InternalMsgBody;\n\nself_destroy#64737472 = InternalMsgBody;\n```\n\n## External message body layout\n\n- `signature`: 512-bit long [Ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519) signature.\n- `wallet_id`: 32-bit long subwallet ID.\n- `valid_until`: 32-bit long Unix time integer.\n- `msg_seqno`: 32-bit long sequence number.\n- `opcode`: 32-bit long operation code.\n- other data depending on the opcode\n\nNext, let's explore the types of messages:\n\n### Simple send (opcode = 0x0)\n\nThe simple send operation processes a chain of messages, where each message contains a mode and a reference to the actual message cell:\n\n<Image\n  src=\"/resources/images/wallets/simple_opcode_light.svg\"\n  darkSrc=\"/resources/images/wallets/simple_opcode_dark.svg\"\n  alt=\"Simple send operation message chain\"\n/>\n\n**Processing logic:**\n\n```func\nif (op == 0) { ;; simple send\n  while (cs.slice_refs()) {\n    var mode = cs~load_uint(8);\n    send_raw_message(cs~load_ref(), mode);\n  }\n}\n```\n\n- `mode`: up to four 8-bit integers defining the sending mode for each message.\n- `out_msg`: up to four references to cells containing messages.\n\n### Deploy and install plugin (opcode = 0x1)\n\n```tlb\ndeploy_and_install_plugin#01\n  workchain:(## 8)\n  balance:Coins\n  state_init:^Cell\n  body:^Cell\n= WalletAction;\n```\n\nDeploys a new plugin contract and adds it to the wallet's plugin allowlist:\n\n- `workchain`: 8-bit workchain ID where the plugin will be deployed\n- `balance`: Initial Toncoin balance for the plugin contract\n- `state_init`: Cell reference containing the plugin's initial state and code\n- `body`: Cell reference containing the deployment message body\n\n### Install plugin (opcode = 0x2)\n\n```tlb\nwc_n_address#_ wc:(## 8) hash:(## 256) = WorkchainWithAddress;\n\ninstall_plugin#02\n  wc_n_address:WorkchainWithAddress\n  balance:Coins\n  query_id:(## 64)\n= WalletAction;\n```\n\nAdds an existing plugin contract to the wallet's allowlist:\n\n- `wc_n_address`: Combined 8-bit workchain ID and 256-bit plugin address\n- `balance`: Toncoin amount to send during installation\n- `query_id`: 64-bit identifier for tracking the operation\n\n### Remove plugin (opcode = 0x3)\n\n```tlb\nwc_n_address#_ wc:(## 8) hash:(## 256) = WorkchainWithAddress;\n\nremove_plugin#03\n  wc_n_address:WorkchainWithAddress\n  balance:Coins\n  query_id:(## 64)\n= WalletAction;\n```\n\nRemoves a plugin from the wallet's allowlist:\n\n- `wc_n_address`: Combined 8-bit workchain ID and 256-bit plugin address\n- `balance`: Toncoin amount\n- `query_id`: 64-bit identifier for tracking the operation\n\nWallet V4 provides standard functionality through the `0x0` opcode, similar to previous versions (see [wallet overview](/standard/wallets/history) for details on message layout). The `0x2` and `0x3` operations allow manipulation of the plugin dictionary.\n\n## Exit codes\n\n| Exit code | Description                                                             |\n| --------- | ----------------------------------------------------------------------- |\n| 33        | `seqno` check failed, replay protection triggered                       |\n| 34        | `wallet_id` does not match the stored one                               |\n| 35        | `signature` check failed                                                |\n| 36        | `valid_until` check failed, transaction attempted too late              |\n| 39        | Plugins dictionary manipulation failed (0x1-0x3 recv\\_external opcodes) |\n| 80        | Not enough funds for the plugin funds request                           |\n| 0         | Standard successful execution exit code.                                |\n\n## Get methods\n\n1. `int seqno()` returns current stored seqno.\n1. `int get_public_key()` returns current stored public key.\n1. `int get_subwallet_id()` returns current subwallet ID.\n1. `int is_plugin_installed(int wc, int addr_hash)` checks if plugin with defined workchain\\_id and address hash is installed. Returns `-1` (true) if the plugin is installed, `0` (false) if not installed.\n1. `tuple get_plugin_list()` returns list of plugins.\n"
  },
  {
    "path": "standard/wallets/v5-api.mdx",
    "content": "---\ntitle: \"Wallet V5 API\"\nsidebarTitle: \"How to interact\"\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\nimport { Image } from '/snippets/image.jsx';\n\nThis article provides overview of wallet V5 public interfaces, how to interact with them and serialize used data structures.\n\n<Aside>\n  Note, that many of the things we implement in this article are for education purposes and they might need to be refined before production use.\n\n  Moreover, all these V5 wallet contract interfaces are implemented in [`@ton/ton`](https://github.com/ton-org/ton) client library as WalletV5 contract wrapper class.\n</Aside>\n\nThere are several ways how you can interact with deployed V5 wallet smart contract:\n\n- Send external signed message\n- Send internal signed message\n- Send internal message from extension\n\nLet's first explore message structure, that is used to perform different actions on wallet contract.\n\n## TL-B\n\nThis is TL-B for V5 wallet actions, it includes some [complex TL-B patterns](/languages/tl-b/complex-and-non-trivial-examples.mdx). You can also find it on [GitHub](https://github.com/ton-blockchain/wallet-contract-v5/blob/321186127e8cc5e395ad3b2f1870839237c56f5f/types.tlb), in the wallet repo.\n\n```tlb expandable\n// Contract state\ncontract_state$_\n  is_signature_allowed: (## 1)\n  seqno:                #\n  wallet_id:            #\n  public_key:           (## 256)\n  extensions_dict:      (HashmapE 256 int1)\n= ContractState;\n\n// Extended actions in W5:\nadd_extension#02 addr:MsgAddressInt = W5ExtendedAction;\ndelete_extension#03 addr:MsgAddressInt = W5ExtendedAction;\nset_signature_auth_allowed#04 allowed:Bool = W5ExtendedAction;\n\n// note: `m = extended actions count - 1`, so the last ref is not empty cell\nextended_list_last$_ action:W5ExtendedAction = W5ExtendedActionList 0;\nextended_list_action$_ {n:#} action:W5ExtendedAction prev:^(W5ExtendedActionList n) = W5ExtendedActionList (n + 1);\n\n// `OutList m` is standard actions from block.tlb:\nw5_actions_request$_ {m:#} {n:#} out_actions:(Maybe ^(OutList m)) extended_actions:(Maybe (W5ExtendedActionList n)) = W5InnerRequest m n;\n\nw5_signed_request$_ {m:#} {n:#}\n  wallet_id:    #\n  valid_until:  #\n  msg_seqno:    #\n  inner:        (W5InnerRequest m n)\n  signature:    bits512\n= W5SignedRequest m n;\n\n// actions_count = m, extended_actions_count - 1 = n\nw5_internal_signed_request#73696e74 {m:#} {n:#} request:(W5SignedRequest m n) = W5MsgBody m n;\nw5_external_signed_request#7369676e {m:#} {n:#} request:(W5SignedRequest m n) = W5MsgBody m n;\n\nw5_extension_action_request#6578746e {m:#} {n:#} query_id:uint64 request:(W5InnerRequest m n) = W5MsgBody m n;\n\n// opcode detection, actual InternalMsgBody / ExternalMsgBody is in W5MsgBody\nw5_internal_signed_request#73696e74 rest:Any = InternalMsgBody;\nw5_external_signed_request#7369676e rest:Any = InternalMsgBody;\nw5_extension_action_request#6578746e rest:Any = InternalMsgBody;\n```\n\nThree types of messages that were described above can be seen here:\n\n```tlb\nw5_internal_signed_request#73696e74 {m:#} {n:#} request:(W5SignedRequest m n) = W5MsgBody m n;\nw5_external_signed_request#7369676e {m:#} {n:#} request:(W5SignedRequest m n) = W5MsgBody m n;\nw5_extension_action_request#6578746e {m:#} {n:#} query_id:uint64 request:(W5InnerRequest m n) = W5MsgBody m n;\n```\n\nEach of them includes the same `W5InnerRequest` field that dictates whats need to be done by wallet contract. In case of signed messages, the request needs to be verified, so `W5InnerRequest` is wrapped in `W5SignedRequest` structure, which contains necessary information for this.\n\nLet's break down these data structures.\n\n## Message structure\n\nMessage structure for V5 wallet contract is quite cumbersome and hard to read, it's made for optimal (de-)serialization and not optimized for understanding. It is described in [TL-B](/languages/tl-b/overview) languages and includes snake-cell pattern. We will try to get a grip of it by breaking down core data structures and how they are used.\n\nYou can skip to [Examples section](#examples), where we would use existing high-level libraries that abstract low level logic from the user.\n\n## Inner Request\n\nInner request is defined as follows:\n\n```tlb\nw5_actions_request$_ {m:#} {n:#}\n  out_actions:(Maybe ^(OutList m))\n  extended_actions:(Maybe (W5ExtendedActionList n))\n= W5InnerRequest m n;\n```\n\nV5 wallet supports two main types of actions that can be performed:\n\n```mermaid\ngraph TD\n    A[Root Actions] --> B[Send Message Action]\n    A --> C[Extended Actions]\n    C --> D[Add Extension]\n    C --> E[Delete Extension]\n    C --> F[Set Signature Auth]\n```\n\nThe action structure allows for:\n\n- **Send Message Actions**: Standard message sending with specified mode\n- **Extended Actions**: Advanced wallet management operations\n  - **Add Extension**: Register new extension addresses\n  - **Delete Extension**: Remove extension addresses\n  - **Set Signature Auth**: Enable/disable signature-based authentication\n\nAs you can see in TL-B, `out_actions` are snake-cell list of ordinary out messages, followed then by binary flag `has_other_actions` and `other_actions` extended action list.\n\n#### Inner Request Structure\n\nThe Inner Request serialization follows this structure:\n\n```mermaid\ngraph TD\n    A[Inner Request] --> B[out_actions: Maybe OutList]\n    A --> C[has_other_actions: 1 bit]\n\n    B --> B1{Has out actions?}\n    B1 -->|Yes| B2[OutList Chain]\n    B1 -->|No| B3[Empty/Nothing]\n\n    B2 --> B4[Mode: 8 bits]\n    B2 --> B5[Message Reference]\n    B2 --> B6[Previous OutList Reference]\n\n    C --> C1{Bit = 1?}\n    C1 -->|Yes| D[other_actions: ActionList]\n    C1 -->|No| D1[No extended actions]\n\n    D --> D2[Extended Action]\n    D --> D3[Previous ActionList Reference]\n\n    D2 --> D4[Add Extension #02]\n    D2 --> D5[Delete Extension #03]\n    D2 --> D6[Set Signature Auth #04]\n\n    style A fill:#e1f5fe\n    style B2 fill:#f3e5f5\n    style D fill:#e8f5e8\n```\n\n#### Serialization Layout\n\nThe Inner Request is serialized in the following order:\n\n```mermaid\ngraph LR\n    subgraph \"Cell Data\"\n        A[out_actions flag] --> B[has_other_actions: 1 bit]\n    end\n\n    subgraph \"References\"\n        C[Ref 0: OutList Chain]\n        D[Ref 1: ActionList Chain]\n    end\n\n    A -.-> C\n    B -.-> D\n\n    subgraph \"OutList Structure\"\n        E[Mode: 8 bits] --> F[Message Ref] --> G[Prev OutList Ref]\n    end\n\n    subgraph \"ActionList Structure\"\n        H[Action Type: 8 bits] --> I[Action Data] --> J[Prev ActionList Ref]\n    end\n\n    C --> E\n    D --> H\n```\n\n## Signed Request\n\nSigned message is a message that was signed using owners private key from his dedicated keypair, method from asymmetric cryptography. Later this message will be verified on-chain using public key stored in wallet smart contract - [read more](/standard/wallets/how-it-works#how-ownership-verification-works) about how ownership verification works.\n\nBefore V5 standard, there was only one way to deliver signed message to wallet contract - via external-in message. However, external messages has certain limitations, e.g. you can only send external-out messages from the smart contracts themselves. This means that it wasn't possible to deliver signed message from inside the blockchain, from another smart contract. V5 standard adds this functionality, partially enabling [gasless transaction](/standard/wallets/v5#preparing-for-gasless-transactions).\n\nBesides `W5InnerRequest` field that contains actual actions that will be performed, `W5SignedRequest` structure contains usual wallet message fields that were in-place in previous versions, read more about them [here](/standard/wallets/how-it-works).\n\n## Examples\n\nHere we will take a look at code examples in Typescript using low level serialization library _@ton/core_.\n\n### How to create Inner Request\n\nAs per message structure section above, `Inner Request` consists of 2 kinds of actions, basic _send message_ actions and _extended actions_ that affect contract behavior.\n\nLet's write code that handles packing for extended actions:\n\n```ts expandable\nimport {\n    Address,\n    beginCell,\n    Builder,\n    Cell\n} from '@ton/core';\n\n// declare actions as tagged union\nexport type OutActionAddExtension = {\n    type: 'addExtension';\n    address: Address;\n}\n\nexport type OutActionRemoveExtension = {\n    type: 'removeExtension';\n    address: Address;\n}\n\nexport type OutActionSetIsPublicKeyEnabled = {\n    type: 'setIsPublicKeyEnabled';\n    isEnabled: boolean;\n}\n\nexport type OutActionExtended = OutActionSetIsPublicKeyEnabled | OutActionAddExtension | OutActionRemoveExtension;\n\n// store each action content as described in its TL-B specification:\n// 8 bits for action tag and then useful payload\n\nconst outActionAddExtensionTag = 0x02;\nfunction storeOutActionAddExtension(action: OutActionAddExtension) {\n    return (builder: Builder) => {\n        builder.storeUint(outActionAddExtensionTag, 8).storeAddress(action.address)\n    }\n}\n\nconst outActionRemoveExtensionTag = 0x03;\nfunction storeOutActionRemoveExtension(action: OutActionRemoveExtension) {\n    return (builder: Builder) => {\n        builder.storeUint(outActionRemoveExtensionTag, 8).storeAddress(action.address)\n    }\n}\n\nconst outActionSetIsPublicKeyEnabledTag = 0x04;\nfunction storeOutActionSetIsPublicKeyEnabled(action: OutActionSetIsPublicKeyEnabled) {\n    return (builder: Builder) => {\n        builder.storeUint(outActionSetIsPublicKeyEnabledTag, 8).storeUint(action.isEnabled ? 1 : 0, 1)\n    }\n}\n\n// entry point for storing any extended action\nexport function storeOutActionExtendedV5R1(action: OutActionExtended) {\n    switch (action.type) {\n        case 'setIsPublicKeyEnabled':\n            return storeOutActionSetIsPublicKeyEnabled(action);\n        case 'addExtension':\n            return storeOutActionAddExtension(action);\n        case 'removeExtension':\n            return storeOutActionRemoveExtension(action);\n        default:\n            throw new Error('Unknown action type' + (action as OutActionExtended)?.type);\n    }\n}\n\n// and now the hard part - list snake-cell serialization;\n// we will use this function recursively, to store actions as reference cells one by one\nfunction packExtendedActionsRec(extendedActions: OutActionExtended[]): Cell {\n    const [first, ...rest] = extendedActions;\n\n    let builder = beginCell()\n        .store(storeOutActionExtendedV5R1(first));\n\n    if (rest.length > 0) {\n        // if there are more actions, store them recursively\n        builder = builder.storeRef(packExtendedActionsRec(rest));\n    }\n\n    return builder.endCell();\n}\n```\n\nNow we have to deal with basic action serialization. However, since these are the messages that are described in [`block.tlb`](/languages/tl-b/overview), we can use contract-agnostic code from serialization library to store them.\n\nHere is a code snippet for storing V5 wallet actions as per `Inner Request` TL-B:\n\n```ts expandable\nimport {\n    beginCell,\n    Builder, Cell,\n    loadOutList,\n    OutActionSendMsg, SendMode,\n    Slice,\n    storeOutList\n} from '@ton/core';\n\n// helper functions\nexport function isOutActionExtended(action: OutActionSendMsg | OutActionExtended): action is OutActionExtended {\n    return (\n        action.type === 'setIsPublicKeyEnabled' || action.type === 'addExtension' || action.type === 'removeExtension'\n    );\n}\n\nexport function isOutActionBasic(action: OutActionSendMsg | OutActionExtended): action is OutActionSendMsg {\n    return !isOutActionExtended(action);\n\n}\n\n// main entrypoint for storing any actions list\nexport function storeOutListExtendedV5(actions: (OutActionExtended | OutActionSendMsg)[]) {\n    const extendedActions = actions.filter(isOutActionExtended);\n    const basicActions = actions.filter(isOutActionBasic);\n\n    return (builder: Builder) => {\n        // here we use \"storeOutList\", serialization function from @ton/core\n        const outListPacked = basicActions.length ? beginCell().store(storeOutList(basicActions.slice())) : null;\n        builder.storeMaybeRef(outListPacked);\n\n        if (extendedActions.length === 0) {\n           // has_more_actions flag to false\n            builder.storeUint(0, 1);\n        } else {\n            const [first, ...rest] = extendedActions;\n\n            builder\n            // has_more_actions flag to true\n                .storeUint(1, 1)\n            // here we use our store function from previous code section\n                .store(storeOutActionExtendedV5(first));\n            // if there are more actions - store them one by one\n            if (rest.length > 0) {\n                builder.storeRef(packExtendedActionsRec(rest));\n            }\n        }\n    }\n}\n```\n\nWith this, we can serialize and store list of actions, in next section we will learn how to use them to send signed message.\n\n### How to create and send Signed Request\n\nThere are several additional arguments that we need to create signed message besides the list of actions from previous section:\n\n- `walletId`\n- `seqno`\n- `privateKey`\n- `validUntil`\n\nYou can read more about where to obtain them and what there purpose is in [How it works](/standard/wallets/how-it-works) section.\n\nIn this code snippet we will learn how to create signed serialized message.\n\n```ts expandable\nimport { sign } from \"@ton/crypto\";\n\nexport type WalletV5BasicSendArgs = {\n    seqno: number;\n    validUntil: number;\n    privateKey: Buffer;\n}\n\n// w5_internal_signed_request#73696e74 {m:#} {n:#} request:(W5SignedRequest m n) = W5MsgBody m n;\n// w5_external_signed_request#7369676e {m:#} {n:#} request:(W5SignedRequest m n) = W5MsgBody m n;\nexport type WalletV5SendArgsSinged = WalletV5BasicSendArgs\n    & { authType?: 'external' | 'internal';};\n\n// w5_extension_action_request#6578746e {m:#} {n:#} query_id:uint64 request:(W5InnerRequest m n) = W5MsgBody m n;\nexport type Wallet5VSendArgsExtensionAuth = WalletV5BasicSendArgs & {\n    authType: 'extension';\n    queryId?: bigint;\n}\n\nexport type WalletV5SendArgs =\n    | WalletV5SendArgsSinged\n    | Wallet5VSendArgsExtensionAuth;\n\nconst OpCodes = {\n    authExtension: 0x6578746e,\n    authSignedExternal: 0x7369676e,\n    authSignedInternal: 0x73696e74\n}\n\nexport function createWalletTransferV5R1<T extends WalletV5SendArgs>(\n    args: T extends Wallet5VSendArgsExtensionAuth\n    // action types are from Inner Request section\n        ? T & { actions: (OutActionSendMsg | OutActionExtended)[]}\n        : T & { actions: (OutActionSendMsg | OutActionExtended)[], walletId: (builder: Builder) => void }\n): Cell {\n    // Check number of actions\n    if (args.actions.length > 255) {\n        throw Error(\"Maximum number of OutActions in a single request is 255\");\n    }\n\n    // store each message type according to its TL-B\n\n    if (args.authType === 'extension') {\n        return beginCell()\n            .storeUint(OpCodes.authExtension, 32)\n            .storeUint(args.queryId ?? 0, 64)\n            // use storeOutListExtendedV5\n            .store(storeOutListExtendedV5(args.actions))\n            .endCell();\n    }\n\n    const signingMessage = beginCell()\n        .storeUint(args.authType === 'internal'\n            ? OpCodes.authSignedInternal\n            : OpCodes.authSignedExternal, 32)\n        .store(args.walletId);\n\n\n    // now we store common part for both messages\n    signingMessage.storeUint(args.timeout || Math.floor(Date.now() / 1e3) + 60, 32); // Default timeout: 60 seconds\n\n    signingMessage\n        .storeUint(args.seqno, 32)\n        .store(storeOutListExtendedV5(args.actions));\n\n    // now we need to sign message\n    const signature = sign(signingMessage.endCell().hash(), args.secretKey);\n\n    return beginCell().storeBuilder(signingMessage).storeBuffer(signature).endCell();\n}\n```\n\nNow what is left is sending the message. The way we send created message is dependent on the message type.\n\n#### Sending external\\_signed message\n\nAfter obtaining signed message cell we need to serialize it as external message and send it to the blockchain.\n\n```ts\nimport {\n    Address,\n    beginCell,\n    Cell,\n    external,\n    storeMessage\n} from '@ton/core';\n\n// with authType = 'external'\nconst msgCell = createWalletTransferV5(...);\n\nconst v5WalletAddress = Address.parse(\"EQ....\");\n\nconst serializedExternal = external({\n  to: v5WalletAddress,\n  body: msgCell\n});\n\n// BoC: bag of cells\nconst boc = beginCell()\n  .store(storeMessage(serializedExternal))\n  .endCell()\n  .toBoc();\n```\n\nYou can send this BoC to the network in any convenient way, e.g. with API provider like [TonCenter /message](https://toncenter.com/api/v3/index.html#/api%2Fv2/api_v3_post_v2_message) or with your own [liteserver](/ecosystem/nodes/overview).\n\n#### Sending internal\\_extension and internal\\_signed\n\nThese two types of messages are internal messages, meaning that they need to come from another contract. However strange that may sound, the easiest way to send internal message from another contract is to ask another wallet contract to send internal message to our wallet contract with body that will contain our constructed message.\n\n<Image\n  src=\"/resources/images/wallets/internal_message_light.svg\"\n  darkSrc=\"/resources/images/wallets/internal_message_dark.svg\"\n  alt=\"Internal message flow\"\n/>\n\nFor simplicity, we will use wallet V4 contract with existing client serialization library that will take care of all low level stuff.\n\n```ts expandable\nimport {beginCell, toNano, TonClient, WalletContractV4, internal, fromNano} from \"@ton/ton\"\nimport {getHttpEndpoint} from \"@orbs-network/ton-access\"\nimport {mnemonicToPrivateKey} from \"@ton/crypto\"\n\n// v4 wallet mnemonic\nconst mnemonics = \"dog bacon bread ...\"\n\nconst endpoint = await getHttpEndpoint({network: 'testnet'})\nconst client = new TonClient({\n    endpoint: endpoint,\n})\nconst keyPair = await mnemonicToPrivateKey(mnemonics.split(\" \"))\nconst secretKey = keyPair.secretKey\nconst workchain = 0 // we are working in basechain.\nconst deployerWallet = WalletContractV4.create({\n    workchain: workchain,\n    publicKey: keyPair.publicKey,\n})\n\nconst deployerWalletContract = client.open(deployerWallet)\n\n\n// with authType = 'internal' or 'extension'\nconst internalMsgBody = createWalletTransferV5(...);\n\n// here we use function from previous section to create V5 wallet message cell\n// next, we will send it as internal message using V4 wallet\n\n// address of our V5 wallet contract\nconst v5WalletAddress = Address.parse(\"EQ....\");\n\nconst seqnoForV4Wallet: number = await deployerWalletContract.getSeqno()\n\nawait deployerWalletContract.sendTransfer({\n    seqno,\n    secretKey,\n    messages: [\n        internal({\n            to: v5WalletAddress,\n            value: toNano(\"0.05\"),\n            body: internalMsgBody,\n        }),\n    ],\n})\n```\n"
  },
  {
    "path": "standard/wallets/v5.mdx",
    "content": "---\ntitle: \"Wallet V5\"\nsidebarTitle: \"Overview\"\n---\n\nimport { Image } from '/snippets/image.jsx';\n\nThe V5 wallet standard offers many benefits that improve the experience for both users and developers. V5 supports gasless transactions, account delegation and recovery, subscription payments using Jettons and Toncoin, and low-cost multi-transfers. In addition to retaining the previous functionality (V4), the new contract allows you to send up to 255 messages at a time.\n\nThis article provides only a high-level wallet V5 contract overview. If you want to learn more about how to use its interfaces or develop extensions, check out the [wallet V5 API](/standard/wallets/v5-api) article.\n\nSource links:\n\n- [Wallet V5 source code](https://github.com/ton-blockchain/wallet-contract-v5).\n- [TL-B scheme for V5](https://github.com/ton-blockchain/wallet-contract-v5/blob/321186127e8cc5e395ad3b2f1870839237c56f5f/types.tlb)\n\n## Persistent memory layout\n\n```tlb\ncontract_state$_\n  is_signature_allowed:(## 1)\n  seqno:(## 32)\n  wallet_id:(## 32)\n  public_key:(## 256)\n  extensions_dict:(HashmapE 256 int1) = ContractState;\n```\n\n- `is_signature_allowed`: 1-bit flag that restricts or allows access through the signature and stored public key.\n- `seqno`: 32-bit sequence number.\n- `wallet_id`: 32-bit wallet ID (equivalent to subwallet\\_id in previous versions).\n- `public_key`: 256-bit public key.\n- `extensions_dict`: dictionary containing extensions (may be empty).\n\nAs you can see, the `ContractState`, compared to previous versions, hasn't changed much. The main difference is the new `is_signature_allowed` 1-bit flag, which restricts or allows access through the signature and stored public key. We will describe the importance of this change in later topics.\n\n## Message layout\n\n### External message body layout\n\n- `wallet_id`: 32-bit long wallet ID.\n- `valid_until`: 32-bit long Unix time integer.\n- `msg_seqno`: 32-bit long sequence number.\n- `inner`: InnerRequest containing the actual actions to perform.\n- `signature`: 512-bit long [Ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519) signature.\n\n### Internal message body layout\n\nLearn more about internal message serialization [here](/standard/wallets/v5-api).\n\n## Authentication process\n\n```tlb\ninternal_signed#73696e74\n  signed:SignedRequest = InternalMsgBody;\n\ninternal_extension#6578746e\n  query_id:(## 64)\n  inner:InnerRequest = InternalMsgBody;\n```\n\nBefore we get to the actual payload of our messages — `InnerRequest` — let's first look at how version 5 differs from previous versions in the authentication process. The `InternalMsgBody` combinator describes two ways to access wallet actions through internal messages. The first method is one we are already familiar with from version 4: authentication as a previously registered extension, the address of which is stored in `extensions_dict`. The second method is authentication through the stored public key and signature, similar to external requests.\n\nAt first, this might seem like an unnecessary feature, but it actually enables requests to be processed through external services (smart contracts) that are not part of your wallet's extension infrastructure — a key feature of V5. Gasless transactions rely on this functionality.\n\nAny received internal message that doesn't pass the authentication process will be considered a transfer.\n\n## Actions\n\nThe first thing that we should notice is `InnerRequest`, which we have already seen in the authentication process. In contrast to the previous version, both external and internal messages have access to the same functionality, except for changing the signature mode (i.e., the `is_signature_allowed` flag).\n\nWe can consider `InnerRequest` as two lists of actions: the first, `OutList`, is an optional chain of cell references, each containing a send message request led by the message mode. The second, `ActionList`, is led by a one-bit flag, `has_other_actions`, which marks the presence of extended actions, starting from the first cell and continuing as a chain of cell references. We are already familiar with the first two extended actions, `action_add_ext` and `action_delete_ext`, followed by the internal address that we want to add or delete from the extensions dictionary. The third, `action_set_signature_auth_allowed`, restricts or allows authentication through the public key, leaving the only way to interact with the wallet through extensions. This functionality might be extremely important in the case of a lost or compromised private key.\n\nLearn more about actions [here](/standard/wallets/v5-api).\n\n## Exit codes\n\n| Exit code | Description                                                                        |\n| --------- | ---------------------------------------------------------------------------------- |\n| 132       | Authentication attempt through signature while it's disabled                       |\n| 133       | `seqno` check failed, replay protection occurred                                   |\n| 134       | `wallet_id` does not correspond to the stored one                                  |\n| 135       | `signature` check failed                                                           |\n| 136       | `valid_until` check failed                                                         |\n| 137       | Enforce that `send_mode` has the +2 bit (ignore errors) set for external messages. |\n| 138       | `external_signed` prefix doesn't correspond to the received one                    |\n| 139       | Add extension operation was not successful                                         |\n| 140       | Remove extension operation was not successful                                      |\n| 141       | Unsupported extended message prefix                                                |\n| 142       | Tried to disable auth by signature while the extension dictionary is empty         |\n| 143       | Attempt to set signature to an already set state                                   |\n| 144       | Tried to remove the last extension when signature is disabled                      |\n| 145       | Extension has the wrong workchain                                                  |\n| 146       | Tried to change signature mode through external message                            |\n| 147       | Invalid `c5`, `action_send_msg` verification failed                                |\n| 0         | Standard successful execution exit code.                                           |\n\n<Aside\n  type=\"caution\"\n>\n  Note that the `142`, `144`, and `146` wallet exit codes are designed to prevent you from losing access to wallet functionality. Nevertheless, you should still remember that the wallet doesn't check whether the stored extension addresses actually exist in TON. You can also deploy a wallet with initial data consisting of an empty extensions dictionary and restricted signature mode. In that case, you will still be able to access the wallet through the public key until you add your first extension. So, be careful with these scenarios.\n</Aside>\n\n## Get methods\n\n1. `int is_signature_allowed()` returns stored `is_signature_allowed` flag.\n1. `int seqno()` returns current stored seqno.\n1. `int get_wallet_id()` returns current wallet ID.\n1. `int get_public_key()` returns current stored public key.\n1. `cell get_extensions()` returns extensions dictionary.\n\n## Gasless transactions\n\nStarting with v5, the wallet smart contract supports owner-signed internal messages (`internal_signed`), which enables gasless transactions—for example, paying network fees in USDT when transferring USDT. Gasless transactions are supported not at the network protocol level, meaning that to pay fees in USDT it is necessary to rely on some off-chain infrastructure, e.g., like in Tonkeeper.\n\nFlow scheme for Tonkeeper gasless transactions looks like this:\n\n<Image\n  src=\"/resources/images/wallets/gasless_light.png\"\n  darkSrc=\"/resources/images/wallets/gasless_dark.png\"\n  alt=\"gasless\"\n/>\n\n### Flow details\n\n1. When sending USDT, the user signs one message containing two outgoing USDT transfers:\n   1. USDT transfer to the recipient's address.\n   1. Transfer of a small amount of USDT in favor of the service.\n1. This signed message is sent off-chain by HTTPS to the service backend. The service backend sends it to the TON Blockchain, paying Toncoin for network fees.\n\nThe beta version of the gasless backend API is available at [`tonapi.io/api-v2`](https://tonapi.io/api-v2). If you are developing a wallet app and have feedback about these methods, please share it in [`@tonapitech`](https://t.me/tonapitech) chat.\n"
  },
  {
    "path": "start-here.mdx",
    "content": "---\ntitle: \"Start here\"\nicon: rocket\n---\n\nimport { Aside } from \"/snippets/aside.jsx\";\nimport { Image } from \"/snippets/image.jsx\";\n\nThe documentation is organized by layers of detail, with lower-level details appearing later.\n\n|                        |                                                                                                                                                                  |\n| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Ecosystem              | Tools and libraries for developing on TON, and how to use them.                                                                                                  |\n| Payment processing     | Guides on monitoring and handling blockchain transactions for business applications, such as [exchanges](https://en.wikipedia.org/wiki/Cryptocurrency_exchange). |\n| Standard contracts     | Working with most popular standardized contracts.                                                                                                                |\n| Contract development   | Guides on developing smart-contracts.                                                                                                                            |\n| Languages              | Reference documentation for TON-specific languages.                                                                                                              |\n| TON Virtual Machine    | Description of the low-level language that runs smart-contracts, and details of the runtime.                                                                     |\n| Blockchain foundations | Comprehensive description of the blockchain. Includes web version of whitepapers.                                                                                |\n| Contribute             | Documentation on writing this documentation.                                                                                                                     |\n\n<Aside\n  type=\"caution\"\n>\n  This is a condensed description of TON. The rest of the documentation may assume that all of this is already known to the reader.\n</Aside>\n\n<Aside type=\"tip\">\n  To start building on TON, begin with [Your first smart contract](/contract-dev/first-smart-contract).\n</Aside>\n\n## TON overview\n\n_TON_ is a [blockchain](https://en.wikipedia.org/wiki/Blockchain). It provides a distributed platform for storing data and code, as well as running computations, all the ingredients to host applications. Roughly speaking, it works as if it were a single server executing all the code. The hosted applications are called _smart-contracts_.\n\nThe platform runs on a set of servers, called [nodes](/ecosystem/nodes/overview). Most important type of nodes, _validators_, are owned by individuals or organizations with a large stake in TON and [great interest](/ecosystem/staking/overview) in keeping the platform safe, fair, and operational. Validators have to reach [consensus](https://en.wikipedia.org/wiki/Consensus_\\(computer_science\\)) on the state of the blockchain. Typically, the process takes 5 seconds to reach [transaction finality](/payments/overview#transaction-finality), a time to mint a new block.\n\n## Network communication\n\nThe nodes that run the blockchain interact via the [ADNL](/foundations/whitepapers/ton#3-1-abstract-datagram-network-layer) protocol. User-facing applications usually use [servers](/ecosystem/api/overview) that proxy JSON HTTP requests into the ADNL network. The official version of such a proxy server is provided by the [liteserver](/ecosystem/node/overview#full-node-modes) software. There are public instances of liteserver, so developers are not required to host one on their own servers.\n\n## Toncoin and fees\n\n_Toncoin_ is TON's primary [cryptocurrency](https://en.wikipedia.org/wiki/Cryptocurrency). It is used to pay for the execution of smart contracts, the storage of their data, and network traffic. Such payments are called [fees](/foundations/fees).\n\n## Mainnet and testnet\n\nThere are two instances of TON blockchain: mainnet and testnet.\n\n_Mainnet_ is the \"real\" network. It's where actual payments in Toncoin are made. Applications use the mainnet by default.\n\nThe other network is _testnet_, and it is used by TON developers to check that their applications work correctly before deploying them to mainnet. It uses \"test coins\" that barely have any value.\n\nUsually, when the TON blockchain gets an update, it is first deployed to testnet, and then to mainnet after a brief period of testing, so sometimes they may run different software. Also, their [configuration](/foundations/config), availability, and throughput might be different.\n\n## Workchains and shards\n\nEach network is split into [workchains](/foundations/shards) that can freely interact with each other, but their implementations may differ significantly.\n\nAt the moment, there are two workchains: _basechain_ (`workchain_id = 0`) for regular use, and a very similar _masterchain_ (`workchain_id = -1`) for TON's [internal](/payments/overview#transaction-finality) [bookkeeping](/foundations/system). The masterchain follows mostly the same rules, except that using it is more expensive to limit the amount of traffic that interferes with TON's internals.\n\nTo be freely scalable, each workchain is split into _shards_. The number of shards is [determined dynamically](/foundations/shards) based on the current network load. Internally, every shard is implemented as a separate blockchain. Except for increased latency, the effect on the user-facing code is minimal.\n\n## Accounts\n\nIt's easiest to visualize the blockchain as a set of [accounts](/foundations/addresses/overview). Each account has an address and a status.\n\n### Account statuses\n\nOver its lifetime, an account changes its [status](/foundations/status) among four values:\n\n- `nonexist`: There wasn't a single operation with the account, or it was removed. It has neither a balance, nor code.\n- `uninit`: If some Toncoin is transferred to an account, it now exists, but there is still no smart contract code on it. It now has a balance.\n- `active`: After a deploy message (see below) with code and initial data is sent to an account, it becomes active and can process other messages. It now has a balance, code, and internal state.\n- `frozen`: If an account is overdue on its [storage fees](/foundations/fees#storage-fee), it will be frozen until the fees are paid. If the overdue amount reaches a maximum limit specified by the blockchain, the account goes completely bankrupt, is removed, and ceases to exist.\n\n### Smart contracts\n\nThe _code_ on an active account is a smart contract. The term _contract_ is often used for an account that holds the code.\n\n<div\n  style={{ display: \"flex\", justifyContent: \"center\" }}\n>\n  <Image\n    src=\"/resources/images/states.png\"\n    darkSrc=\"/resources/images/states-dark.png\"\n    alt=\"Statuses overview\"\n  />\n</div>\n\n### Account addresses\n\nThe [internal address](/foundations/addresses/overview#internal-addresses) of an account is a pair of two numbers: its workchain ID and a 256-bit number. It may be displayed in the [raw format](/foundations/addresses/formats) (e.g., `0:4098805d2272a61b375350c6b2f5faaaf27c8267d8e7521ff2045104fdc7de76`), but is usually shown in a user-friendly format (e.g., `UQBKgXCNLPexWhs2L79kiARR1phGH1LwXxRbNsCFF9doczSI`).\n\n## Messages\n\nAddresses specify where [messages](/foundations/messages/overview) should be delivered. There are three types of messages:\n\n- [internal](/foundations/messages/internal) messages are sent between accounts;\n- [incoming external](/foundations/messages/external-in) messages are sent from code outside the blockchain to a contract;\n- [outgoing external](/foundations/messages/external-out) messages are broadcast to the external network; somewhat similar to adding them into the globally available list of all outgoing external messages that ever happened.\n\nEvery internal message should have some Toncoin attached to it so that it can pay for the cost of handling it. External messages cannot have Toncoin attached to them because they spend some of their time outside the blockchain, and only the blockchain can prove the transfer of Toncoin is correct.\n\nIncoming external messages come from an external address, and outgoing external messages go to an external address.\n\nThe _state_ of the account changes only when it handles messages. Messages also change the account's balance. Usually, to have a state and a balance, and to handle messages, the account must be `active`.\n\n## `StateInit`\n\nA message might also be a [deploy message](/foundations/messages/deploy) if it has a `StateInit` structure attached with its initial code and data. When such a message is sent, the hash of `StateInit` must match the destination address. If it does, the code and data are stored in the account at that address, and the account becomes active. Both the code and data stored in the account may change in the future, but its address will remain the same as when it was originally deployed.\n\n## Transactions\n\nFormally, a message is only an intent: it has a destination, possibly some Toncoin, and data. After the message is handled and all the necessary changes are applied to the blockchain, the message is packed, along with a description of those changes, into a single packet of data, called a [transaction](/foundations/messages/ordinary-tx). A transaction records the state changes on an account. [Some transactions](/foundations/messages/overview#transactions) might happen without any message.\n\n## TON Virtual Machine\n\nInternal and incoming external messages execute the account's code. The code is interpreted by [TON Virtual Machine](/tvm/overview) (TVM). It is written in _bitcode_, a binary format specific to TVM. In the future, TVM might support multiple binary languages, _codepages_, but at the moment there is only codepage 0 (`CP0`).\n\n### Phases\n\nWhen execution [starts](/tvm/initialization), the message and current account state are provided to the code. By the end of execution, the account might change its state or code, or send internal or outgoing external messages.\n\nThe execution follows a process whose steps are called [phases](/foundations/phases). [Fees](/foundations/fees) are deducted during this process. Fees might be deducted from the account's balance or from the Toncoin the message carries, depending on the [mode](/foundations/messages/modes) of the message, or by [explicit choice](/foundations/messages/external-in#accepting-message) made in the contract's code.\n\n### Gas\n\nExecution cost is first measured in _gas_ units, then converted to Toncoin. This unit is separate so that if code execution becomes computationally cheaper (or more expensive), validators can vote to change the [price of gas](/foundations/config#param-20-and-21:-gas-prices) in Toncoin.\n\n### Exit codes\n\nIf something goes wrong, a non-zero [exit code](/tvm/exit-codes) might be returned, no changes to state or code are saved, and no further messages are sent. If the message that resulted in a failed transaction is marked as _bounceable_, a [bounce message](/foundations/messages/internal#bounces) is sent back to the sender. Bounce messages are used to inform the sender that handling of their message failed. They can carry either truncated or full body of the original message.\n\n## Traces\n\nThe most common reason a code is executed is when some account has received a message. Internal messages can only be sent by another contract executing some code, and that contract must have received a message from somewhere too. In the end, every message can be considered part of some _trace_: a tree of messages between accounts that starts with an incoming external message, continues with internal messages, and possibly ends with some outgoing external messages.\n\n### Asynchronous execution\n\nWhen some interaction with the blockchain involves multiple contracts, their code is not executed in the same block. Contracts have to exchange messages with each other, and two such concurrent traces may interleave their messages. This fact is usually referred to as \"_asynchronous_ message handling.\" This feature of TON allows a limit to be placed on the maximum complexity of atomic computation and aids its scalability, but it is important to keep it in mind because it might create [race conditions](/contract-dev/security#race-condition-of-messages).\n\n## Languages\n\nMost development is done in the [Tolk](/languages/tolk/overview), a high-level programming language. Its compiler is included in the [Blueprint](/contract-dev/blueprint/overview) development environment and will be available to all projects created from the template.\n\nOriginally, [Fift](/languages/fift/overview), a Forth-like assembly language, and [FunC](/languages/func/overview), a C-like intermediate-level language, were used for contract development.\n\n## Get methods\n\nIf an external service needs to extract data from the blockchain, it can call a [get method](/tvm/get-method): an arbitrary function implemented in the code deployed to an account. Every call of a get method spawns a separate instance of TVM. Any changes to the blockchain made during the execution of a get method are not committed to the blockchain.\n\nUnlike in [other blockchains](/from-ethereum), get methods cannot be called by other contracts. It is intentional for several reasons:\n\n- by the time another contract receives the result of such a call, other messages may have been processed and may have changed the result;\n- get methods are executed completely separately, and changes from the blockchain are not guaranteed to be propagated to the server running the code of a get method.\n\n## Wallets\n\nThe main user of incoming external messages is a [wallet](/standard/wallets/how-it-works). A wallet is an account with a specific kind of smart contract deployed on it, which can handle incoming external messages, specifically _transfer_ messages. A transfer message is a request to send an internal message to another account. Thus, a wallet transforms incoming external messages to internal messages.\n\n### Wallet contract types\n\nThere are several [implementations](/standard/wallets/comparison) of wallets, with varying extra functionality and protection. [`V5R1`](/standard/wallets/v5) is the latest official general-purpose wallet. The text below describes only the functionality common to most wallets.\n\n### How wallets work\n\nA transfer message consists of a destination address and, optionally, an internal message, both serialized and signed with a [private key](https://en.wikipedia.org/wiki/Public-key_cryptography). The wallet stores a public key and uses it to check that a transfer message was signed with the corresponding private key. If the check succeeds, it sends that internal message to the destination address. This ensures only the user (or a service) who knows the private key can use the wallet.\n\nPrivate and public keys are generated in a program or service outside the blockchain. Public key is used in a `StateInit` during the deploy, and determines the address of the wallet account. Keypair is usually derived from a set of 24 random words called a [mnemonic](/standard/wallets/mnemonics).\n\nBefore the code of the wallet can be deployed on an account with an incoming external message, some other account has to transfer Toncoin to the wallet account. As external messages cannot have any Toncoin attached to them, if no funds are in the account when it handles an external message, it cannot pay for the message that deploys a wallet. The transfer of Toncoin to a wallet account usually comes from an exchange or another user. In testnet, there is [a bot](/ecosystem/wallet-apps/get-coins) that sends test coins to an account for free.\n\nUsually, a transfer message is sent without an internal message in its payload and only instructs the wallet to transfer some Toncoin to a destination address. This is the reason this type of smart contract is called a wallet.\n\nAn internal message might be a request to some other contract or even a deploy message that deploys code on other accounts. In this way, a wallet acts as a proxy between a user (or an external service) and the rest of the blockchain.\n\n### Wallet apps\n\nEnd users usually use [wallet apps](/ecosystem/wallet-apps/web) to create and use wallets. An exchange will usually create a wallet for a user as well.\n\n## Standard contracts\n\nThe other [important types](/standard/tokens/overview) of contracts are\n\n- [Jetton](/standard/tokens/jettons/overview) tokens roughly correspond to coins and allow developers to mint their own currency;\n- [NFT](/standard/tokens/nft/overview) tokens are similar to tickets: unique items that can be sold;\n- [SBT](/standard/tokens/nft/sbt) tokens are like medals: unique items that can be given to someone but can never be sold or transferred.\n\nMany popular contract types have been standardized in [TON Enhancement Proposals](https://github.com/ton-blockchain/TEPs) (_TEP_), mostly describing expected contract interfaces with TL-B schemas. This allows tooling to be reused between similar contracts. For example, explorers detect TEP-standardized contracts and display their binary messages in a user-friendly format, and provide an interface to call their get methods.\n\n## Explorers\n\nAn [explorer](/ecosystem/explorers/overview) is a type of web app that displays information about the current state of accounts (including wallets, Jettons, and NFTs) and the history of transactions.\n\n## APIs and SDKs\n\nTo interact with wallets, Jettons, and other contracts, data has to be sent through an ADNL or HTTP API into the network. There are several ways to connect:\n\n- directly call the API, or\n- use [an SDK](/ecosystem/sdks) that simplifies working with an API by wrapping its methods in a more user-friendly interface; the most popular TypeScript SDK for this is `@ton/ton`.\n\n## TON Connect\n\nWhen an application has to use a wallet to prove the user's identity, it needs access to the wallet's private key. Giving arbitrary applications access to the private key is insecure, as they could perform arbitrary actions with the wallet. To address this, there is the [TON Connect](/ecosystem/ton-connect/overview) set of SDKs that provide interfaces\n\n- for an application to perform an action through the wallet app;\n- for a wallet app to handle these requests.\n\nFor example, Telegram apps use TON Connect to access a wallet that is integrated into Telegram.\n\n## Data storage model\n\nAll data on TON is stored as trees of [cells](/foundations/serialization/cells): the state of contracts, their code, and messages. Each cell stores up to 1023 bits of data and can have up to 4 _refs_ to other cells. Each cell has a hash computed from its bits and refs. Because the hash of a cell that directly or indirectly references itself would require knowing the same hash, creating cyclic data structures is impossible.\n\nStandard serialization of such a data structure into a single binary string is the [bag of cells](/foundations/serialization/boc) (_BoC_). Compilers of smart-contract programming languages produce a BoC with code. When there is a need to store cells in a file or send them over the network, they are usually serialized into a BoC.\n\n### Binary representation\n\nTo tell other developers how a certain type of data is stored in cells, a [TL-B](/languages/tl-b/overview) schema language is used. Its purpose is similar to that of [protocol buffers](https://en.wikipedia.org/wiki/Protocol_Buffers) or [binary templates](https://en.wikipedia.org/wiki/010_Editor#Binary_Templates), but it provides more features for structuring data at the bit level.\n\n[There are libraries](/ecosystem/sdks) for assembling data structures out of cells. For TypeScript, the most popular one is [`@ton/core`](https://github.com/ton-org/ton-core).\n\nThe TL-B schemas for binary representations of messages, transactions, initial contract state, and most other data structures used by the blockchain can be found in the [`block.tlb`](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb) file in the [TON monorepo](https://github.com/ton-blockchain/ton). TypeScript functions for serializing and deserializing them are provided by the [`@ton/core`](https://github.com/ton-org/ton-core) and [`@ton/ton`](https://github.com/ton-org/ton) libraries.\n\nIn general, a library that converts data structures between cells and the format native to a programming language, or allows calling contract methods as native functions of the language, is called a _wrapper_ or _binding_. For example, functions that deserialize Jetton-related cell data into TypeScript objects can be found in the [`assets-sdk`](https://github.com/ton-community/assets-sdk/blob/5285cd75a97acbb15999e7dfb3b8e4ec9e98b4ed/src/jetton/types/JettonBurnMessage.ts) library. Some high-level programming languages [can generate](/languages/tact) bindings from the contract's source code. The \"rule of thumb\" is that production-grade code should not include low-level manipulation of binary data, and should instead rely on a library with bindings. This reduces the chance of mistakes and ensures the code has more users. With widely reused code, there are more opportunities to detect mistakes, and they are more likely to be fixed quickly.\n\n### Blockchain interaction\n\nSo, to interact with the blockchain, a couple of libraries are usually used: one that handles the connection to the blockchain and another that works with the specific type of data sent over that connection.\n\nNot all computation has to be done _on-chain_, i.e., executed inside TVM and paid for with Toncoin. Computing and storing data on the blockchain is significantly more expensive than doing so on a regular CPU. Instead, much of the work can be done in _off-chain_ code, in a regular programming language, before or after sending a request to the blockchain. The recommended development practice is to write a TypeScript library that calls contracts implemented in Tolk.\n"
  },
  {
    "path": "tvm/builders-and-slices.mdx",
    "content": "---\ntitle: \"Builders and Slices\"\n---\n\nIn TVM, the `Cell` type contains only metadata of the cell: level, hashes, and depths. To read actual data, TVM need to _load_ cell from celldb, key-value storage of the node, which stores cells by their representation hashes. [`CTOS`](/tvm/instructions#d0-ctos) instruction loads a cell by its metadata from `Cell` type, and provides a `Slice`, a read-only wrapper for the cell's content. To simplify coding cell deserializers in smart contracts, instead of behaving like a simple bit/ref array, `Slice` is a \"read cursor\": it allows loading a piece of data from the beginning of the slice, returning that data and the slice that contains remaining data. On the other hand, there is a `Builder` type, which provides a convenient way to serialize data to a cell. Only the `Cell` type can be used outside of TVM: in output actions and in persistent storage.\n\n## Builder\n\nBuilder provides a way to construct a cell from a sequence of values of the following TVM types: integers, cells (as references), slices, and builders. Tuples, continuations, and `null` are not serializable.\n\nFor example, serialize the following numbers to a cell:\n\n```\n1 (uint4)\n2 (uint4)\n-1 (int8)\n```\n\nFirst, create an empty builder using [`NEWC`](/tvm/instructions#c8-newc):\n\n```fift Fift\nNEWC  // returns empty builder x{}\n```\n\nThen, put a number on the stack:\n\n```fift Fift\n1 INT  // stack: x{} 1\n```\n\nAnd call [`STU`](/tvm/instructions#cb-stu) (\"STore Unsigned integer\") to store integer into builder (swapping builder and value to meet `STU` input order):\n\n```fift Fift\nSWAP  // stack: 1 x{}\n4 STU  // stack: x{0001}\n```\n\nThen, store the other two numbers:\n\n```fift Fift\n2 INT  // x{0001} 2\nSWAP  // 2 x{0001}\n4 STU  // x{00010010}\n\n-1 INT  // x{00010010} -1\nSWAP  // -1 x{00010010}\n8 STI  // x{0001001011111111}\n```\n\nAnd, finally, [`ENDC`](/tvm/instructions#c9-endc) instruction finalizes the builder to a cell.\n\n## Slice\n\nSlice allows reading data back from a cell, field by field. For example, deserialize bitstring `x{0001001011111111}` created above.\n\n[`CTOS`](/tvm/instructions#d0-ctos) (\"Cell TO Slice\") loads a `Cell` to a `Slice`.\n\n```fift Fift\n// assume a cell with bitstring x{0001001011111111} is on the stack\nCTOS  // x{0001001011111111}\n```\n\nThen, call [`LDU`](/tvm/instructions#d3-ldu) (\"LoaD Unsigned integer\") to read first value (`uint4`).\n\n```fift Fift\n4 LDU  // 1 x{001011111111}\n```\n\n`LDU` takes the first 4 bits from a slice and creates a new slice without these 4 bits: `x{0001|001011111111}` slices into a number `0001` and a slice `x{001011111111}`.\n\nSimilarly, read another two numbers:\n\n```fift Fift\n4 LDU // 1 2 x{11111111}\n8 LDI // 1 2 -1 x{}\n```\n\nA common way to ensure there is no data left inside the slice is to call [`ENDS`](/tvm/instructions#d1-ends).\n"
  },
  {
    "path": "tvm/continuations.mdx",
    "content": "---\ntitle: \"Continuations\"\n---\n\n[Continuation](https://en.wikipedia.org/wiki/Continuation) is a value that contains executable code. Continuations are used whenever non-linear code execution is required:\n\n- conditions\n- loops\n- function calls\n- throwing and catching exceptions\n\nContinuation can be thought as \"pointer to a code\", with an important distinction that, unlike pointers on other machines, it's not a number.\n\n## Ordinary continuation\n\nThe most common kind of continuations are the ordinary continuations, which are just code Slices, containing (the remainder of) TVM bitcode. Optionally, it can contain any of the additional parameters:\n\n- **Stack**. A list of values that will be pushed on stack before continuation is executed.\n- **Savelist**. A list of values for registers before continuation is executed.\n- **Codepage**. Bitcode version used to run this continuation.\n- **Number of arguments (`nargs`)**. Number of values from call-side stack to push onto new stack before continuation is executed.\n\n## Control flow\n\n### Jumps\n\nThe simplest way to change `cc` is to use [`JMPREF`](/tvm/instructions#db3d-jmpref) instruction. It just sets `cc` to the reference operand of `JMPREF` (stack and registers are not affected).\n\nThe following rules are applied during the jump:\n\n- Initialize a new stack with the target continuation initial stack\n- Move `nargs` elements from the caller stack to the new stack, if the target continuation has `nargs`\n- If the target continuation `nargs` is not defined, move all elements from the caller stack to the new stack\n- Pop register values from target continuation savelist\n\nDue to the limitation of the `Cell` type, one continuation can contain no more than 1023 bits of bitcode. To execute longer functions, we could pass `JMPREF` as a last instruction, which will continue execution of a function in a new continuation.\n\n```fift Fift\n// some instructions\n<{\n  // next instructions that exceed the 1023-bit limit are placed in a child cell\n}> JMPREF\n```\n\nTo simplify things, TVM has an _implicit jump_ mechanism, which automatically jumps to the next reference of `cc` when there are no more instructions to execute.\n\n### Calls\n\n_Call_ is a special type of jump, which also saves `cc` to `c0`, so the callee can pass execution back to the caller. That is how [`CALLREF`](/tvm/instructions#db3c-callref) works.\n\n```fift Fift\n2 PUSHINT\n3 PUSHINT\n<{\n  ADD\n}> CALLREF // returns 5\n```\n\nAfter `ADD` is executed, there are no more instructions to execute in `cc`, and also no references for implicit jumps. _Implicit return_ sets `cc` back to `c0`, which was a previous `cc`. Let's look at the _composition_ of continuations which `CALLREF` produces:\n\n```mermaid\nflowchart TD\n    A(var **c**) -->|c<sub>0</sub>| B(cc)\n    B -->|c<sub>0</sub>| C(register c<sub>0</sub>)\n```\n\nDuring the call, the remaining of the current continuation is saved to `c0`. Also, current `c0` is pushed to the savelist of `cc` to restore its original value after return. If we would call function `f1`, then call `f2` inside `f1` and `f3` inside `f2`, there will be a callstack formed by savelists of continuations: `c0` value inside `f3` can be represented as `(rest of f2) ◦0 (rest of f1) ◦0 (rest of the caller)`. `a ◦i b` is a continuation composition operator, which saves continuation `b` as a c<sub>i</sub> register of continuation `b`, so, we can say that `b` is executed after `a` by register c<sub>i</sub>.\n\n## Extraordinary continuations\n\n### Quit\n\n**TL-B**: `vmc_quit$1000 exit_code:int32 = VmCont`\n\nExits TVM with `exit_code`. During [initialization of TVM](/tvm/initialization), `c0` is set to `Quit(0)`, and `c1` to `Quit(1)`.\n\n### ExcQuit\n\n**TL-B**: `vmc_quit_exc$1001 = VmCont`\n\nDefault exception handler. Terminates TVM with exception code popped from the stack. During [initialization of TVM](/tvm/initialization), `c2` is set to `ExcQuit`.\n\n### PushInt\n\n**TL-B**: `vmc_pushint$1111 value:int32 next:^VmCont = VmCont`\n\nPushes `value` on the stack and jumps to `next`. This continuation is only used in [`BOOLEVAL`](/tvm/instructions#edf9-booleval) instruction.\n\n### Envelope\n\n**TL-B**: `vmc_envelope$01 cdata:VmControlData next:^VmCont = VmCont`\n\nUpdates current VM state with `cdata` and jumps to `next`.\n\n### Repeat\n\n**TL-B**: `vmc_repeat$10100 count:uint63 body:^VmCont after:^VmCont = VmCont`\n\nExecutes `body` `count` times, then jumps to `after`. Under the hood, it just sets `body` `c0` to `Repeat(count - 1, body, after)` if `count > 0`, otherwise jumps to `after`. Used in [`REPEAT`](/tvm/instructions#e4-repeat) and variants.\n\n### Again\n\n**TL-B**: `vmc_again$110001 body:^VmCont = VmCont`\n\nExecutes `body` infinite times by setting `body` `c0` to `Again(body)`. Used in [`AGAIN`](/tvm/instructions#ea-again) and variants.\n\n### Until\n\n**TL-B**: `vmc_until$110000 body:^VmCont after:^VmCont = VmCont`\n\nPops bool from stack, jumps to `body` with `c0 = Until(body, after)` if bool is `false`, otherwise jumps to `after`. Used in [`UNTIL`](/tvm/instructions#e6-until) and variants.\n\n### WhileCondition\n\n**TL-B**: `vmc_while_cond$110010 cond:^VmCont body:^VmCont after:^VmCont = VmCont`\n\nRepresents a branching point of a while loop. Pops a bool from the stack, jumps to `body` with `c0 = WhileBody(cond, body, after)` if the bool is `true`, otherwise jumps to `after`. Used in [`WHILE`](/tvm/instructions#e8-while) and variants.\n\n### WhileBody\n\n**TL-B**: `vmc_while_body$110011 cond:^VmCont body:^VmCont after:^VmCont = VmCont`\n\nRepresents a delayed iteration of a while loop. Jumps to `cond` with `c0 = WhileCondition(cond, body, after)`. It is assumed that the evaluation of `cond` leaves a bool at the top of the stack for the following `WhileCondition` to check. Used in [`WHILE`](/tvm/instructions#e8-while) and variants.\n"
  },
  {
    "path": "tvm/exit-codes.mdx",
    "content": "---\ntitle: \"Exit codes\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nAn exit code is a 32-bit signed integer that indicates whether the compute or action phase of the transaction was successful. If not, it holds the code of the exception that occurred.\n\nEach transaction on TON Blockchain consists of multiple phases. An _exit code_ is a 32-bit signed integer that indicates whether the [compute](#compute) or [action](#action) phase of the transaction was successful, and if not, holds the code of the exception that occurred. Each exit code represents its own exception or the resulting state of the transaction.\n\nExit codes 0 and 1 indicate normal (successful) execution of the [compute phase](#compute). Exit (or [result](#action)) code 0 indicates normal (successful) execution of the [action phase](#action). Any other exit code indicates that a certain exception has occurred and that the transaction was not successful in one way or another, i.e., the transaction was reverted or the inbound message has bounced back.\n\nTON Blockchain reserves exit code values from 0 to 127. The range from 256 to 65535 is free for developer-defined exit codes.\n\n<Aside>\n  While an exit (or [result](#action)) code is a 32-bit signed integer on TON Blockchain, an attempt to throw an exit code outside the bounds of a 16-bit unsigned integer ($0 - 65535$) will cause an error with [exit code 5](#5%3A-integer-out-of-expected-range). This is done intentionally to prevent some exit codes from being produced artificially, such as [exit code -14](#-14%3A-out-of-gas-error).\n</Aside>\n\n## Table of exit codes\n\nThe following table lists exit codes with their origin (where they can occur) and a short description for each.\n\n| Exit code                                                    | Origin                              | Brief description                                                                                      |\n| :----------------------------------------------------------- | :---------------------------------- | :----------------------------------------------------------------------------------------------------- |\n| [0](#0%3A-normal-termination)                                | [Compute][c] and [action][a] phases | Standard successful execution exit code.                                                               |\n| [1](#1%3A-alternative-termination)                           | [Compute phase][c]                  | Alternative successful execution exit code. Reserved, but does not occur.                              |\n| [2](#2%3A-stack-underflow)                                   | [Compute phase][c]                  | Stack underflow.                                                                                       |\n| [3](#3%3A-stack-overflow)                                    | [Compute phase][c]                  | Stack overflow.                                                                                        |\n| [4](#4%3A-integer-overflow)                                  | [Compute phase][c]                  | Integer overflow.                                                                                      |\n| [5](#5%3A-integer-out-of-expected-range)                     | [Compute phase][c]                  | Range check error — an integer is out of its expected range.                                           |\n| [6](#6%3A-invalid-opcode)                                    | [Compute phase][c]                  | Invalid [TVM][tvm] opcode.                                                                             |\n| [7](#7%3A-type-check-error)                                  | [Compute phase][c]                  | Type check error.                                                                                      |\n| [8](#8%3A-cell-overflow)                                     | [Compute phase][c]                  | Cell overflow.                                                                                         |\n| [9](#9%3A-cell-underflow)                                    | [Compute phase][c]                  | Cell underflow.                                                                                        |\n| [10](#10%3A-dictionary-error)                                | [Compute phase][c]                  | Dictionary error.                                                                                      |\n| [11](#11%3A-%22unknown%22-error)                             | [Compute phase][c]                  | Described in [TVM][tvm] docs as \"Unknown error, may be thrown by user programs.\"                       |\n| [12](#12%3A-fatal-error)                                     | [Compute phase][c]                  | Fatal error. Thrown by [TVM][tvm] in situations deemed impossible.                                     |\n| [13](#13%3A-out-of-gas-error)                                | [Compute phase][c]                  | Out of gas error.                                                                                      |\n| [-14](#-14%3A-out-of-gas-error)                              | [Compute phase][c]                  | Same as 13. Negative, so that it [cannot be faked](#13%3A-out-of-gas-error).                           |\n| [14](#14%3A-virtualization-error)                            | [Compute phase][c]                  | VM virtualization error. Reserved, but never thrown.                                                   |\n| [32](#32%3A-action-list-is-invalid)                          | [Action phase][a]                   | Action list is invalid.                                                                                |\n| [33](#33%3A-action-list-is-too-long)                         | [Action phase][a]                   | Action list is too long.                                                                               |\n| [34](#34%3A-invalid-or-unsupported-action)                   | [Action phase][a]                   | Action is invalid or not supported.                                                                    |\n| [35](#35%3A-invalid-source-address-in-outbound-message)      | [Action phase][a]                   | Invalid source address in outbound message.                                                            |\n| [36](#36%3A-invalid-destination-address-in-outbound-message) | [Action phase][a]                   | Invalid destination address in outbound message.                                                       |\n| [37](#37%3A-not-enough-toncoin)                              | [Action phase][a]                   | Not enough Toncoin.                                                                                    |\n| [38](#38%3A-not-enough-extra-currencies)                     | [Action phase][a]                   | Not enough extra currencies.                                                                           |\n| [39](#39%3A-outbound-message-does-not-fit-into-cell)         | [Action phase][a]                   | Outbound message does not fit into a cell after rewriting.                                             |\n| [40](#40%3A-cannot-process-message)                          | [Action phase][a]                   | Cannot process a message — not enough funds, the message is too large, or its Merkle depth is too big. |\n| [41](#41%3A-library-reference-is-null)                       | [Action phase][a]                   | Library reference is null during library change action.                                                |\n| [42](#42%3A-library-change-action-error)                     | [Action phase][a]                   | Library change action error.                                                                           |\n| [43](#43%3A-library-limits-exceeded)                         | [Action phase][a]                   | Exceeded the maximum number of cells in the library or the maximum depth of the Merkle tree.           |\n| [50](#50%3A-account-state-size-exceeded-limits)              | [Action phase][a]                   | Account state size exceeded limits.                                                                    |\n\n{/* NOTE: Some might depend on a phase; in such cases, the table entry might be:\n\n  | number | [Compute][c] and [action][a] phases | Depends on the phase.\n\n  */}\n\n<Aside>\n  Often enough, you might encounter the exit code 65535 (or `0xffff`), which usually means the same as the [exit code 130](#130%3A-) — the received opcode is unknown to the contract, as no receivers were expecting it. When writing contracts, the exit code 65535 is set by the developers and not by [TVM][tvm] or the Tolk compiler.\n</Aside>\n\n[c]: /tvm/overview#compute-phase\n[a]: /tvm/overview#action-phase\n\n## Exit codes in Blueprint projects\n\nIn [Blueprint][bp] tests, exit codes from the [compute phase](#compute) are specified in the `exitCode` field of the object argument for the `toHaveTransaction()` method of the `expect()` matcher. The field for the [result](#action) codes (exit codes from the [action phase](#action)) in the same `toHaveTransaction()` method is called `actionResultCode`.\n\n{/*\n  <Aside>\n\n  Read more about expecting specific exit codes: [Transactions with intentional errors](/book/debug#tests-errors).\n\n  </Aside>\n  */}\n\nAdditionally, one can examine the result of sending a message to a contract and discover the phases of each transaction and their values, including exit (or result) codes for the [compute phase](#compute) (or [action phase](#action)).\n\nNote that to do so, you'll have to perform a couple of type checks first:\n\n```ts\nit('tests something, you name it', async () => {\n  // Send a specific message to our contract and store the results\n  const res = await your_contract_name.send({/* … */});\n\n  // Now, we have access to an array of executed transactions,\n  // with the second one (index 1) being the one we look for\n  const tx = res.transactions[1]!;\n\n  // To do something useful with it, let's ensure that its type is 'generic'\n  // and that the compute phase in it wasn't skipped\n  if (tx.description.type === \"generic\"\n      && tx.description.computePhase.type === \"vm\") {\n    // Finally, we're able to freely peek into the transaction for general details,\n    // such as printing out the exit code of the compute phase if we so desire\n    console.log(tx.description.computePhase.exitCode);\n  }\n});\n```\n\n## Compute and action phases\n\n### 0: Normal termination\n\nThis exit (or [result](#action)) code indicates the successful completion of the [compute phase](#compute) (or [action phase](#action)) of the transaction.\n\n## Compute phase\n\n[TVM][tvm] initialization and all computations occur in the [compute phase][c].\n\nIf the compute phase fails (the resulting exit code is neither [0](#0%3A-normal-termination) nor [1](#1%3A-alternative-termination)), the transaction skips the [action phase](#action) and proceeds to the bounce phase. In this phase, a bounce message is formed for transactions initiated by the inbound message.\n\n### 1: Alternative termination\n\nThis is an alternative exit code for the successful execution of the [compute phase](#compute). It is reserved but never occurs.\n\n### 2: Stack underflow\n\nIf an operation consumes more elements than exist on the stack, an error with exit code 2 is thrown: `Stack underflow`.\n\n```tolk title=\"Tolk\"\nfun drop(): void asm \"DROP\"\n\nfun onInternalMessage() {\n    try {\n        // Removes 100 elements from the stack, causing an underflow\n        repeat(100){\n            drop();\n        }\n    } catch(exitCode) {\n        // exitCode is 2\n        assert (exitCode == 2) throw 1111;\n    }\n}\n```\n\n<Aside\n  title=\"Useful links\"\n>\n  [TVM overview][tvm].\n</Aside>\n\n### 3: Stack overflow\n\nIf there are too many elements copied into a closure continuation, an error with exit code 3 is thrown: `Stack overflow`. This occurs rarely unless you're deep in the [Fift and TVM assembly](/languages/fift/fift-and-tvm-assembly) trenches:\n\n```tolk title=\"Tolk\"\n// Remember kids, don't try to overflow the stack at home!\nfun stackOverflow(): void asm\n\"\"\"\n    x{} SLICE        // s\n    BLESS            // c\n    0 SETNUMARGS     // c'\n    2 PUSHINT        // c' 2\n    SWAP             // 2 c'\n    1 -1 SETCONTARGS // ← this blows up\n\"\"\"\n\nfun onInternalMessage() {\n    try {\n        stackOverflow();\n    } catch(exitCode) {\n        // exitCode is 3\n        assert (exitCode == 3) throw 1111;\n    }\n}\n```\n\n<Aside\n  title=\"Useful links\"\n>\n  [TVM overview][tvm].\n</Aside>\n\n### 4: Integer overflow\n\nIf the value in a calculation goes beyond the range from $-2^{256}$ to $2^{256} - 1$ inclusive, or there's an attempt to divide or perform modulo by zero, an error with exit code 4 is thrown: `Integer overflow`.\n\n```tolk title=\"Tolk\"\nfun touch<T>(y: T): void asm \"NOP\" // so that the compiler doesn't remove instructions\nfun pow2(y: int): int asm \"POW2\"\n\nfun onInternalMessage() {\n    var x = -pow2(255) - pow2(255);\n    var zero = x - x;\n\n    try {\n        touch(-x); // integer overflow by negation\n                   // since the max positive value is 2^{256} - 1\n    } catch(exitCode) {\n        // exitCode is 4\n        assert (exitCode == 4) throw 1111;\n    }\n\n    try {\n        touch(x / zero); // division by zero!\n    } catch (exitCode) {\n        // exitCode is 4\n        assert (exitCode == 4) throw 1111;\n    }\n\n    try {\n        touch(x * x * x); // integer overflow!\n    } catch (exitCode) {\n        // exitCode is 4\n        assert (exitCode == 4) throw 1111;\n    }\n\n    // There can also be an integer overflow when performing:\n    // addition (+),\n    // subtraction (-),\n    // division (/) by a negative number or modulo (%) by zero\n}\n```\n\n### 5: Integer out of expected range\n\nA range check error occurs when some integer is out of its expected range. Any attempt to store an unexpected amount of data or specify an out-of-bounds value throws an error with exit code 5: `Integer out of expected range`.\n\nExamples of specifying an out-of-bounds value:\n\n```tolk title=\"Tolk\"\nfun touch<T>(y: T): void asm \"NOP\" // so that the compiler doesn't remove instructions\nfun pow2(y: int): int asm \"POW2\"\n\nfun onInternalMessage() {\n    try {\n        // Repeat only operates on an inclusive range from 1 to 2^{31} - 1\n        // Any valid integer value greater than that causes an error with exit code 5\n        repeat (pow2(55)) {\n            touch(\"smash. I. must.\");\n        }\n    } catch(exitCode) {\n        // exitCode is 5\n        assert (exitCode == 5) throw 1111;\n    }\n\n    try {\n        // Builder.storeUint() function can only use up to 256 bits, thus 512 is too much:\n        touch(beginCell().storeUint(-1, 512).toCell());\n    } catch (exitCode) {\n        // exitCode is 5\n        assert (exitCode == 5) throw 1111;\n    }\n\n    try {\n        touch(beginCell().storeUint(100, 2).toCell()); // maximum value is 2^{2} - 1 = 3 < 100\n    }\n    catch(exitCode) {\n        // exitCode is 5\n        assert (exitCode == 5) throw 1111;\n    }\n\n    try {\n        val deployMsg = createMessage({\n            bounce: false,\n            dest: {\n                workchain: 0,\n                stateInit: {\n                    code: beginCell().endCell(),\n                    data: beginCell().endCell(),\n                },\n                toShard: {\n                    fixedPrefixLength: pow2(52), // but fixedPrefixLength is uint5\n                    closeTo: contract.getAddress()\n                },\n            },\n            value: 1,\n            body: beginCell().endCell(),\n        });\n\n        deployMsg.send(SEND_MODE_PAY_FEES_SEPARATELY);\n    } catch (exitCode) {\n        // exitCode is 5\n        assert (exitCode == 5) throw 1111;\n    }\n}\n\n```\n\n### 6: Invalid opcode\n\nIf you specify an instruction that is not defined in the current [TVM][tvm] version or attempt to set an unsupported [code page][tvm], an error with exit code 6 is thrown: `Invalid opcode`.\n\n```tolk title=\"Tolk\"\n// There's no such code page, and an attempt to set it fails\nfun invalidOpcode(): void asm \"42 SETCP\"\n\nfun onInternalMessage() {\n    try {\n        invalidOpcode();\n    } catch (exitCode) {\n        // exitCode is 6\n        assert (exitCode == 6) throw 1111;\n    }\n}\n```\n\n### 7: Type check error\n\nIf an argument to a primitive is of an incorrect value type or there is any other mismatch in types during the [compute phase](#compute), an error with exit code 7 is thrown: `Type check error`.\n\n```tolk title=\"Tolk\"\nfun touch<T>(y: T): void asm \"NOP\" // so that the compiler doesn't remove instructions\n// The actual returned value type doesn't match the declared one\nfun typeCheckError(): cell asm \"42 PUSHINT\";\n\nfun onInternalMessage() {\n    try {\n        // it isn't cell\n        touch(typeCheckError().beginParse());\n    } catch (exitCode) {\n        // exitCode is 7\n        assert (exitCode == 7) throw 1111;\n    }\n}\n```\n\n### 8: Cell overflow\n\nTo construct a `cell`, a `builder` primitive is used. If you try to store more than 1023 bits of data or more than four references to other cells, an error with exit code 8 is thrown: `Cell overflow`.\n\nThis error can be triggered by manual construction of the cells via relevant methods, such as `storeInt()`, or when using structs, their convenience methods.\n\n```tolk title=\"Tolk\"\nfun touch<T>(y: T): void asm \"NOP\" // so that the compiler doesn't remove instructions\n\nfun onInternalMessage() {\n    // Too many bits\n    try {\n        val data = beginCell()\n            .storeInt(0, 250)\n            .storeInt(0, 250)\n            .storeInt(0, 250)\n            .storeInt(0, 250)\n            .storeInt(0, 24) // 1024 bits!\n            .toCell();\n        touch(data);\n    } catch (exitCode) {\n        // exitCode is 8\n        assert (exitCode == 8) throw 1111;\n    }\n\n    // Too many refs\n    try {\n        val data = beginCell()\n            .storeRef(beginCell().endCell())\n            .storeRef(beginCell().endCell())\n            .storeRef(beginCell().endCell())\n            .storeRef(beginCell().endCell())\n            .storeRef(beginCell().endCell()) // 5 refs!\n            .toCell();\n        touch(data);\n    } catch (exitCode) {\n        // exitCode is 8\n        assert (exitCode == 8) throw 1111;\n    }\n}\n```\n\n### 9: Cell underflow\n\nTo parse a `cell`, a `slice` primitive is used. If you try to load more data or references than a `slice` contains, an error with exit code 9 is thrown: `Cell underflow`.\n\nThe most common cause of this error is a mismatch between the expected and actual memory layouts of the cells, so it's recommended to use Tolk structs for parsing the cells instead of manual parsing via relevant methods, such as `loadInt()`.\n\n```tolk title=\"Tolk\"\nfun touch<T>(y: T): void asm \"NOP\" // so that the compiler doesn't remove instructions\n\nfun onInternalMessage() {\n    // Too few bits\n    try {\n        touch(beginCell().endCell().beginParse().loadInt(1)); // 0 bits!\n    } catch (exitCode) {\n        // exitCode is 9\n        assert (exitCode == 9) throw 1111;\n    }\n\n    // Too few refs\n    try {\n        touch(beginCell().endCell().beginParse().loadRef()); // 0 refs!\n    } catch (exitCode) {\n        // exitCode is 9\n        assert (exitCode == 9) throw 1111;\n    }\n}\n```\n\n### 10: Dictionary error\n\nIn Tolk, the `map<K, V>` type is an abstraction over the [\"hash\" map dictionaries of TVM](/languages/func/dictionaries).\n\nIf there is incorrect manipulation of dictionaries, such as improper assumptions about their memory layout, an error with exit code 10 is thrown: `Dictionary error`. Note that Tolk prevents you from getting this error unless you perform [TVM assembly](/languages/fift/fift-and-tvm-assembly) work yourself:\n\n```tolk title=\"Tolk\"\nimport \"@stdlib/tvm-dicts\";\n\nfun touch<T>(y: T): void asm \"NOP\" // so that the compiler doesn't remove instructions\nfun cast<T, U>(y: T): U asm \"NOP\"\nfun cell?.addIntToIDict(mutate self, key: int, number: int): void {\n    return self.iDictSetBuilder(32, key, beginCell().storeInt(number, 32));\n}\n\nfun onInternalMessage() {\n    var dict = createEmptyDict();\n    dict.addIntToIDict(0, 0);\n    dict.addIntToIDict(1, 1);\n\n    // The Int to Int dictionary is being misinterpreted as a map<int32, cell>\n    val m: map<int32, cell> = cast(dict);\n\n    try {\n        // And the error happens only when we touch it\n        touch(m.get(0).isFound);\n    } catch (exitCode) {\n        // exitCode is 10\n        assert (exitCode == 10) throw 1111;\n    }\n}\n```\n\n### 11: \"Unknown\" error\n\nDescribed in the [TVM][tvm] docs as \"Unknown error, may be thrown by user programs,\" although most commonly used for problems with queuing a message send or problems with getters.\n\nIn particular, if you try to send an ill-formed message on-chain or to call a non-existent getter function off-chain, an exit code 11 will be thrown.\n\n```tolk title=\"Tolk\"\nfun sendMessage(msg: cell, mode: int): void asm \"SENDMSG\"\n\nfun onInternalMessage() {\n    try {\n        // fails in the Compute phase when the message is ill-formed\n        sendMessage(beginCell().endCell(), 0);\n    } catch (exitCode) {\n        // exitCode is 11\n        assert (exitCode == 11) throw 1111;\n    }\n}\n```\n\n### 12: Fatal error\n\nFatal error. Thrown by TVM in situations deemed impossible.\n\n### 13: Out of gas error\n\nIf there isn't enough gas to complete computations in the [compute phase](#compute), an error with exit code 13 is thrown: `Out of gas error`.\n\nHowever, this code isn't immediately shown as is — instead, the bitwise NOT operation is applied, changing the value from 13 to -14. Only then is the code displayed.\n\nThis is done to prevent the resulting code (-14) from being produced artificially in user contracts, as all functions that can throw an exit code can only specify integers in the range from 0 to 65535 inclusive.\n\n```tolk title=\"Tolk\"\nimport \"@stdlib/gas-payments\";\n\nfun onInternalMessage() {\n    setGasLimit(100);\n}\n```\n\n### -14: Out of gas error\n\nSee [exit code 13](#13%3A-out-of-gas-error).\n\n### 14: Virtualization error\n\nVirtualization error related to pruned branch cells. Reserved but never thrown.\n\n## Action phase\n\nThe [action phase][a] is processed after the successful execution of the [compute phase](#compute). It attempts to perform the actions stored in the action list by [TVM][tvm] during the compute phase.\n\nSome actions may fail during processing, in which case those actions may be skipped or the whole transaction may revert, depending on the mode of actions. The code indicating the resulting state of the [action phase][a] is called a _result code_. Since it is also a 32-bit signed integer that essentially serves the same purpose as the _exit code_ of the [compute phase](#compute), it is common to call the result code an exit code as well.\n\n### 32: Action list is invalid\n\nIf the list of actions contains exotic cells, an action entry cell does not have references, or some action entry cell cannot be parsed, an error with exit code 32 is thrown: `Action list is invalid`.\n\n<Aside>\n  Aside from this exit code, there is a boolean flag `valid`, which you can find under `description.actionPhase.valid` in the transaction results when working with [Sandbox and Blueprint](#blueprint). A transaction can set this flag to `false` even when there is some other exit code thrown from the action phase.\n</Aside>\n\n### 33: Action list is too long\n\nIf there are more than 255 actions queued for execution, the [action phase](#action) will throw an error with an exit code 33: `Action list is too long`.\n\n```tolk title=\"Tolk\"\nimport \"@stdlib/gas-payments\";\n\nfun onInternalMessage() {\n    // For example, let's attempt to queue the reservation of a specific amount of nanoToncoins\n    // This won't fail in the compute phase, but will result in exit code 33 in the action phase\n    repeat (256) {\n        reserveToncoinsOnBalance(1000000, RESERVE_MODE_AT_MOST);\n    }\n}\n```\n\n### 34: Invalid or unsupported action\n\nThere are only four supported actions at the moment: changing the contract code, sending a message, reserving a specific amount of nanoToncoin, and changing the library cell. If there is any issue with the specified action (invalid message, unsupported action, etc.), an error with exit code 34 is thrown: `Invalid or unsupported action`.\n\n```tolk title=\"Tolk\"\nfun onInternalMessage() {\n    // For example, let's try to send an ill-formed message:\n    // won't fail in the compute phase, but will result in exit code 34 in the Action phase\n    sendRawMessage(beginCell().endCell(), 0);\n}\n```\n\n### 35: Invalid source address in outbound message\n\nIf the source address in the outbound message is not equal to `addr_none` or to the address of the contract that initiated this message, an error with exit code 35 is thrown: `Invalid source address in outbound message`.\n\n### 36: Invalid destination address in outbound message\n\nIf the destination address in the outbound message is invalid, e.g., it does not conform to the relevant [TL-B][tlb] schemas, contains an unknown workchain ID, or has an invalid length for the given workchain, an error with exit code 36 is thrown: `Invalid destination address in outbound message`.\n\n<Aside>\n  If the optional `mode` flag +2 is set, this error won't be thrown, and the given message won't be sent.\n</Aside>\n\n### 37: Not enough Toncoin\n\nIf all funds of the inbound message with base `mode` 64 set have already been consumed and there are not enough funds to pay for the failed action, or the [TL-B][tlb] layout of the provided value (`CurrencyCollection`) is invalid, or there are not enough funds to pay forward fees or not enough funds after deducting fees, an error with exit code 37 is thrown: `Not enough Toncoin`.\n\n<Aside>\n  If the optional `mode` flag +2 is set, this error won't be thrown, and the given message won't be sent.\n</Aside>\n\n### 38: Not enough extra currencies\n\nBesides the native currency, Toncoin, TON Blockchain supports up to $2^{32}$ extra currencies. They differ from creating new Jettons because extra currencies are natively supported — one can potentially just specify an additional `HashmapE` of extra currency amounts in addition to the Toncoin amount in the internal message to another contract. Unlike Jettons, extra currencies can only be stored and transferred and do not have any other functionality.\n\nWhen there is not enough extra currency to send the specified amount, an exit code 38 is thrown: `Not enough extra currencies`.\n\n### 39: Outbound message does not fit into cell\n\nWhen processing the message, TON Blockchain tries to pack it according to the relevant TL-B schemas, and if it cannot, an error with exit code 39 is thrown: `Outbound message doesn't fit into a cell`.\n\n<Aside>\n  If attempts at sending the message fail multiple times and the optional `mode` flag +2 is set, this error won't be thrown, and the given message won't be sent.\n</Aside>\n\n### 40: Cannot process message\n\nIf there are not enough funds to process all the cells in a message, the message is too large, or its Merkle depth is too big, an error with exit code 40 is thrown: `Cannot process a message`.\n\n<Aside>\n  If the optional `mode` flag +2 is set, this error won't be thrown, and the given message won't be sent.\n</Aside>\n\n### 41: Library reference is null\n\nIf a library reference is required during a library change action but is null, an error with exit code 41 is thrown: `Library reference is null`.\n\n### 42: Library change action error\n\nIf there's an error during an attempt at a library change action, an error with exit code 42 is thrown: `Library change action error`.\n\n### 43: Library limits exceeded\n\nIf the maximum number of cells in the library is exceeded or the maximum depth of the Merkle tree is exceeded, an error with exit code 43 is thrown: `Library limits exceeded`.\n\n### 50: Account state size exceeded limits\n\nIf the account state (contract storage, essentially) exceeds any of the limits specified in [config param 43 of TON Blockchain](/foundations/config#param-43) by the end of the [action phase](#action), an error with exit code 50 is thrown: `Account state size exceeded limits`.\n\nIf the configuration is absent, the default values are:\n\n- `max_msg_bits` is equal to $2^{21}$ — maximum message size in bits.\n- `max_msg_cells` is equal to $2^{13}$ — maximum number of cells a message can occupy.\n- `max_library_cells` is equal to 1000 — maximum number of cells that can be used as library reference cells.\n- `max_vm_data_depth` is equal to $2^{9}$ — maximum cells depth in messages and account state.\n- `ext_msg_limits.max_size` is equal to 65535 — maximum external message size in bits.\n- `ext_msg_limits.max_depth` is equal to $2^{9}$ — maximum external message depth.\n- `max_acc_state_cells` is equal to $2^{16}$ — maximum number of cells that an account state can occupy.\n- `max_acc_state_bits` is equal to $2^{16} \\times 1023$ — maximum account state size in bits.\n- `max_acc_public_libraries` is equal to $2^{8}$ — maximum number of library reference cells that an account state can use on the masterchain.\n- `defer_out_queue_size_limit` is equal to $2^{8}$ — maximum number of outbound messages to be queued (regarding validators and collators).\n\n{/* NOTE: Reserved a section until Tolk introduces any custom exit codes.\n\n  ## Tolk compiler\n\n  Tolk utilizes exit codes from 128 to 255. Note that exit codes used by Tolk indicate contract errors which can occur when using Tolk-generated code and are therefore thrown in the transaction's [compute phase](#compute), not during compilation.\n  */}\n\n[tlb]: /languages/tl-b/overview\n[tvm]: /tvm/overview\n[bp]: /contract-dev/blueprint/overview\n[sb]: https://github.com/ton-org/sandbox\n[jest]: https://jestjs.io\n"
  },
  {
    "path": "tvm/gas.mdx",
    "content": "---\ntitle: \"Gas\"\n---\n\nEach instruction executed in TVM consumes gas. All instructions consume _basic gas_, which is calculated from the size of the instruction in the bitcode. Some instructions may consume _extra gas_, which is often not fixed but calculated based on the input data.\n\n## Basic gas usage (per bit of executed code)\n\nEach instruction consumes a fixed amount of `10` gas and `1` gas for each bit of this instruction, not including variable-length operands and references.\n\nExamples:\n\n| Instruction                                             | TL-B                                                                                             | Gas  | Notes                                                                                                                                              |\n| ------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ---- | -------------------------------------------------------------------------------------------------------------------------------------------------- |\n| [`NEWC`](/tvm/instructions#c8-newc)                     | `#C8`                                                                                            | `18` | 8-bit prefix without operands                                                                                                                      |\n| [`STU`](/tvm/instructions#cb-stu)                       | `#CB` <br />`cc:uint8`                                                                           | `26` | 8-bit prefix, 8-bit operand                                                                                                                        |\n| [`PUSHINT_LONG`](/tvm/instructions#82-pushint_long)     | `#82` <br />`l:(## 5)` <br />`xxx:(int (8 * l + 19))`                                            | `23` | 8-bit prefix, 5-bit operand, length of `xxx` depends on `l`, so it is not included                                                                 |\n| [`STSLICE_CONST`](/tvm/instructions#cfc0_-stsliceconst) | `#CFC0_` <br />`x:(## 2)` <br />`y:(## 3)` <br />`c:(x * ^Cell)` <br />`sss:((8 * y + 2) * Bit)` | `24` | 9-bit prefix (`CF` is 8 bits, `C0_` is `C_`, which is just bit `1`), 2-bit and 3-bit operands, refs `c` and variable-length `sss` are not included |\n\n## Cell operations\n\nWhen any instruction internally finalizes a `Builder` to a `Cell`, it consumes `500` gas. When a `Cell` is loaded as a `Slice`, it consumes `100` gas for the first access in current smart contract invocation, and `25` gas for each subsequent load from cache. Cells are identified by representation hash, e.g., loading cell with the same hash for the second time will always cost `25` gas.\n\nThis applies to all instructions that internally operate with cells (including dictionary operations). The only exceptions are:\n\n- `BTOS` converts a `Builder` to a `Slice` without consuming gas for cell operations.\n- `HASHBU` computes hash without consuming gas for converting `Builder` to a `Cell`\n\n## Exceptions\n\nTVM consumes `50` gas when any exception is thrown, both explicitly by [`THROW`](/tvm/instructions#f2c4_-throw)-like instructions or implicitly during execution of other instructions. This happens before the jump to the exception handler `c2`.\n\n## Implicit jumps and returns\n\nWhen the current continuation ends and there is a remaining reference, TVM jumps to it and consumes `10` gas. When there are no instructions to execute and references to jump to, implicit return to `c0` occurs, which consumes `5` gas.\n\n## Nested continuations\n\nCalling more than `8` extraordinary continuations in a chain consumes `1` gas for each subsequent continuation.\n\n## Tuple operations\n\n[`TUPLE`](/tvm/instructions#6f0-tuple), [`TUPLEVAR`](/tvm/instructions#6f80-tuplevar), [`UNTUPLE`](/tvm/instructions#6f2-untuple), [`UNTUPLEVAR`](/tvm/instructions#6f82-untuplevar), [`UNPACKFIRST`](/tvm/instructions#6f3-unpackfirst), [`UNPACKFIRSTVAR`](/tvm/instructions#6f83-unpackfirstvar), [`EXPLODE`](/tvm/instructions#6f4-explode), [`EXPLODEVAR`](/tvm/instructions#6f84-explodevar) consumes `1` gas for each entry been pushed or popped into a tuple. [`TPUSH`](/tvm/instructions#6f8c-tpush), [`TPOP`](/tvm/instructions#6f8d-tpop), [`SETINDEX`](/tvm/instructions#6f5-setindex), [`SETINDEXVAR`](/tvm/instructions#6f85-setindexvar), [`SETINDEXQ`](/tvm/instructions#6f7-setindexq)/[`SETINDEXVARQ`](/tvm/instructions#6f87-setindexvarq) consumes `len(tuple)` gas for the resulting tuple size after push/pop/set. Same applies to instructions operating with `c7`: [`SETGLOB`](/tvm/instructions#f87_-setglob)/[`SETGLOBVAR`](/tvm/instructions#f860-setglobvar), [`RANDU256`](/tvm/instructions#f810-randu256)/[`RAND`](/tvm/instructions#f811-rand), [`SETRAND`](/tvm/instructions#f814-setrand), [`ADDRAND`](/tvm/instructions#f815-addrand).\n\n## Stack operations\n\nTVM consumes 1 gas for each stack element deeper than 32 elements inside the resulting new stack each time stack gets copied: when calling or jumping to a continuation with a non-empty argument number, an initial stack, or both, when extending a continuation stack using [`SETCONTARGS`](/tvm/instructions#ec-setcontargs_n) and similar instructions, when using [`RUNVM`](/tvm/instructions#db4-runvm) (both for initial and resulting stacks of the vm).\n\n## Extra currency\n\nThe first `5` executions of `GETEXTRABALANCE` consume at most `26 + 200` gas each. The subsequent executions incur the full gas cost of `26` (normal instruction cost) plus gas for loading cells (up to `3300` if the dictionary has maximum depth).\n\n## RUNVM\n\n[`RUNVM`](/tvm/instructions#db4-runvm) and [`RUNVMX`](/tvm/instructions#db50-runvmx) consume `40` extra gas before starting a VM.\n\n## Cryptography\n\n### CHKSIGNS/CHKSIGNU\n\n[`CHKSIGNS`](/tvm/instructions#f911-chksigns) and [`CHKSIGNU`](/tvm/instructions#f910-chksignu) can be invoked `10` times without extra gas cost. Next checks will cost `4000` gas each.\n\n### HASHEXT\n\n`HASHEXT*` instructions always consume `1` extra gas for each part of the input. Additionally, the following gas is consumed for each hashed byte:\n\n| Algorithm | Gas consumed  |\n| --------- | ------------- |\n| SHA256    | 1/33 per byte |\n| SHA512    | 1/16 per byte |\n| BLAKE2B   | 1/19 per byte |\n| KECCAK256 | 1/11 per byte |\n| KECCAK512 | 1/6 per byte  |\n\nOnly the integer part of the gas is consumed; for example, 0-32 bytes of SHA256 cost 0 gas, 33-64 bytes cost 1 gas, and so on.\n\n### RIST255\n\nInstructions consume constant extra gas.\n\n| Instruction                                                   | Extra gas |\n| ------------------------------------------------------------- | --------- |\n| [`RIST255_FROMHASH`](/tvm/instructions#f920-rist255_fromhash) | 600       |\n| [`RIST255_VALIDATE`](/tvm/instructions#f921-rist255_validate) | 200       |\n| [`RIST255_ADD`](/tvm/instructions#f922-rist255_add)           | 600       |\n| [`RIST255_MUL`](/tvm/instructions#f924-rist255_mul)           | 2000      |\n| [`RIST255_MULBASE`](/tvm/instructions#f925-rist255_mulbase)   | 750       |\n\n### Other instructions\n\n[`ECRECOVER`](/tvm/instructions#f912-ecrecover) consumes 1500 extra gas.\n\n`SECP256K1_XONLY_PUBKEY_TWEAK_ADD` consumes 1250 extra gas.\n\n[`P256_CHKSIGNU`](/tvm/instructions#f914-p256_chksignu) and [`P256_CHKSIGNS`](/tvm/instructions#f915-p256_chksigns) consume 3500 extra gas.\n\n### BLS\n\n#### Signature verification and aggregation\n\n| Instruction                                                                   | Gas consumed        | Notes                                                                             |\n| ----------------------------------------------------------------------------- | ------------------- | --------------------------------------------------------------------------------- |\n| [`BLS_VERIFY`](/tvm/instructions#f93000-bls_verify)                           | `61000`             |                                                                                   |\n| [`BLS_AGGREGATE`](/tvm/instructions#f93001-bls_aggregate)                     | `-2650 + 4350 * n`  | `n` is the number of signatures aggregated.                                       |\n| [`BLS_FASTAGGREGATEVERIFY`](/tvm/instructions#f93002-bls_fastaggregateverify) | `58000 + 3000 * n`  | `n` is the number of public keys verified against one message/signature pair.     |\n| [`BLS_AGGREGATEVERIFY`](/tvm/instructions#f93003-bls_aggregateverify)         | `38500 + 22500 * n` | `n` is the number of `(public key, message)` pairs checked against one signature. |\n\n#### G1 group helpers\n\n| Instruction                                                                                               | Gas consumed |\n| --------------------------------------------------------------------------------------------------------- | ------------ |\n| [`BLS_G1_ADD`](/tvm/instructions#f93010-bls_g1_add) / [`BLS_G1_SUB`](/tvm/instructions#f93011-bls_g1_sub) | `3900`       |\n| [`BLS_G1_NEG`](/tvm/instructions#f93012-bls_g1_neg)                                                       | `750`        |\n| [`BLS_G1_MUL`](/tvm/instructions#f93013-bls_g1_mul)                                                       | `5200`       |\n| [`BLS_MAP_TO_G1`](/tvm/instructions#f93016-bls_map_to_g1)                                                 | `2350`       |\n| [`BLS_G1_INGROUP`](/tvm/instructions#f93017-bls_g1_ingroup)                                               | `2950`       |\n\n[`BLS_G1_MULTIEXP`](/tvm/instructions#f93014-bls_g1_multiexp) consumes `11375 + 630 * n + (8820 * n) / max(log₂ n, 4)` extra gas, where `n` is the number of `(point, scalar)` pairs.\n\nInstructions [`BLS_G1_ZERO`](/tvm/instructions#f93015-bls_g1_zero) and [`BLS_G1_ISZERO`](/tvm/instructions#f93018-bls_g1_iszero) do not charge additional gas.\n\n#### G2 group helpers\n\n| Instruction                                                                                               | Gas consumed |\n| --------------------------------------------------------------------------------------------------------- | ------------ |\n| [`BLS_G2_ADD`](/tvm/instructions#f93020-bls_g2_add) / [`BLS_G2_SUB`](/tvm/instructions#f93021-bls_g2_sub) | `6100`       |\n| [`BLS_G2_NEG`](/tvm/instructions#f93022-bls_g2_neg)                                                       | `1550`       |\n| [`BLS_G2_MUL`](/tvm/instructions#f93023-bls_g2_mul)                                                       | `10550`      |\n| [`BLS_MAP_TO_G2`](/tvm/instructions#f93026-bls_map_to_g2)                                                 | `7950`       |\n| [`BLS_G2_INGROUP`](/tvm/instructions#f93027-bls_g2_ingroup)                                               | `4250`       |\n\n[`BLS_G2_MULTIEXP`](/tvm/instructions#f93024-bls_g2_multiexp) consumes `30388 + 1280 * n + (22840 * n) / max(log₂ n, 4)` gas, where `n` is the number of `(point, scalar)` pairs.\n\nInstructions [`BLS_G2_ZERO`](/tvm/instructions#f93025-bls_g2_zero) and [`BLS_G2_ISZERO`](/tvm/instructions#f93028-bls_g2_iszero) do not charge additional gas.\n\n#### Pairing and constants\n\n| Instruction                                           | Gas consumed        | Notes                                                                         |\n| ----------------------------------------------------- | ------------------- | ----------------------------------------------------------------------------- |\n| [`BLS_PAIRING`](/tvm/instructions#f93030-bls_pairing) | `20000 + 11800 * n` | `n` is the number of `(G1, G2)` pairs supplied for the pairing product check. |\n\n[`BLS_PUSHR`](/tvm/instructions#f93031-bls_pushr) do not charge additional gas.\n\n## `GasLimits` structure\n\nTVM has inner structure `GasLimits` for gas manipulations. Its fields are:\n\n- `gas_max`: the equivalent of contract's balance at the start of the compute phase in gas units.\n- `gas_limit`: the amount of gas that can be consumed during the virtual machine execution. At the start of the execution, it equals:\n  - minimum of `gas_max` and the amount of gas that can be bought with the incoming message value (i.e., the amount of TON coins attached to the message) in the case of an internal message;\n  - `0` in the case of an external message.\n- `gas_credit`: the amount of free gas that can be spent during the execution before accepting an external message. At the start of the execution, it equals:\n  - minimum of `gas_max` and corresponding value in configuration parameter `20` for masterchain and `21` for basechain in the case of an external message;\n  - `0` in the case of an internal message.\n- `gas_remaining`: the amount of available but not spent gas. At the start of the execution, it equals `gas_limit + gas_credit`. It decreases after each instruction execution by the amount of gas consumed by the instruction.\n- `gas_base`: an auxiliary parameter that is necessary for rebasing and shows the initial value of `gas_remaining`. At the start of the execution, it equals `gas_remaining`.\n\nInstructions `SETGASLIMIT` and `ACCEPT` change all above values except `gas_max`:\n\n- `SETGASLIMIT` sets `gas_limit` to the minimum of the indicated value and `gas_max`, `gas_credit` to zero, `gas_base` to the new `gas_limit`, and `gas_remaining` to `gas_remaining + (new gas_base - old gas_base)`.\n- `ACCEPT` is equivalent to `SETGASLIMIT` with the new gas limit equal to `2**63 - 1` (the maximum value of a signed 64-bits integer).\n\nThe final value (in gas units) that will be deducted from contract's balance after the execution is `gas_base - gas_remaining`. Note that this value will be deducted if and only if after the execution `gas_credit` is zero, i.e. if `SETGASLIMIT` or `ACCEPT` was called at least once during the execution in the case of incoming external message. Without condition `gas_credit == 0`, there will be no commit of the new code and data.\n"
  },
  {
    "path": "tvm/get-method.mdx",
    "content": "---\ntitle: \"Get methods\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nGet methods are smart contract methods that are supposed to be executed off-chain. They are useful for structured retrieval of data from a smart contract ([`get_collection_data` get-method on an NFT collection](/standard/tokens/nft/reference#return-collection-data)), and for any logic that is a part of a smart contract but is needed off-chain ([`get_nft_address_by_index` get-method on an NFT collection](/standard/tokens/nft/reference#return-item-address-by-index)). Under the hood of APIs, this happens by fetching the actual state of the smart contract from the blockchain and executing TVM to get the result. This process is purely read-only and does not modify the blockchain state in any way.\n\n## Defining\n\nGet methods are processed by the [function selector](/tvm/registers#c3-%E2%80%94-function-selector). By convention, the ID of a get method is calculated as `crc16(\"name\") | 0x10000` where `name` is set by the developer. This simplifies practical usage because a human-readable name has to be used instead of some arbitrary number.\n\n<Aside type=\"note\">\n  The algorithm used for hashing is CRC‑16/XMODEM (`poly=0x1021`, `init=0x0000`, `refin=false`, `refout=false`, `xorout=0x0000`).\n</Aside>\n\nA minimal example of a smart contract that has a get method that follows the ID convention:\n\n```fift\n\"Asm.fif\" include\n\n<{\n  // The ID from the top of the stack is compared with 97865\n  97865 EQINT\n  // If ID != 97865, an 11 error is thrown by convention\n  11 THROWIFNOT\n  // Otherwise, 123 is pushed as the result\n  123 PUSHINT\n}>s\n```\n\nBut in practice, it is easier to use `PROGRAM{` from the Fift assembler that handles function selector logic.\n\n```fift\n\"Asm.fif\" include\n\nPROGRAM{\n  DECLPROC main\n  // crc16(\"get_x\") | 0x10000 = 97865\n  97865 DECLMETHOD get_x\n  main PROC:<{\n  }>\n  get_x PROC:<{\n    123 PUSHINT\n  }>\n}END>s\n```\n\nThe above is equivalent to the following Tolk code, which compiles to almost identical Fift code.\n\n```tolk title=\"Tolk\"\nfun main() { }\n\nget fun get_x(): int {\n    return 123;\n}\n```\n\n## Executing\n\nIn order to execute a get method, the actual state of the smart contract has to be fetched, and TVM has to be executed with [c7](/tvm/registers#c7-%E2%80%94-environment-information-and-global-variables) initialized and the desired parameters pushed on the stack.\n\n### Local way\n\nWith all the required values known, it is possible to execute a get method completely locally. A minimal example that uses a placeholder c7 for simplicity, as it is only necessary when the get method uses data from it during execution:\n\n```fift\n\"Asm.fif\" include\n\n// example code\n// could also be defined as a constant cell without using assembly\nPROGRAM{\n  DECLPROC main\n  97865 DECLMETHOD get_x\n  main PROC:<{\n  }>\n  get_x PROC:<{\n    123 PUSHINT\n  }>\n}END>s constant code\n\n// example data\n// empty in this case\n<b b> constant data\n\n// example c7\n// placeholder for simplicity\n0 tuple 0x076ef1ea , 1 tuple constant c7\n\n// execute method 97865\n97865 code data c7 runvmctx .s\n// result: 123 0 C{96A296D224F285C67BEE93C30F8A309157F0DAA35DC5B87E410B78630A09CFC7}\n// where:\n// 123 is the value returned by the get method\n// 0 is the exit code\n// C{...} is a new data cell\n```\n\nNote that if the get method uses some values from c7, for example with instructions such as `NOW` or `MYCODE`, the c7 tuple should be populated according to its [structure](/tvm/registers#c7-%E2%80%94-environment-information-and-global-variables).\n\n### Decentralized way\n\nThe process of fetching the actual contract state and initializing c7 can be handled by [liteserver](/ecosystem/nodes/overview) for easier execution. To execute a get method via liteserver, the request follows the [`liteServer.runSmcMethod` TL schema](https://github.com/ton-blockchain/ton/blob/f58297f1b668c7b49e8b30b65062951ca7c18acc/tl/generate/scheme/lite_api.tl#L90).\n\nIn that request, `params:bytes` is a [BoC](/foundations/serialization/boc) of a serialized [`VmStack`](https://github.com/ton-blockchain/ton/blob/f58297f1b668c7b49e8b30b65062951ca7c18acc/crypto/block/block.tlb#L891) object containing the stack with arguments.\n\nThe response follows the [liteServer.runMethodResult TL schema](https://github.com/ton-blockchain/ton/blob/f58297f1b668c7b49e8b30b65062951ca7c18acc/tl/generate/scheme/lite_api.tl#L39). Apart from the values used for initialization and proofs, the result is included as `result:mode.2?bytes`, which is a BoC of a serialized `VmStack` object, similarly to the request.\n\nAn example execution via liteclient that handles serialization:\n\n```text\nrunmethod UQBKgXCNLPexWhs2L79kiARR1phGH1LwXxRbNsCFF9doczSI get_public_key\n```\n\nResult:\n\n```text\narguments:  [ 78748 ]\nresult:  [ 37001869727465363790964079650574219024351072622925678701060821828351030750605 ]\n```\n\n### High-level API\n\nThe easiest path is using a high-level API, such as [TON Center](/ecosystem/api/toncenter/introduction). It has a [`/api/v3/runGetMethod`](/ecosystem/api/toncenter/v3/apiv2/run-get-method) endpoint that takes a smart contract address, a get method name, and arguments and returns the resulting stack. Example usage:\n\n```bash\ncurl -X 'POST' \\\n  'https://toncenter.com/api/v3/runGetMethod' \\\n  -H 'accept: application/json' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n  \"address\": \"EQBG-g6ahkAUGWpefWbx-D_9sQ8oWbvy6puuq78U2c4NUDFS\",\n  \"method\": \"get_nft_address_by_index\",\n  \"stack\": [\n    {\n      \"type\": \"num\",\n      \"value\": \"123\"\n    }\n  ]\n}'\n```\n\nThe result for this call is presented below. The stack in this case contains a single cell element in BoC format.\n\n```text\n{\n  \"gas_used\": 4049,\n  \"exit_code\": 0,\n  \"stack\": [\n    {\n      \"type\": \"cell\",\n      \"value\": \"te6cckEBAQEAJAAAQ4AVoN3BhVDLKet4AYoVxOHz8WkaFncQfg/M79YWJEV4pxDg5fQi\"\n    }\n  ]\n}\n```\n"
  },
  {
    "path": "tvm/initialization.mdx",
    "content": "---\ntitle: \"Initialization\"\ndescription: \"State of TVM before smart contract execution\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\n## Initialization of `cc`, `cp`, and gas limits\n\n- The original `cc`, current continuation, is initialized using the cell slice created from the `code` section of the smart contract. If the account is frozen or uninitialized, the code must be provided in the `init` field of the incoming message.\n\n- The `cp`, current TVM codepage, is set to the default value of 0.\n\n- The gas limit values are initialized based on the results of the [credit phase](/foundations/phases).\n\n## Registers initialization\n\n<Aside type=\"tip\">\n  For more info about registers, take a look at [Registers](/tvm/registers)\n</Aside>\n\n- `c0`: `Quit` — extraordinary continuation which terminates TVM with exit code `0`.\n\n- `c1`: `Quit` — extraordinary continuation which terminates TVM with exit code `1`. Both exit codes `0` and `1` are considered successful terminations of TVM.\n\n- `c2`: `ExcQuit` — extraordinary continuation which terminates TVM with an exception. In this case, the exit code is an exception number.\n\n- `c3`: root cell of code currently executing in TVM.\n\n- `c4`: root cell of account data.\n\n- `c5`: empty cell.\n\n- `c7`: `Tuple[Tuple[0x076ef1ea, 0, 0, ...]]`.\n\n## Stack\n\nThe contents of the stack depend on the event that triggered the transaction:\n\n- Internal message\n- External message\n- Tick-tock\n- Split prepare\n- Merge install\n- [Get method (off-chain)](/tvm/get-method)\n\nThe top of the stack is always the _function selector_, an _integer_ that identifies the event that caused the transaction.\n\nThe following function selectors are defined:\n\n| ID | Name              | Description                                        |\n| -- | ----------------- | -------------------------------------------------- |\n| 0  | onInternalMessage | Received an internal message                       |\n| -1 | onExternalMessage | Received an external message                       |\n| -2 | onRunTickTock     | Received a tick-tock event                         |\n| -3 | onSplitPrepare    | Received a split prepare event (unimplemented yet) |\n| -4 | onSplitInstall    | Received a split install event (unimplemented yet) |\n\nGet methods can have arbitrary IDs and should not overlap with the ones listed above.\n\n### External/internal message\n\n| Index | Name              | Type      | Description                                                                                                                                                   |\n| ----- | ----------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `s0`  | Function selector | `Integer` | `-1` for external messages, `0` for internal messages.                                                                                                        |\n| `s1`  | Message body      | `Slice`   | This is an arbitrary payload of a message, which can be used for text comments (when sending TONs from one wallet to another) or for smart contract commands. |\n| `s2`  | Message           | `Cell`    | Cell containing message metadata (sender, receiver, amount) as well as message body.                                                                          |\n| `s3`  | Message value     | `Integer` | Amount of received nanotons (`0` for externals).                                                                                                              |\n| `s4`  | Contract balance  | `Integer` | Current account balance in nanotons.                                                                                                                          |\n\n### Tick‑tock\n\n| Index | Name              | Type    | Description                                            |\n| ----- | ----------------- | ------- | ------------------------------------------------------ |\n| `s0`  | Function selector | Integer | `-2` for tick-tock transactions.                       |\n| `s1`  | Tick or tock?     | Integer | `0` for tick transactions, `-1` for tock transactions. |\n| `s2`  | Account address   | Integer | 256-bit raw account address (without workchain).       |\n| `s3`  | Contract          | Integer | Current account balance in nanotons.                   |\n\n### Split/merge events\n\nThese events are not implemented yet. Possible stack layout for split/merge events is described in [TON Blockchain](/foundations/whitepapers/tblkch#4-4-8-processing-split-prepare-transactions) whitepaper. However, it is subject to change.\n"
  },
  {
    "path": "tvm/instructions.mdx",
    "content": "---\ntitle: \"Instructions\"\ndescription: \"Interactive reference for TVM instructions\"\nmode: \"wide\"\n---\nimport { TvmInstructionTable } from \"/snippets/tvm-instruction-table.jsx\"\n\n<TvmInstructionTable />\n\n{/* STATIC_START tvm_instructions */}\n<div hidden>\n#### `00` NOP\n\nDoes nothing.<br />\n**Category:** Stack Basic (stack_basic)<br />\n\n```fift Fift\nNOP\n```\n\n#### `0i` XCHG_0I\n\nInterchanges `s0` with `s[i]`, `1 <= i <= 15`.<br />\n**Category:** Stack Basic (stack_basic)<br />\n\n```fift Fift\ns[i] XCHG0\n```\n\n**Aliases**:\n- `SWAP`<br />\n  Same as `s1 XCHG0`.\n\n#### `10ij` XCHG_IJ\n\nInterchanges `s[i]` with `s[j]`, `1 <= i < j <= 15`.<br />\n**Category:** Stack Basic (stack_basic)<br />\n\n```fift Fift\ns[i] s[j] XCHG\n```\n\n#### `11ii` XCHG_0I_LONG\n\nInterchanges `s0` with `s[ii]`, `0 <= ii <= 255`.<br />\n**Category:** Stack Basic (stack_basic)<br />\n\n```fift Fift\ns0 [ii] s() XCHG\n```\n\n#### `1i` XCHG_1I\n\nInterchanges `s1` with `s[i]`, `2 <= i <= 15`.<br />\n**Category:** Stack Basic (stack_basic)<br />\n\n```fift Fift\ns1 s[i] XCHG\n```\n\n#### `2i` PUSH\n\nPushes a copy of the old `s[i]` into the stack.<br />\n**Category:** Stack Basic (stack_basic)<br />\n\n```fift Fift\ns[i] PUSH\n```\n\n**Aliases**:\n- `DUP`<br />\n  Same as `s0 PUSH`.\n- `OVER`<br />\n  Same as `s1 PUSH`.\n\n#### `3i` POP\n\nPops the old `s0` value into the old `s[i]`.<br />\n**Category:** Stack Basic (stack_basic)<br />\n\n```fift Fift\ns[i] POP\n```\n\n**Aliases**:\n- `DROP`<br />\n  Same as `s0 POP`, discards the top-of-stack value.\n- `NIP`<br />\n  Same as `s1 POP`.\n\n#### `4ijk` XCHG3\n\nEquivalent to `s2 s[i] XCHG` `s1 s[j] XCHG` `s[k] XCHG0`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\ns[i] s[j] s[k] XCHG3\n```\n\n#### `50ij` XCHG2\n\nEquivalent to `s1 s[i] XCHG` `s[j] XCHG0`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\ns[i] s[j] XCHG2\n```\n\n#### `51ij` XCPU\n\nEquivalent to `s[i] XCHG0` `s[j] PUSH`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\ns[i] s[j] XCPU\n```\n\n#### `52ij` PUXC\n\nEquivalent to `s[i] PUSH` `SWAP` `s[j] XCHG0`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\ns[i] s[j-1] PUXC\n```\n\n#### `53ij` PUSH2\n\nEquivalent to `s[i] PUSH` `s[j+1] PUSH`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\ns[i] s[j] PUSH2\n```\n\n#### `540ijk` XCHG3_ALT\n\nLong form of `XCHG3`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\ns[i] s[j] s[k] XCHG3_l\n```\n\n#### `541ijk` XC2PU\n\nEquivalent to `s[i] s[j] XCHG2` `s[k] PUSH`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\ns[i] s[j] s[k] XC2PU\n```\n\n#### `542ijk` XCPUXC\n\nEquivalent to `s1 s[i] XCHG` `s[j] s[k-1] PUXC`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\ns[i] s[j] s[k-1] XCPUXC\n```\n\n#### `543ijk` XCPU2\n\nEquivalent to `s[i] XCHG0` `s[j] s[k] PUSH2`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\ns[i] s[j] s[k] XCPU2\n```\n\n#### `544ijk` PUXC2\n\nEquivalent to `s[i] PUSH` `s2 XCHG0` `s[j] s[k] XCHG2`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\ns[i] s[j-1] s[k-1] PUXC2\n```\n\n#### `545ijk` PUXCPU\n\nEquivalent to `s[i] s[j-1] PUXC` `s[k] PUSH`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\ns[i] s[j-1] s[k-1] PUXCPU\n```\n\n#### `546ijk` PU2XC\n\nEquivalent to `s[i] PUSH` `SWAP` `s[j] s[k-1] PUXC`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\ns[i] s[j-1] s[k-2] PU2XC\n```\n\n#### `547ijk` PUSH3\n\nEquivalent to `s[i] PUSH` `s[j+1] s[k+1] PUSH2`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\ns[i] s[j] s[k] PUSH3\n```\n\n#### `55ij` BLKSWAP\n\nPermutes two blocks `s[j+i+1] ... s[j+1]` and `s[j] ... s0`.<br />`0 <= i,j <= 15`<br />Equivalent to `[i+1] [j+1] REVERSE` `[j+1] 0 REVERSE` `[i+j+2] 0 REVERSE`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\n[i+1] [j+1] BLKSWAP\n```\n\n**Aliases**:\n- `ROT2`<br />\n  Rotates the three topmost pairs of stack entries.\n- `ROLL`<br />\n  Rotates the top `i+1` stack entries.<br />Equivalent to `1 [i+1] BLKSWAP`.\n- `ROLLREV`<br />\n  Rotates the top `i+1` stack entries in the other direction.<br />Equivalent to `[i+1] 1 BLKSWAP`.\n\n#### `56ii` PUSH_LONG\n\nPushes a copy of the old `s[ii]` into the stack.<br />`0 <= ii <= 255`<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\n[ii] s() PUSH\n```\n\n#### `57ii` POP_LONG\n\nPops the old `s0` value into the old `s[ii]`.<br />`0 <= ii <= 255`<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\n[ii] s() POP\n```\n\n#### `58` ROT\n\nEquivalent to `1 2 BLKSWAP` or to `s2 s1 XCHG2`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\nROT\n```\n\n#### `59` ROTREV\n\nEquivalent to `2 1 BLKSWAP` or to `s2 s2 XCHG2`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\nROTREV\n-ROT\n```\n\n#### `5A` SWAP2\n\nEquivalent to `2 2 BLKSWAP` or to `s3 s2 XCHG2`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\nSWAP2\n2SWAP\n```\n\n#### `5B` DROP2\n\nEquivalent to `DROP` `DROP`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\nDROP2\n2DROP\n```\n\n#### `5C` DUP2\n\nEquivalent to `s1 s0 PUSH2`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\nDUP2\n2DUP\n```\n\n#### `5D` OVER2\n\nEquivalent to `s3 s2 PUSH2`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\nOVER2\n2OVER\n```\n\n#### `5Eij` REVERSE\n\nReverses the order of `s[j+i+1] ... s[j]`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\n[i+2] [j] REVERSE\n```\n\n#### `5F0i` BLKDROP\n\nEquivalent to `DROP` performed `i` times.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\n[i] BLKDROP\n```\n\n#### `5Fij` BLKPUSH\n\nEquivalent to `PUSH s(j)` performed `i` times.<br />`1 <= i <= 15`, `0 <= j <= 15`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\n[i] [j] BLKPUSH\n```\n\n#### `60` PICK\n\nPops integer `i` from the stack, then performs `s[i] PUSH`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\nPICK\nPUSHX\n```\n\n#### `61` ROLLX\n\nPops integer `i` from the stack, then performs `1 [i] BLKSWAP`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\nROLLX\n```\n\n#### `62` -ROLLX\n\nPops integer `i` from the stack, then performs `[i] 1 BLKSWAP`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\n-ROLLX\nROLLREVX\n```\n\n#### `63` BLKSWX\n\nPops integers `i`,`j` from the stack, then performs `[i] [j] BLKSWAP`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\nBLKSWX\n```\n\n#### `64` REVX\n\nPops integers `i`,`j` from the stack, then performs `[i] [j] REVERSE`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\nREVX\n```\n\n#### `65` DROPX\n\nPops integer `i` from the stack, then performs `[i] BLKDROP`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\nDROPX\n```\n\n#### `66` TUCK\n\nEquivalent to `SWAP` `OVER` or to `s1 s1 XCPU`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\nTUCK\n```\n\n#### `67` XCHGX\n\nPops integer `i` from the stack, then performs `s[i] XCHG`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\nXCHGX\n```\n\n#### `68` DEPTH\n\nPushes the current depth of the stack.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\nDEPTH\n```\n\n#### `69` CHKDEPTH\n\nPops integer `i` from the stack, then checks whether there are at least `i` elements, generating a stack underflow exception otherwise.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\nCHKDEPTH\n```\n\n#### `6A` ONLYTOPX\n\nPops integer `i` from the stack, then removes all but the top `i` elements.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\nONLYTOPX\n```\n\n#### `6B` ONLYX\n\nPops integer `i` from the stack, then leaves only the bottom `i` elements. Approximately equivalent to `DEPTH` `SWAP` `SUB` `DROPX`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\nONLYX\n```\n\n#### `6Cij` BLKDROP2\n\nDrops `i` stack elements under the top `j` elements.<br />`1 <= i <= 15`, `0 <= j <= 15`<br />Equivalent to `[i+j] 0 REVERSE` `[i] BLKDROP` `[j] 0 REVERSE`.<br />\n**Category:** Stack Complex (stack_complex)<br />\n\n```fift Fift\n[i] [j] BLKDROP2\n```\n\n#### `6D` NULL\n\nPushes the only value of type _Null_.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nNULL\nPUSHNULL\n```\n\n**Aliases**:\n- `NEWDICT`<br />\n  Returns a new empty dictionary.<br />It is an alternative mnemonics for `PUSHNULL`.\n\n#### `6E` ISNULL\n\nChecks whether `x` is a _Null_, and returns `-1` or `0` accordingly.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nISNULL\n```\n\n**Aliases**:\n- `DICTEMPTY`<br />\n  Checks whether dictionary `D` is empty, and returns `-1` or `0` accordingly.<br />It is an alternative mnemonics for `ISNULL`.\n\n#### `6F0n` TUPLE\n\nCreates a new _Tuple_ `t=(x_1, ... ,x_n)` containing `n` values `x_1`,..., `x_n`.<br />`0 <= n <= 15`<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\n[n] TUPLE\n```\n\n**Aliases**:\n- `NIL`<br />\n  Pushes the only _Tuple_ `t=()` of length zero.\n- `SINGLE`<br />\n  Creates a singleton `t:=(x)`, i.e., a _Tuple_ of length one.\n- `PAIR`<br />\n  Creates pair `t:=(x,y)`.\n- `TRIPLE`<br />\n  Creates triple `t:=(x,y,z)`.\n\n#### `6F1k` INDEX\n\nReturns the `k`-th element of a _Tuple_ `t`.<br />`0 <= k <= 15`.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\n[k] INDEX\n```\n\n**Aliases**:\n- `FIRST`<br />\n  Returns the first element of a _Tuple_.\n- `SECOND`<br />\n  Returns the second element of a _Tuple_.\n- `THIRD`<br />\n  Returns the third element of a _Tuple_.\n\n#### `6F2n` UNTUPLE\n\nUnpacks a _Tuple_ `t=(x_1,...,x_n)` of length equal to `0 <= n <= 15`.<br />If `t` is not a _Tuple_, or if `|t| != n`, a type check exception is thrown.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\n[n] UNTUPLE\n```\n\n**Aliases**:\n- `UNSINGLE`<br />\n  Unpacks a singleton `t=(x)`.\n- `UNPAIR`<br />\n  Unpacks a pair `t=(x,y)`.\n- `UNTRIPLE`<br />\n  Unpacks a triple `t=(x,y,z)`.\n\n#### `6F3k` UNPACKFIRST\n\nUnpacks first `0 <= k <= 15` elements of a _Tuple_ `t`.<br />If `|t|<k`, throws a type check exception.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\n[k] UNPACKFIRST\n```\n\n**Aliases**:\n- `CHKTUPLE`<br />\n  Checks whether `t` is a _Tuple_. If not, throws a type check exception.\n\n#### `6F4n` EXPLODE\n\nUnpacks a _Tuple_ `t=(x_1,...,x_m)` and returns its length `m`, but only if `m <= n <= 15`. Otherwise throws a type check exception.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\n[n] EXPLODE\n```\n\n#### `6F5k` SETINDEX\n\nComputes _Tuple_ `t'` that differs from `t` only at position `t'_{k+1}`, which is set to `x`.<br />`0 <= k <= 15`<br />If `k >= |t|`, throws a range check exception.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\n[k] SETINDEX\n```\n\n**Aliases**:\n- `SETFIRST`<br />\n  Sets the first component of _Tuple_ `t` to `x` and returns the resulting _Tuple_ `t'`.\n- `SETSECOND`<br />\n  Sets the second component of _Tuple_ `t` to `x` and returns the resulting _Tuple_ `t'`.\n- `SETTHIRD`<br />\n  Sets the third component of _Tuple_ `t` to `x` and returns the resulting _Tuple_ `t'`.\n\n#### `6F6k` INDEXQ\n\nReturns the `k`-th element of a _Tuple_ `t`, where `0 <= k <= 15`. In other words, returns `x_{k+1}` if `t=(x_1,...,x_n)`. If `k>=n`, or if `t` is _Null_, returns a _Null_ instead of `x`.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\n[k] INDEXQ\n```\n\n**Aliases**:\n- `FIRSTQ`<br />\n  Returns the first element of a _Tuple_.\n- `SECONDQ`<br />\n  Returns the second element of a _Tuple_.\n- `THIRDQ`<br />\n  Returns the third element of a _Tuple_.\n\n#### `6F7k` SETINDEXQ\n\nSets the `k`-th component of _Tuple_ `t` to `x`, where `0 <= k < 16`, and returns the resulting _Tuple_ `t'`.<br />If `|t| <= k`, first extends the original _Tuple_ to length `n'=k+1` by setting all new components to _Null_. If the original value of `t` is _Null_, treats it as an empty _Tuple_. If `t` is not _Null_ or _Tuple_, throws an exception. If `x` is _Null_ and either `|t| <= k` or `t` is _Null_, then always returns `t'=t` (and does not consume tuple creation gas).<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\n[k] SETINDEXQ\n```\n\n**Aliases**:\n- `SETFIRSTQ`<br />\n  Sets the first component of _Tuple_ `t` to `x` and returns the resulting _Tuple_ `t'`.\n- `SETSECONDQ`<br />\n  Sets the second component of _Tuple_ `t` to `x` and returns the resulting _Tuple_ `t'`.\n- `SETTHIRDQ`<br />\n  Sets the third component of _Tuple_ `t` to `x` and returns the resulting _Tuple_ `t'`.\n\n#### `6F80` TUPLEVAR\n\nCreates a new _Tuple_ `t` of length `n` similarly to `TUPLE`, but with `0 <= n <= 255` taken from the stack.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nTUPLEVAR\n```\n\n#### `6F81` INDEXVAR\n\nSimilar to `k INDEX`, but with `0 <= k <= 254` taken from the stack.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nINDEXVAR\n```\n\n#### `6F82` UNTUPLEVAR\n\nSimilar to `n UNTUPLE`, but with `0 <= n <= 255` taken from the stack.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nUNTUPLEVAR\n```\n\n#### `6F83` UNPACKFIRSTVAR\n\nSimilar to `n UNPACKFIRST`, but with `0 <= n <= 255` taken from the stack.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nUNPACKFIRSTVAR\n```\n\n#### `6F84` EXPLODEVAR\n\nSimilar to `n EXPLODE`, but with `0 <= n <= 255` taken from the stack.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nEXPLODEVAR\n```\n\n#### `6F85` SETINDEXVAR\n\nSimilar to `k SETINDEX`, but with `0 <= k <= 254` taken from the stack.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nSETINDEXVAR\n```\n\n#### `6F86` INDEXVARQ\n\nSimilar to `n INDEXQ`, but with `0 <= k <= 254` taken from the stack.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nINDEXVARQ\n```\n\n#### `6F87` SETINDEXVARQ\n\nSimilar to `k SETINDEXQ`, but with `0 <= k <= 254` taken from the stack.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nSETINDEXVARQ\n```\n\n#### `6F88` TLEN\n\nReturns the length of a _Tuple_.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nTLEN\n```\n\n#### `6F89` QTLEN\n\nSimilar to `TLEN`, but returns `-1` if `t` is not a _Tuple_.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nQTLEN\n```\n\n#### `6F8A` ISTUPLE\n\nReturns `-1` or `0` depending on whether `t` is a _Tuple_.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nISTUPLE\n```\n\n#### `6F8B` LAST\n\nReturns the last element of a non-empty _Tuple_ `t`.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nLAST\n```\n\n#### `6F8C` TPUSH\n\nAppends a value `x` to a _Tuple_ `t=(x_1,...,x_n)`, but only if the resulting _Tuple_ `t'=(x_1,...,x_n,x)` is of length at most 255. Otherwise throws a type check exception.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nTPUSH\nCOMMA\n```\n\n#### `6F8D` TPOP\n\nDetaches the last element `x=x_n` from a non-empty _Tuple_ `t=(x_1,...,x_n)`, and returns both the resulting _Tuple_ `t'=(x_1,...,x_{n-1})` and the original last element `x`.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nTPOP\n```\n\n#### `6FA0` NULLSWAPIF\n\nPushes a _Null_ under the topmost _Integer_ `x`, but only if `x!=0`.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nNULLSWAPIF\n```\n\n#### `6FA1` NULLSWAPIFNOT\n\nPushes a _Null_ under the topmost _Integer_ `x`, but only if `x=0`. May be used for stack alignment after quiet primitives such as `PLDUXQ`.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nNULLSWAPIFNOT\n```\n\n#### `6FA2` NULLROTRIF\n\nPushes a _Null_ under the second stack entry from the top, but only if the topmost _Integer_ `y` is non-zero.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nNULLROTRIF\n```\n\n#### `6FA3` NULLROTRIFNOT\n\nPushes a _Null_ under the second stack entry from the top, but only if the topmost _Integer_ `y` is zero. May be used for stack alignment after quiet primitives such as `LDUXQ`.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nNULLROTRIFNOT\n```\n\n#### `6FA4` NULLSWAPIF2\n\nPushes two nulls under the topmost _Integer_ `x`, but only if `x!=0`.<br />Equivalent to `NULLSWAPIF` `NULLSWAPIF`.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nNULLSWAPIF2\n```\n\n#### `6FA5` NULLSWAPIFNOT2\n\nPushes two nulls under the topmost _Integer_ `x`, but only if `x=0`.<br />Equivalent to `NULLSWAPIFNOT` `NULLSWAPIFNOT`.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nNULLSWAPIFNOT2\n```\n\n#### `6FA6` NULLROTRIF2\n\nPushes two nulls under the second stack entry from the top, but only if the topmost _Integer_ `y` is non-zero.<br />Equivalent to `NULLROTRIF` `NULLROTRIF`.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nNULLROTRIF2\n```\n\n#### `6FA7` NULLROTRIFNOT2\n\nPushes two nulls under the second stack entry from the top, but only if the topmost _Integer_ `y` is zero.<br />Equivalent to `NULLROTRIFNOT` `NULLROTRIFNOT`.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\nNULLROTRIFNOT2\n```\n\n#### `6FBij` INDEX2\n\nRecovers `x=(t_{i+1})_{j+1}` for `0 <= i,j <= 3`.<br />Equivalent to `[i] INDEX` `[j] INDEX`.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\n[i] [j] INDEX2\n```\n\n**Aliases**:\n- `CADR`<br />\n  Recovers `x=(t_2)_1`.\n- `CDDR`<br />\n  Recovers `x=(t_2)_2`.\n\n#### `6FE_ijk` INDEX3\n\nRecovers `x=t_{i+1}_{j+1}_{k+1}`.<br />`0 <= i,j,k <= 3`<br />Equivalent to `[i] [j] INDEX2` `[k] INDEX`.<br />\n**Category:** Tuple (tuple)<br />\n\n```fift Fift\n[i] [j] [k] INDEX3\n```\n\n**Aliases**:\n- `CADDR`<br />\n  Recovers `x=t_2_2_1`.\n- `CDDDR`<br />\n  Recovers `x=t_2_2_2`.\n\n#### `7i` PUSHINT_4\n\nPushes integer `x` into the stack. `-5 <= x <= 10`.<br />Here `i` equals four lower-order bits of `x` (`i=x mod 16`).<br />\n**Category:** Const Int (const_int)<br />\n\n```fift Fift\n[x] PUSHINT\n[x] INT\n```\n\n**Aliases**:\n- `ZERO`<br />\n- `ONE`<br />\n- `TWO`<br />\n- `TEN`<br />\n- `TRUE`<br />\n\n#### `80xx` PUSHINT_8\n\nPushes integer `xx`. `-128 <= xx <= 127`.<br />\n**Category:** Const Int (const_int)<br />\n\n```fift Fift\n[xx] PUSHINT\n[xx] INT\n```\n\n#### `81xxxx` PUSHINT_16\n\nPushes integer `xxxx`. `-2^15 <= xx < 2^15`.<br />\n**Category:** Const Int (const_int)<br />\n\n```fift Fift\n[xxxx] PUSHINT\n[xxxx] INT\n```\n\n#### `82lxxx` PUSHINT_LONG\n\nPushes integer `xxx`.<br />_Details:_ 5-bit `0 <= l <= 30` determines the length `n=8l+19` of signed big-endian integer `xxx`.<br />The total length of this instruction is `l+4` bytes or `n+13=8l+32` bits.<br />\n**Category:** Const Int (const_int)<br />\n\n```fift Fift\n[xxx] PUSHINT\n[xxx] INT\n```\n\n#### `83xx` PUSHPOW2\n\n(Quietly) pushes `2^(xx+1)` for `0 <= xx <= 255`.<br />`2^256` is a `NaN`.<br />\n**Category:** Const Int (const_int)<br />\n\n```fift Fift\n[xx+1] PUSHPOW2\n```\n\n#### `83FF` PUSHNAN\n\nPushes a `NaN`.<br />\n**Category:** Const Int (const_int)<br />\n\n```fift Fift\nPUSHNAN\n```\n\n#### `84xx` PUSHPOW2DEC\n\nPushes `2^(xx+1)-1` for `0 <= xx <= 255`.<br />\n**Category:** Const Int (const_int)<br />\n\n```fift Fift\n[xx+1] PUSHPOW2DEC\n```\n\n#### `85xx` PUSHNEGPOW2\n\nPushes `-2^(xx+1)` for `0 <= xx <= 255`.<br />\n**Category:** Const Int (const_int)<br />\n\n```fift Fift\n[xx+1] PUSHNEGPOW2\n```\n\n#### `88` PUSHREF\n\nPushes the reference `ref` into the stack.<br />_Details:_ Pushes the first reference of `cc.code` into the stack as a _Cell_ (and removes this reference from the current continuation).<br />\n**Category:** Const Data (const_data)<br />\n\n```fift Fift\n[ref] PUSHREF\n```\n\n#### `89` PUSHREFSLICE\n\nSimilar to `PUSHREF`, but converts the cell into a _Slice_.<br />\n**Category:** Const Data (const_data)<br />\n\n```fift Fift\n[ref] PUSHREFSLICE\n```\n\n#### `8A` PUSHREFCONT\n\nSimilar to `PUSHREFSLICE`, but makes a simple ordinary _Continuation_ out of the cell.<br />\n**Category:** Const Data (const_data)<br />\n\n```fift Fift\n[ref] PUSHREFCONT\n```\n\n#### `8Bxsss` PUSHSLICE\n\nPushes the slice `slice` into the stack.<br />_Details:_ Pushes the (prefix) subslice of `cc.code` consisting of its first `8x+4` bits and no references (i.e., essentially a bitstring), where `0 <= x <= 15`.<br />A completion tag is assumed, meaning that all trailing zeroes and the last binary one (if present) are removed from this bitstring.<br />If the original bitstring consists only of zeroes, an empty slice will be pushed.<br />\n**Category:** Const Data (const_data)<br />\n\n```fift Fift\n[slice] PUSHSLICE\n[slice] SLICE\n```\n\n#### `8Crxxssss` PUSHSLICE_REFS\n\nPushes the slice `slice` into the stack.<br />_Details:_ Pushes the (prefix) subslice of `cc.code` consisting of its first `1 <= r+1 <= 4` references and up to first `8xx+1` bits of data, with `0 <= xx <= 31`.<br />A completion tag is also assumed.<br />\n**Category:** Const Data (const_data)<br />\n\n```fift Fift\n[slice] PUSHSLICE\n[slice] SLICE\n```\n\n#### `8Drxxsssss` PUSHSLICE_LONG\n\nPushes the slice `slice` into the stack.<br />_Details:_ Pushes the subslice of `cc.code` consisting of `0 <= r <= 4` references and up to `8xx+6` bits of data, with `0 <= xx <= 127`.<br />A completion tag is assumed.<br />\n**Category:** Const Data (const_data)<br />\n\n```fift Fift\n[slice] PUSHSLICE\n[slice] SLICE\n```\n\n#### `8F_rxxcccc` PUSHCONT\n\nPushes a continuation made from `builder`.<br />_Details:_ Pushes the simple ordinary continuation `cccc` made from the first `0 <= r <= 3` references and the first `0 <= xx <= 127` bytes of `cc.code`.<br />\n**Category:** Const Data (const_data)<br />\n\n```fift Fift\n[builder] PUSHCONT\n[builder] CONT\n```\n\n#### `9xccc` PUSHCONT_SHORT\n\nPushes a continuation made from `builder`.<br />_Details:_ Pushes an `x`-byte continuation for `0 <= x <= 15`.<br />\n**Category:** Const Data (const_data)<br />\n\n```fift Fift\n[builder] PUSHCONT\n[builder] CONT\n```\n\n#### `A0` ADD\n\n<br />\n**Category:** Arithm Basic (arithm_basic)<br />\n\n```fift Fift\nADD\n```\n\n#### `A1` SUB\n\n<br />\n**Category:** Arithm Basic (arithm_basic)<br />\n\n```fift Fift\nSUB\n```\n\n#### `A2` SUBR\n\nEquivalent to `SWAP` `SUB`.<br />\n**Category:** Arithm Basic (arithm_basic)<br />\n\n```fift Fift\nSUBR\n```\n\n#### `A3` NEGATE\n\nEquivalent to `-1 MULCONST` or to `ZERO SUBR`.<br />Notice that it triggers an integer overflow exception if `x=-2^256`.<br />\n**Category:** Arithm Basic (arithm_basic)<br />\n\n```fift Fift\nNEGATE\n```\n\n#### `A4` INC\n\nEquivalent to `1 ADDCONST`.<br />\n**Category:** Arithm Basic (arithm_basic)<br />\n\n```fift Fift\nINC\n```\n\n#### `A5` DEC\n\nEquivalent to `-1 ADDCONST`.<br />\n**Category:** Arithm Basic (arithm_basic)<br />\n\n```fift Fift\nDEC\n```\n\n#### `A6cc` ADDCONST\n\n`-128 <= cc <= 127`.<br />\n**Category:** Arithm Basic (arithm_basic)<br />\n\n```fift Fift\n[cc] ADDCONST\n[cc] ADDINT\n[-cc] SUBCONST\n[-cc] SUBINT\n```\n\n#### `A7cc` MULCONST\n\n`-128 <= cc <= 127`.<br />\n**Category:** Arithm Basic (arithm_basic)<br />\n\n```fift Fift\n[cc] MULCONST\n[cc] MULINT\n```\n\n#### `A8` MUL\n\n<br />\n**Category:** Arithm Basic (arithm_basic)<br />\n\n```fift Fift\nMUL\n```\n\n#### `A900` ADDDIVMOD\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nADDDIVMOD\n```\n\n#### `A901` ADDDIVMODR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nADDDIVMODR\n```\n\n#### `A902` ADDDIVMODC\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nADDDIVMODC\n```\n\n#### `A904` DIV\n\n`q=floor(x/y)`, `r=x-y*q`<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nDIV\n```\n\n#### `A905` DIVR\n\n`q'=round(x/y)`, `r'=x-y*q'`<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nDIVR\n```\n\n#### `A906` DIVC\n\n`q''=ceil(x/y)`, `r''=x-y*q''`<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nDIVC\n```\n\n#### `A908` MOD\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMOD\n```\n\n#### `A909` MODR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMODR\n```\n\n#### `A90A` MODC\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMODC\n```\n\n#### `A90C` DIVMOD\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nDIVMOD\n```\n\n#### `A90D` DIVMODR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nDIVMODR\n```\n\n#### `A90E` DIVMODC\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nDIVMODC\n```\n\n#### `A920` ADDRSHIFTMOD_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nADDRSHIFTMOD\n```\n\n#### `A921` ADDRSHIFTMODR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nADDRSHIFTMODR\n```\n\n#### `A922` ADDRSHIFTMODC\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nADDRSHIFTMODC\n```\n\n#### `A925` RSHIFTR_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nRSHIFTR\n```\n\n#### `A926` RSHIFTC_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nRSHIFTC\n```\n\n#### `A928` MODPOW2_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMODPOW2\n```\n\n#### `A929` MODPOW2R_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMODPOW2R\n```\n\n#### `A92A` MODPOW2C_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMODPOW2C\n```\n\n#### `A92C` RSHIFTMOD_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nRSHIFTMOD\n```\n\n#### `A92D` RSHIFTMODR_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nRSHIFTMODR\n```\n\n#### `A92E` RSHIFTMODC_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nRSHIFTMODC\n```\n\n#### `A930tt` ADDRSHIFTMOD\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] ADDRSHIFT#MOD\n```\n\n#### `A931tt` ADDRSHIFTRMOD\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] ADDRSHIFTR#MOD\n```\n\n#### `A932tt` ADDRSHIFTCMOD\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] ADDRSHIFTC#MOD\n```\n\n#### `A935tt` RSHIFTR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] RSHIFTR#\n```\n\n#### `A936tt` RSHIFTC\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] RSHIFTC#\n```\n\n#### `A938tt` MODPOW2\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] MODPOW2#\n```\n\n#### `A939tt` MODPOW2R\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] MODPOW2R#\n```\n\n#### `A93Att` MODPOW2C\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] MODPOW2C#\n```\n\n#### `A93Ctt` RSHIFTMOD\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] RSHIFT#MOD\n```\n\n#### `A93Dtt` RSHIFTRMOD\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] RSHIFTR#MOD\n```\n\n#### `A93Ett` RSHIFTCMOD\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] RSHIFTC#MOD\n```\n\n#### `A980` MULADDDIVMOD\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULADDDIVMOD\n```\n\n#### `A981` MULADDDIVMODR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULADDDIVMODR\n```\n\n#### `A982` MULADDDIVMODC\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULADDDIVMODC\n```\n\n#### `A984` MULDIV\n\n`q=floor(x*y/z)`<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULDIV\n```\n\n#### `A985` MULDIVR\n\n`q'=round(x*y/z)`<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULDIVR\n```\n\n#### `A986` MULDIVC\n\n`q'=ceil(x*y/z)`<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULDIVC\n```\n\n#### `A988` MULMOD\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULMOD\n```\n\n#### `A989` MULMODR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULMODR\n```\n\n#### `A98A` MULMODC\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULMODC\n```\n\n#### `A98C` MULDIVMOD\n\n`q=floor(x*y/z)`, `r=x*y-z*q`<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULDIVMOD\n```\n\n#### `A98D` MULDIVMODR\n\n`q=round(x*y/z)`, `r=x*y-z*q`<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULDIVMODR\n```\n\n#### `A98E` MULDIVMODC\n\n`q=ceil(x*y/z)`, `r=x*y-z*q`<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULDIVMODC\n```\n\n#### `A9A0` MULADDRSHIFTMOD_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULADDRSHIFTMOD\n```\n\n#### `A9A1` MULADDRSHIFTRMOD_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULADDRSHIFTRMOD\n```\n\n#### `A9A2` MULADDRSHIFTCMOD_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULADDRSHIFTCMOD\n```\n\n#### `A9A4` MULRSHIFT_VAR\n\n`0 <= z <= 256`<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULRSHIFT\n```\n\n#### `A9A5` MULRSHIFTR_VAR\n\n`0 <= z <= 256`<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULRSHIFTR\n```\n\n#### `A9A6` MULRSHIFTC_VAR\n\n`0 <= z <= 256`<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULRSHIFTC\n```\n\n#### `A9A8` MULMODPOW2_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULMODPOW2_VAR\n```\n\n#### `A9A9` MULMODPOW2R_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULMODPOW2R_VAR\n```\n\n#### `A9AA` MULMODPOW2C_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULMODPOW2C_VAR\n```\n\n#### `A9AC` MULRSHIFTMOD_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULRSHIFTMOD_VAR\n```\n\n#### `A9AD` MULRSHIFTRMOD_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULRSHIFTRMOD_VAR\n```\n\n#### `A9AE` MULRSHIFTCMOD_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULRSHIFTCMOD_VAR\n```\n\n#### `A9B0tt` MULADDRSHIFTMOD\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] MULADDRSHIFT#MOD\n```\n\n#### `A9B1tt` MULADDRSHIFTRMOD\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] MULADDRSHIFTR#MOD\n```\n\n#### `A9B2tt` MULADDRSHIFTCMOD\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] MULADDRSHIFTC#MOD\n```\n\n#### `A9B4tt` MULRSHIFT\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] MULRSHIFT#\n```\n\n#### `A9B5tt` MULRSHIFTR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] MULRSHIFTR#\n```\n\n#### `A9B6tt` MULRSHIFTC\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] MULRSHIFTC#\n```\n\n#### `A9B8tt` MULMODPOW2\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] MULMODPOW2#\n```\n\n#### `A9B9tt` MULMODPOW2R\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] MULMODPOW2R#\n```\n\n#### `A9BAtt` MULMODPOW2C\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] MULMODPOW2C#\n```\n\n#### `A9BC` MULRSHIFTMOD\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULRSHIFT#MOD\n```\n\n#### `A9BD` MULRSHIFTRMOD\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULRSHIFTR#MOD\n```\n\n#### `A9BE` MULRSHIFTCMOD\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nMULRSHIFTC#MOD\n```\n\n#### `A9C0` LSHIFTADDDIVMOD_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nLSHIFTADDDIVMOD\n```\n\n#### `A9C1` LSHIFTADDDIVMODR_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nLSHIFTADDDIVMODR\n```\n\n#### `A9C2` LSHIFTADDDIVMODC_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nLSHIFTADDDIVMODC\n```\n\n#### `A9C4` LSHIFTDIV_VAR\n\n`0 <= z <= 256`<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nLSHIFTDIV\n```\n\n#### `A9C5` LSHIFTDIVR_VAR\n\n`0 <= z <= 256`<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nLSHIFTDIVR\n```\n\n#### `A9C6` LSHIFTDIVC_VAR\n\n`0 <= z <= 256`<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nLSHIFTDIVC\n```\n\n#### `A9C8` LSHIFTMOD_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nLSHIFTMOD\n```\n\n#### `A9C9` LSHIFTMODR_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nLSHIFTMODR\n```\n\n#### `A9CA` LSHIFTMODC_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nLSHIFTMODC\n```\n\n#### `A9CC` LSHIFTDIVMOD_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nLSHIFTDIVMOD\n```\n\n#### `A9CD` LSHIFTDIVMODR_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nLSHIFTDIVMODR\n```\n\n#### `A9CE` LSHIFTDIVMODC_VAR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\nLSHIFTDIVMODC\n```\n\n#### `A9D0tt` LSHIFTADDDIVMOD\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] LSHIFT#ADDDIVMOD\n```\n\n#### `A9D1tt` LSHIFTADDDIVMODR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] LSHIFT#ADDDIVMODR\n```\n\n#### `A9D2tt` LSHIFTADDDIVMODC\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] LSHIFT#ADDDIVMODC\n```\n\n#### `A9D4tt` LSHIFTDIV\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] LSHIFT#DIV\n```\n\n#### `A9D5tt` LSHIFTDIVR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] LSHIFT#DIVR\n```\n\n#### `A9D6tt` LSHIFTDIVC\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] LSHIFT#DIVC\n```\n\n#### `A9D8tt` LSHIFTMOD\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] LSHIFT#MOD\n```\n\n#### `A9D9tt` LSHIFTMODR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] LSHIFT#MODR\n```\n\n#### `A9DAtt` LSHIFTMODC\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] LSHIFT#MODC\n```\n\n#### `A9DCtt` LSHIFTDIVMOD\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] LSHIFT#DIVMOD\n```\n\n#### `A9DDtt` LSHIFTDIVMODR\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] LSHIFT#DIVMODR\n```\n\n#### `A9DEtt` LSHIFTDIVMODC\n\n<br />\n**Category:** Arithm Div (arithm_div)<br />\n\n```fift Fift\n[tt+1] LSHIFT#DIVMODC\n```\n\n#### `AAcc` LSHIFT\n\n`0 <= cc <= 255`<br />\n**Category:** Arithm Logical (arithm_logical)<br />\n\n```fift Fift\n[cc+1] LSHIFT#\n```\n\n#### `ABcc` RSHIFT\n\n`0 <= cc <= 255`<br />\n**Category:** Arithm Logical (arithm_logical)<br />\n\n```fift Fift\n[cc+1] RSHIFT#\n```\n\n#### `AC` LSHIFT_VAR\n\n`0 <= y <= 1023`<br />\n**Category:** Arithm Logical (arithm_logical)<br />\n\n```fift Fift\nLSHIFT\n```\n\n#### `AD` RSHIFT_VAR\n\n`0 <= y <= 1023`<br />\n**Category:** Arithm Logical (arithm_logical)<br />\n\n```fift Fift\nRSHIFT\n```\n\n#### `AE` POW2\n\n`0 <= y <= 1023`<br />Equivalent to `ONE` `SWAP` `LSHIFT`.<br />\n**Category:** Arithm Logical (arithm_logical)<br />\n\n```fift Fift\nPOW2\n```\n\n#### `B0` AND\n\nBitwise and of two signed integers `x` and `y`, sign-extended to infinity.<br />\n**Category:** Arithm Logical (arithm_logical)<br />\n\n```fift Fift\nAND\n```\n\n#### `B1` OR\n\nBitwise or of two integers.<br />\n**Category:** Arithm Logical (arithm_logical)<br />\n\n```fift Fift\nOR\n```\n\n#### `B2` XOR\n\nBitwise xor of two integers.<br />\n**Category:** Arithm Logical (arithm_logical)<br />\n\n```fift Fift\nXOR\n```\n\n#### `B3` NOT\n\nBitwise not of an integer.<br />\n**Category:** Arithm Logical (arithm_logical)<br />\n\n```fift Fift\nNOT\n```\n\n#### `B4cc` FITS\n\nChecks whether `x` is a `cc+1`-bit signed integer for `0 <= cc <= 255` (i.e., whether `-2^cc <= x < 2^cc`).<br />If not, either triggers an integer overflow exception, or replaces `x` with a `NaN` (quiet version).<br />\n**Category:** Arithm Logical (arithm_logical)<br />\n\n```fift Fift\n[cc+1] FITS\n```\n\n**Aliases**:\n- `CHKBOOL`<br />\n  Checks whether `x` is a ''boolean value'' (i.e., either 0 or -1).\n\n#### `B5cc` UFITS\n\nChecks whether `x` is a `cc+1`-bit unsigned integer for `0 <= cc <= 255` (i.e., whether `0 <= x < 2^(cc+1)`).<br />\n**Category:** Arithm Logical (arithm_logical)<br />\n\n```fift Fift\n[cc+1] UFITS\n```\n\n**Aliases**:\n- `CHKBIT`<br />\n  Checks whether `x` is a binary digit (i.e., zero or one).\n\n#### `B600` FITSX\n\nChecks whether `x` is a `c`-bit signed integer for `0 <= c <= 1023`.<br />\n**Category:** Arithm Logical (arithm_logical)<br />\n\n```fift Fift\nFITSX\n```\n\n#### `B601` UFITSX\n\nChecks whether `x` is a `c`-bit unsigned integer for `0 <= c <= 1023`.<br />\n**Category:** Arithm Logical (arithm_logical)<br />\n\n```fift Fift\nUFITSX\n```\n\n#### `B602` BITSIZE\n\nComputes smallest `c >= 0` such that `x` fits into a `c`-bit signed integer (`-2^(c-1) <= c < 2^(c-1)`).<br />\n**Category:** Arithm Logical (arithm_logical)<br />\n\n```fift Fift\nBITSIZE\n```\n\n#### `B603` UBITSIZE\n\nComputes smallest `c >= 0` such that `x` fits into a `c`-bit unsigned integer (`0 <= x < 2^c`), or throws a range check exception.<br />\n**Category:** Arithm Logical (arithm_logical)<br />\n\n```fift Fift\nUBITSIZE\n```\n\n#### `B608` MIN\n\nComputes the minimum of two integers `x` and `y`.<br />\n**Category:** Arithm Logical (arithm_logical)<br />\n\n```fift Fift\nMIN\n```\n\n#### `B609` MAX\n\nComputes the maximum of two integers `x` and `y`.<br />\n**Category:** Arithm Logical (arithm_logical)<br />\n\n```fift Fift\nMAX\n```\n\n#### `B60A` MINMAX\n\nSorts two integers. Quiet version of this operation returns two `NaN`s if any of the arguments are `NaN`s.<br />\n**Category:** Arithm Logical (arithm_logical)<br />\n\n```fift Fift\nMINMAX\nINTSORT2\n```\n\n#### `B60B` ABS\n\nComputes the absolute value of an integer `x`.<br />\n**Category:** Arithm Logical (arithm_logical)<br />\n\n```fift Fift\nABS\n```\n\n#### `B7A0` QADD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQADD\n```\n\n#### `B7A1` QSUB\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQSUB\n```\n\n#### `B7A2` QSUBR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQSUBR\n```\n\n#### `B7A3` QNEGATE\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQNEGATE\n```\n\n#### `B7A4` QINC\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQINC\n```\n\n#### `B7A5` QDEC\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQDEC\n```\n\n#### `B7A8` QMUL\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMUL\n```\n\n#### `B7A900` QADDDIVMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQADDDIVMOD\n```\n\n#### `B7A901` QADDDIVMODR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQADDDIVMODR\n```\n\n#### `B7A902` QADDDIVMODC\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQADDDIVMODC\n```\n\n#### `B7A904` QDIV\n\nDivision returns `NaN` if `y=0`.<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQDIV\n```\n\n#### `B7A905` QDIVR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQDIVR\n```\n\n#### `B7A906` QDIVC\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQDIVC\n```\n\n#### `B7A908` QMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMOD\n```\n\n#### `B7A909` QMODR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMODR\n```\n\n#### `B7A90A` QMODC\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMODC\n```\n\n#### `B7A90C` QDIVMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQDIVMOD\n```\n\n#### `B7A90D` QDIVMODR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQDIVMODR\n```\n\n#### `B7A90E` QDIVMODC\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQDIVMODC\n```\n\n#### `B7A920` QADDRSHIFTMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQADDRSHIFTMOD\n```\n\n#### `B7A921` QADDRSHIFTMODR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQADDRSHIFTMODR\n```\n\n#### `B7A922` QADDRSHIFTMODC\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQADDRSHIFTMODC\n```\n\n#### `B7A925` QRSHIFTR_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQRSHIFTR\n```\n\n#### `B7A926` QRSHIFTC_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQRSHIFTC\n```\n\n#### `B7A928` QMODPOW2_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMODPOW2\n```\n\n#### `B7A929` QMODPOW2R_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMODPOW2R\n```\n\n#### `B7A92A` QMODPOW2C_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMODPOW2C\n```\n\n#### `B7A92C` QRSHIFTMOD_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQRSHIFTMOD\n```\n\n#### `B7A92D` QRSHIFTMODR_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQRSHIFTMODR\n```\n\n#### `B7A92E` QRSHIFTMODC_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQRSHIFTMODC\n```\n\n#### `B7A930tt` QADDRSHIFTMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QADDRSHIFT#MOD\n```\n\n#### `B7A931tt` QADDRSHIFTRMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QADDRSHIFTR#MOD\n```\n\n#### `B7A932tt` QADDRSHIFTCMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QADDRSHIFTC#MOD\n```\n\n#### `B7A935tt` QRSHIFTR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QRSHIFTR#\n```\n\n#### `B7A936tt` QRSHIFTC\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QRSHIFTC#\n```\n\n#### `B7A938tt` QMODPOW2\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QMODPOW2#\n```\n\n#### `B7A939tt` QMODPOW2R\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QMODPOW2R#\n```\n\n#### `B7A93Att` QMODPOW2C\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QMODPOW2C#\n```\n\n#### `B7A93Ctt` QRSHIFTMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QRSHIFT#MOD\n```\n\n#### `B7A93Dtt` QRSHIFTRMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QRSHIFTR#MOD\n```\n\n#### `B7A93Ett` QRSHIFTCMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QRSHIFTC#MOD\n```\n\n#### `B7A980` QMULADDDIVMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULADDDIVMOD\n```\n\n#### `B7A981` QMULADDDIVMODR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULADDDIVMODR\n```\n\n#### `B7A982` QMULADDDIVMODC\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULADDDIVMODC\n```\n\n#### `B7A984` QMULDIV\n\n`q=floor(x*y/z)`<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULDIV\n```\n\n#### `B7A985` QMULDIVR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULDIVR\n```\n\n#### `B7A986` QMULDIVC\n\n`q'=ceil(x*y/z)`<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULDIVC\n```\n\n#### `B7A988` QMULMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULMOD\n```\n\n#### `B7A989` QMULMODR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULMODR\n```\n\n#### `B7A98A` QMULMODC\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULMODC\n```\n\n#### `B7A98C` QMULDIVMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULDIVMOD\n```\n\n#### `B7A98D` QMULDIVMODR\n\n`q=round(x*y/z)`, `r=x*y-z*q`<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULDIVMODR\n```\n\n#### `B7A98E` QMULDIVMODC\n\n`q=ceil(x*y/z)`, `r=x*y-z*q`<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULDIVMODC\n```\n\n#### `B7A9A0` QMULADDRSHIFTMOD_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULADDRSHIFTMOD\n```\n\n#### `B7A9A1` QMULADDRSHIFTRMOD_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULADDRSHIFTRMOD\n```\n\n#### `B7A9A2` QMULADDRSHIFTCMOD_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULADDRSHIFTCMOD\n```\n\n#### `B7A9A4` QMULRSHIFT_VAR\n\n`0 <= z <= 256`<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULRSHIFT\n```\n\n#### `B7A9A5` QMULRSHIFTR_VAR\n\n`0 <= z <= 256`<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULRSHIFTR\n```\n\n#### `B7A9A6` QMULRSHIFTC_VAR\n\n`0 <= z <= 256`<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULRSHIFTC\n```\n\n#### `B7A9A8` QMULMODPOW2_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULMODPOW2_VAR\n```\n\n#### `B7A9A9` QMULMODPOW2R_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULMODPOW2R_VAR\n```\n\n#### `B7A9AA` QMULMODPOW2C_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULMODPOW2C_VAR\n```\n\n#### `B7A9AC` QMULRSHIFTMOD_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULRSHIFTMOD_VAR\n```\n\n#### `B7A9AD` QMULRSHIFTRMOD_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULRSHIFTRMOD_VAR\n```\n\n#### `B7A9AE` QMULRSHIFTCMOD_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULRSHIFTCMOD_VAR\n```\n\n#### `B7A9B0tt` QMULADDRSHIFTMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QMULADDRSHIFT#MOD\n```\n\n#### `B7A9B1tt` QMULADDRSHIFTRMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QMULADDRSHIFTR#MOD\n```\n\n#### `B7A9B2tt` QMULADDRSHIFTCMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QMULADDRSHIFTC#MOD\n```\n\n#### `B7A9B4tt` QMULRSHIFT\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QMULRSHIFT#\n```\n\n#### `B7A9B5tt` QMULRSHIFTR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QMULRSHIFTR#\n```\n\n#### `B7A9B6tt` QMULRSHIFTC\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QMULRSHIFTC#\n```\n\n#### `B7A9B8tt` QMULMODPOW2\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QMULMODPOW2#\n```\n\n#### `B7A9B9tt` QMULMODPOW2R\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QMULMODPOW2R#\n```\n\n#### `B7A9BAtt` QMULMODPOW2C\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QMULMODPOW2C#\n```\n\n#### `B7A9BC` QMULRSHIFTMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULRSHIFT#MOD\n```\n\n#### `B7A9BD` QMULRSHIFTRMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULRSHIFTR#MOD\n```\n\n#### `B7A9BE` QMULRSHIFTCMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQMULRSHIFTC#MOD\n```\n\n#### `B7A9C0` QLSHIFTADDDIVMOD_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQLSHIFTADDDIVMOD\n```\n\n#### `B7A9C1` QLSHIFTADDDIVMODR_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQLSHIFTADDDIVMODR\n```\n\n#### `B7A9C2` QLSHIFTADDDIVMODC_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQLSHIFTADDDIVMODC\n```\n\n#### `B7A9C4` QLSHIFTDIV_VAR\n\n`0 <= z <= 256`<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQLSHIFTDIV\n```\n\n#### `B7A9C5` QLSHIFTDIVR_VAR\n\n`0 <= z <= 256`<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQLSHIFTDIVR\n```\n\n#### `B7A9C6` QLSHIFTDIVC_VAR\n\n`0 <= z <= 256`<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQLSHIFTDIVC\n```\n\n#### `B7A9C8` QLSHIFTMOD_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQLSHIFTMOD\n```\n\n#### `B7A9C9` QLSHIFTMODR_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQLSHIFTMODR\n```\n\n#### `B7A9CA` QLSHIFTMODC_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQLSHIFTMODC\n```\n\n#### `B7A9CC` QLSHIFTDIVMOD_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQLSHIFTDIVMOD\n```\n\n#### `B7A9CD` QLSHIFTDIVMODR_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQLSHIFTDIVMODR\n```\n\n#### `B7A9CE` QLSHIFTDIVMODC_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQLSHIFTDIVMODC\n```\n\n#### `B7A9D0tt` QLSHIFTADDDIVMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QLSHIFT#ADDDIVMOD\n```\n\n#### `B7A9D1tt` QLSHIFTADDDIVMODR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QLSHIFT#ADDDIVMODR\n```\n\n#### `B7A9D2tt` QLSHIFTADDDIVMODC\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QLSHIFT#ADDDIVMODC\n```\n\n#### `B7A9D4tt` QLSHIFTDIV\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QLSHIFT#DIV\n```\n\n#### `B7A9D5tt` QLSHIFTDIVR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QLSHIFT#DIVR\n```\n\n#### `B7A9D6tt` QLSHIFTDIVC\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QLSHIFT#DIVC\n```\n\n#### `B7A9D8tt` QLSHIFTMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QLSHIFT#MOD\n```\n\n#### `B7A9D9tt` QLSHIFTMODR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QLSHIFT#MODR\n```\n\n#### `B7A9DAtt` QLSHIFTMODC\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QLSHIFT#MODC\n```\n\n#### `B7A9DCtt` QLSHIFTDIVMOD\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QLSHIFT#DIVMOD\n```\n\n#### `B7A9DDtt` QLSHIFTDIVMODR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QLSHIFT#DIVMODR\n```\n\n#### `B7A9DEtt` QLSHIFTDIVMODC\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[tt+1] QLSHIFT#DIVMODC\n```\n\n#### `B7AAcc` QLSHIFT\n\n`0 <= cc <= 255`<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[cc+1] QLSHIFT#\n```\n\n#### `B7ABcc` QRSHIFT\n\n`0 <= cc <= 255`<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[cc+1] QRSHIFT#\n```\n\n#### `B7AC` QLSHIFT_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQLSHIFT\n```\n\n#### `B7AD` QRSHIFT_VAR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQRSHIFT\n```\n\n#### `B7AE` QPOW2\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQPOW2\n```\n\n#### `B7B0` QAND\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQAND\n```\n\n#### `B7B1` QOR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQOR\n```\n\n#### `B7B2` QXOR\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQXOR\n```\n\n#### `B7B3` QNOT\n\n<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQNOT\n```\n\n#### `B7B4cc` QFITS\n\nReplaces `x` with a `NaN` if x is not a `cc+1`-bit signed integer, leaves it intact otherwise.<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[cc+1] QFITS\n```\n\n#### `B7B5cc` QUFITS\n\nReplaces `x` with a `NaN` if x is not a `cc+1`-bit unsigned integer, leaves it intact otherwise.<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\n[cc+1] QUFITS\n```\n\n#### `B7B600` QFITSX\n\nReplaces `x` with a `NaN` if x is not a c-bit signed integer, leaves it intact otherwise.<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQFITSX\n```\n\n#### `B7B601` QUFITSX\n\nReplaces `x` with a `NaN` if x is not a c-bit unsigned integer, leaves it intact otherwise.<br />\n**Category:** Arithm Quiet (arithm_quiet)<br />\n\n```fift Fift\nQUFITSX\n```\n\n#### `B8` SGN\n\nComputes the sign of an integer `x`:<br />`-1` if `x<0`, `0` if `x=0`, `1` if `x>0`.<br />\n**Category:** Compare Int (compare_int)<br />\n\n```fift Fift\nSGN\n```\n\n#### `B9` LESS\n\nReturns `-1` if `x<y`, `0` otherwise.<br />\n**Category:** Compare Int (compare_int)<br />\n\n```fift Fift\nLESS\n```\n\n#### `BA` EQUAL\n\nReturns `-1` if `x=y`, `0` otherwise.<br />\n**Category:** Compare Int (compare_int)<br />\n\n```fift Fift\nEQUAL\n```\n\n#### `BB` LEQ\n\n<br />\n**Category:** Compare Int (compare_int)<br />\n\n```fift Fift\nLEQ\n```\n\n#### `BC` GREATER\n\n<br />\n**Category:** Compare Int (compare_int)<br />\n\n```fift Fift\nGREATER\n```\n\n#### `BD` NEQ\n\nEquivalent to `EQUAL` `NOT`.<br />\n**Category:** Compare Int (compare_int)<br />\n\n```fift Fift\nNEQ\n```\n\n#### `BE` GEQ\n\nEquivalent to `LESS` `NOT`.<br />\n**Category:** Compare Int (compare_int)<br />\n\n```fift Fift\nGEQ\n```\n\n#### `BF` CMP\n\nComputes the sign of `x-y`:<br />`-1` if `x<y`, `0` if `x=y`, `1` if `x>y`.<br />No integer overflow can occur here unless `x` or `y` is a `NaN`.<br />\n**Category:** Compare Int (compare_int)<br />\n\n```fift Fift\nCMP\n```\n\n#### `C0yy` EQINT\n\nReturns `-1` if `x=yy`, `0` otherwise.<br />`-2^7 <= yy < 2^7`.<br />\n**Category:** Compare Int (compare_int)<br />\n\n```fift Fift\n[yy] EQINT\n```\n\n**Aliases**:\n- `ISZERO`<br />\n  Checks whether an integer is zero. Corresponds to Forth's `0=`.\n\n#### `C1yy` LESSINT\n\nReturns `-1` if `x<yy`, `0` otherwise.<br />`-2^7 <= yy < 2^7`.<br />\n**Category:** Compare Int (compare_int)<br />\n\n```fift Fift\n[yy] LESSINT\n[yy-1] LEQINT\n```\n\n**Aliases**:\n- `ISNEG`<br />\n  Checks whether an integer is negative. Corresponds to Forth's `0<`.\n- `ISNPOS`<br />\n  Checks whether an integer is non-positive.\n\n#### `C2yy` GTINT\n\nReturns `-1` if `x>yy`, `0` otherwise.<br />`-2^7 <= yy < 2^7`.<br />\n**Category:** Compare Int (compare_int)<br />\n\n```fift Fift\n[yy] GTINT\n[yy+1] GEQINT\n```\n\n**Aliases**:\n- `ISPOS`<br />\n  Checks whether an integer is positive. Corresponds to Forth's `0>`.\n- `ISNNEG`<br />\n  Checks whether an integer is non-negative.\n\n#### `C3yy` NEQINT\n\nReturns `-1` if `x!=yy`, `0` otherwise.<br />`-2^7 <= yy < 2^7`.<br />\n**Category:** Compare Int (compare_int)<br />\n\n```fift Fift\n[yy] NEQINT\n```\n\n#### `C4` ISNAN\n\nChecks whether `x` is a `NaN`.<br />\n**Category:** Compare Int (compare_int)<br />\n\n```fift Fift\nISNAN\n```\n\n#### `C5` CHKNAN\n\nThrows an arithmetic overflow exception if `x` is a `NaN`.<br />\n**Category:** Compare Int (compare_int)<br />\n\n```fift Fift\nCHKNAN\n```\n\n#### `C700` SEMPTY\n\nChecks whether a _Slice_ `s` is empty (i.e., contains no bits of data and no cell references).<br />\n**Category:** Compare Other (compare_other)<br />\n\n```fift Fift\nSEMPTY\n```\n\n#### `C701` SDEMPTY\n\nChecks whether _Slice_ `s` has no bits of data.<br />\n**Category:** Compare Other (compare_other)<br />\n\n```fift Fift\nSDEMPTY\n```\n\n#### `C702` SREMPTY\n\nChecks whether _Slice_ `s` has no references.<br />\n**Category:** Compare Other (compare_other)<br />\n\n```fift Fift\nSREMPTY\n```\n\n#### `C703` SDFIRST\n\nChecks whether the first bit of _Slice_ `s` is a one.<br />\n**Category:** Compare Other (compare_other)<br />\n\n```fift Fift\nSDFIRST\n```\n\n#### `C704` SDLEXCMP\n\nCompares the data of `s` lexicographically with the data of `s'`, returning `-1`, 0, or 1 depending on the result.<br />\n**Category:** Compare Other (compare_other)<br />\n\n```fift Fift\nSDLEXCMP\n```\n\n#### `C705` SDEQ\n\nChecks whether the data parts of `s` and `s'` coincide, equivalent to `SDLEXCMP` `ISZERO`.<br />\n**Category:** Compare Other (compare_other)<br />\n\n```fift Fift\nSDEQ\n```\n\n#### `C708` SDPFX\n\nChecks whether `s` is a prefix of `s'`.<br />\n**Category:** Compare Other (compare_other)<br />\n\n```fift Fift\nSDPFX\n```\n\n#### `C709` SDPFXREV\n\nChecks whether `s'` is a prefix of `s`, equivalent to `SWAP` `SDPFX`.<br />\n**Category:** Compare Other (compare_other)<br />\n\n```fift Fift\nSDPFXREV\n```\n\n#### `C70A` SDPPFX\n\nChecks whether `s` is a proper prefix of `s'` (i.e., a prefix distinct from `s'`).<br />\n**Category:** Compare Other (compare_other)<br />\n\n```fift Fift\nSDPPFX\n```\n\n#### `C70B` SDPPFXREV\n\nChecks whether `s'` is a proper prefix of `s`.<br />\n**Category:** Compare Other (compare_other)<br />\n\n```fift Fift\nSDPPFXREV\n```\n\n#### `C70C` SDSFX\n\nChecks whether `s` is a suffix of `s'`.<br />\n**Category:** Compare Other (compare_other)<br />\n\n```fift Fift\nSDSFX\n```\n\n#### `C70D` SDSFXREV\n\nChecks whether `s'` is a suffix of `s`.<br />\n**Category:** Compare Other (compare_other)<br />\n\n```fift Fift\nSDSFXREV\n```\n\n#### `C70E` SDPSFX\n\nChecks whether `s` is a proper suffix of `s'`.<br />\n**Category:** Compare Other (compare_other)<br />\n\n```fift Fift\nSDPSFX\n```\n\n#### `C70F` SDPSFXREV\n\nChecks whether `s'` is a proper suffix of `s`.<br />\n**Category:** Compare Other (compare_other)<br />\n\n```fift Fift\nSDPSFXREV\n```\n\n#### `C710` SDCNTLEAD0\n\nReturns the number of leading zeroes in `s`.<br />\n**Category:** Compare Other (compare_other)<br />\n\n```fift Fift\nSDCNTLEAD0\n```\n\n#### `C711` SDCNTLEAD1\n\nReturns the number of leading ones in `s`.<br />\n**Category:** Compare Other (compare_other)<br />\n\n```fift Fift\nSDCNTLEAD1\n```\n\n#### `C712` SDCNTTRAIL0\n\nReturns the number of trailing zeroes in `s`.<br />\n**Category:** Compare Other (compare_other)<br />\n\n```fift Fift\nSDCNTTRAIL0\n```\n\n#### `C713` SDCNTTRAIL1\n\nReturns the number of trailing ones in `s`.<br />\n**Category:** Compare Other (compare_other)<br />\n\n```fift Fift\nSDCNTTRAIL1\n```\n\n#### `C8` NEWC\n\nCreates a new empty _Builder_.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nNEWC\n```\n\n#### `C9` ENDC\n\nConverts a _Builder_ into an ordinary _Cell_.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nENDC\n```\n\n#### `CAcc` STI\n\nStores a signed `cc+1`-bit integer `x` into _Builder_ `b` for `0 <= cc <= 255`, throws a range check exception if `x` does not fit into `cc+1` bits.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\n[cc+1] STI\n```\n\n#### `CBcc` STU\n\nStores an unsigned `cc+1`-bit integer `x` into _Builder_ `b`. In all other respects it is similar to `STI`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\n[cc+1] STU\n```\n\n#### `CC` STREF\n\nStores a reference to _Cell_ `c` into _Builder_ `b`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTREF\n```\n\n#### `CD` STBREFR\n\nEquivalent to `ENDC` `SWAP` `STREF`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTBREFR\nENDCST\n```\n\n#### `CE` STSLICE\n\nStores _Slice_ `s` into _Builder_ `b`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTSLICE\n```\n\n**Aliases**:\n- `STDICTS`<br />\n  Stores a _Slice_-represented dictionary `s` into _Builder_ `b`.<br />It is actually a synonym for `STSLICE`.\n\n#### `CF00` STIX\n\nStores a signed `l`-bit integer `x` into `b` for `0 <= l <= 257`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTIX\n```\n\n#### `CF01` STUX\n\nStores an unsigned `l`-bit integer `x` into `b` for `0 <= l <= 256`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTUX\n```\n\n#### `CF02` STIXR\n\nSimilar to `STIX`, but with arguments in a different order.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTIXR\n```\n\n#### `CF03` STUXR\n\nSimilar to `STUX`, but with arguments in a different order.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTUXR\n```\n\n#### `CF04` STIXQ\n\nA quiet version of `STIX`. If there is no space in `b`, sets `b'=b` and `f=-1`.<br />If `x` does not fit into `l` bits, sets `b'=b` and `f=1`.<br />If the operation succeeds, `b'` is the new _Builder_ and `f=0`.<br />However, `0 <= l <= 257`, with a range check exception if this is not so.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTIXQ\n```\n\n#### `CF05` STUXQ\n\nA quiet version of `STUX`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTUXQ\n```\n\n#### `CF06` STIXRQ\n\nA quiet version of `STIXR`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTIXRQ\n```\n\n#### `CF07` STUXRQ\n\nA quiet version of `STUXR`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTUXRQ\n```\n\n#### `CF08cc` STI_ALT\n\nA longer version of `[cc+1] STI`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\n[cc+1] STI_l\n```\n\n#### `CF09cc` STU_ALT\n\nA longer version of `[cc+1] STU`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\n[cc+1] STU_l\n```\n\n#### `CF0Acc` STIR\n\nEquivalent to `SWAP` `[cc+1] STI`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\n[cc+1] STIR\n```\n\n#### `CF0Bcc` STUR\n\nEquivalent to `SWAP` `[cc+1] STU`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\n[cc+1] STUR\n```\n\n#### `CF0Ccc` STIQ\n\nA quiet version of `STI`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\n[cc+1] STIQ\n```\n\n#### `CF0Dcc` STUQ\n\nA quiet version of `STU`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\n[cc+1] STUQ\n```\n\n#### `CF0Ecc` STIRQ\n\nA quiet version of `STIR`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\n[cc+1] STIRQ\n```\n\n#### `CF0Fcc` STURQ\n\nA quiet version of `STUR`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\n[cc+1] STURQ\n```\n\n#### `CF10` STREF_ALT\n\nA longer version of `STREF`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTREF_l\n```\n\n#### `CF11` STBREF\n\nEquivalent to `SWAP` `STBREFR`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTBREF\n```\n\n#### `CF12` STSLICE_ALT\n\nA longer version of `STSLICE`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTSLICE_l\n```\n\n#### `CF13` STB\n\nAppends all data from _Builder_ `b'` to _Builder_ `b`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTB\n```\n\n#### `CF14` STREFR\n\nEquivalent to `SWAP` `STREF`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTREFR\n```\n\n#### `CF15` STBREFR_ALT\n\nA longer encoding of `STBREFR`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTBREFR_l\n```\n\n#### `CF16` STSLICER\n\nEquivalent to `SWAP` `STSLICE`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTSLICER\n```\n\n#### `CF17` STBR\n\nConcatenates two builders.<br />Equivalent to `SWAP` `STB`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTBR\nBCONCAT\n```\n\n#### `CF18` STREFQ\n\nQuiet version of `STREF`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTREFQ\n```\n\n#### `CF19` STBREFQ\n\nQuiet version of `STBREF`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTBREFQ\n```\n\n#### `CF1A` STSLICEQ\n\nQuiet version of `STSLICE`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTSLICEQ\n```\n\n#### `CF1B` STBQ\n\nQuiet version of `STB`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTBQ\n```\n\n#### `CF1C` STREFRQ\n\nQuiet version of `STREFR`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTREFRQ\n```\n\n#### `CF1D` STBREFRQ\n\nQuiet version of `STBREFR`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTBREFRQ\n```\n\n#### `CF1E` STSLICERQ\n\nQuiet version of `STSLICER`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTSLICERQ\n```\n\n#### `CF1F` STBRQ\n\nQuiet version of `STBR`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTBRQ\nBCONCATQ\n```\n\n#### `CF20` STREFCONST\n\nEquivalent to `PUSHREF` `STREFR`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\n[ref] STREFCONST\n```\n\n#### `CF21` STREF2CONST\n\nEquivalent to `STREFCONST` `STREFCONST`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\n[ref] [ref] STREF2CONST\n```\n\n#### `CF23` ENDXC\n\nIf `x!=0`, creates a _special_ or _exotic_ cell from _Builder_ `b`.<br />The type of the exotic cell must be stored in the first 8 bits of `b`.<br />If `x=0`, it is equivalent to `ENDC`. Otherwise some validity checks on the data and references of `b` are performed before creating the exotic cell.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nENDXC\n```\n\n#### `CF28` STILE4\n\nStores a little-endian signed 32-bit integer.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTILE4\n```\n\n#### `CF29` STULE4\n\nStores a little-endian unsigned 32-bit integer.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTULE4\n```\n\n#### `CF2A` STILE8\n\nStores a little-endian signed 64-bit integer.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTILE8\n```\n\n#### `CF2B` STULE8\n\nStores a little-endian unsigned 64-bit integer.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTULE8\n```\n\n#### `CF30` BDEPTH\n\nReturns the depth of _Builder_ `b`. If no cell references are stored in `b`, then `x=0`; otherwise `x` is one plus the maximum of depths of cells referred to from `b`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nBDEPTH\n```\n\n#### `CF31` BBITS\n\nReturns the number of data bits already stored in _Builder_ `b`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nBBITS\n```\n\n#### `CF32` BREFS\n\nReturns the number of cell references already stored in `b`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nBREFS\n```\n\n#### `CF33` BBITREFS\n\nReturns the numbers of both data bits and cell references in `b`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nBBITREFS\n```\n\n#### `CF35` BREMBITS\n\nReturns the number of data bits that can still be stored in `b`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nBREMBITS\n```\n\n#### `CF36` BREMREFS\n\nReturns the number of references that can still be stored in `b`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nBREMREFS\n```\n\n#### `CF37` BREMBITREFS\n\nReturns the numbers of both data bits and references that can still be stored in `b`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nBREMBITREFS\n```\n\n#### `CF38cc` BCHKBITS\n\nChecks whether `cc+1` bits can be stored into `b`, where `0 <= cc <= 255`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\n[cc+1] BCHKBITS#\n```\n\n#### `CF39` BCHKBITS_VAR\n\nChecks whether `x` bits can be stored into `b`, `0 <= x <= 1023`. If there is no space for `x` more bits in `b`, or if `x` is not within the range `0...1023`, throws an exception.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nBCHKBITS\n```\n\n#### `CF3A` BCHKREFS\n\nChecks whether `y` references can be stored into `b`, `0 <= y <= 7`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nBCHKREFS\n```\n\n#### `CF3B` BCHKBITREFS\n\nChecks whether `x` bits and `y` references can be stored into `b`, `0 <= x <= 1023`, `0 <= y <= 7`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nBCHKBITREFS\n```\n\n#### `CF3Ccc` BCHKBITSQ\n\nChecks whether `cc+1` bits can be stored into `b`, where `0 <= cc <= 255`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\n[cc+1] BCHKBITSQ#\n```\n\n#### `CF3D` BCHKBITSQ_VAR\n\nChecks whether `x` bits can be stored into `b`, `0 <= x <= 1023`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nBCHKBITSQ\n```\n\n#### `CF3E` BCHKREFSQ\n\nChecks whether `y` references can be stored into `b`, `0 <= y <= 7`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nBCHKREFSQ\n```\n\n#### `CF3F` BCHKBITREFSQ\n\nChecks whether `x` bits and `y` references can be stored into `b`, `0 <= x <= 1023`, `0 <= y <= 7`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nBCHKBITREFSQ\n```\n\n#### `CF40` STZEROES\n\nStores `n` binary zeroes into _Builder_ `b`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTZEROES\n```\n\n#### `CF41` STONES\n\nStores `n` binary ones into _Builder_ `b`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTONES\n```\n\n#### `CF42` STSAME\n\nStores `n` binary `x`es (`0 <= x <= 1`) into _Builder_ `b`.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nSTSAME\n```\n\n#### `CF50` BTOS\n\nSame as `ENDC CTOS`, but without gas cost for cell creation and loading.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\nBTOS\n```\n\n#### `CFC_xysss` STSLICECONST\n\nStores a constant subslice `sss`.<br />_Details:_ `sss` consists of `0 <= x <= 3` references and up to `8y+2` data bits, with `0 <= y <= 7`. Completion bit is assumed.<br />Note that the assembler can replace `STSLICECONST` with `PUSHSLICE` `STSLICER` if the slice is too big.<br />\n**Category:** Cell Build (cell_build)<br />\n\n```fift Fift\n[slice] STSLICECONST\n```\n\n**Aliases**:\n- `STZERO`<br />\n  Stores one binary zero.\n- `STONE`<br />\n  Stores one binary one.\n\n#### `D0` CTOS\n\nConverts a _Cell_ into a _Slice_. Notice that `c` must be either an ordinary cell, or an exotic cell which is automatically _loaded_ to yield an ordinary cell `c'`, converted into a _Slice_ afterwards.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nCTOS\n```\n\n#### `D1` ENDS\n\nRemoves a _Slice_ `s` from the stack, and throws an exception if it is not empty.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nENDS\n```\n\n#### `D2cc` LDI\n\nLoads (i.e., parses) a signed `cc+1`-bit integer `x` from _Slice_ `s`, and returns the remainder of `s` as `s'`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[cc+1] LDI\n```\n\n#### `D3cc` LDU\n\nLoads an unsigned `cc+1`-bit integer `x` from _Slice_ `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[cc+1] LDU\n```\n\n#### `D4` LDREF\n\nLoads a cell reference `c` from `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nLDREF\n```\n\n#### `D5` LDREFRTOS\n\nEquivalent to `LDREF` `SWAP` `CTOS`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nLDREFRTOS\n```\n\n#### `D6cc` LDSLICE\n\nCuts the next `cc+1` bits of `s` into a separate _Slice_ `s''`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[cc+1] LDSLICE\n```\n\n#### `D700` LDIX\n\nLoads a signed `l`-bit (`0 <= l <= 257`) integer `x` from _Slice_ `s`, and returns the remainder of `s` as `s'`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nLDIX\n```\n\n#### `D701` LDUX\n\nLoads an unsigned `l`-bit integer `x` from (the first `l` bits of) `s`, with `0 <= l <= 256`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nLDUX\n```\n\n#### `D702` PLDIX\n\nPreloads a signed `l`-bit integer from _Slice_ `s`, for `0 <= l <= 257`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nPLDIX\n```\n\n#### `D703` PLDUX\n\nPreloads an unsigned `l`-bit integer from `s`, for `0 <= l <= 256`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nPLDUX\n```\n\n#### `D704` LDIXQ\n\nQuiet version of `LDIX`: loads a signed `l`-bit integer from `s` similarly to `LDIX`, but returns a success flag, equal to `-1` on success or to `0` on failure (if `s` does not have `l` bits), instead of throwing a cell underflow exception.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nLDIXQ\n```\n\n#### `D705` LDUXQ\n\nQuiet version of `LDUX`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nLDUXQ\n```\n\n#### `D706` PLDIXQ\n\nQuiet version of `PLDIX`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nPLDIXQ\n```\n\n#### `D707` PLDUXQ\n\nQuiet version of `PLDUX`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nPLDUXQ\n```\n\n#### `D708cc` LDI_ALT\n\nA longer encoding for `LDI`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[cc+1] LDI_l\n```\n\n#### `D709cc` LDU_ALT\n\nA longer encoding for `LDU`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[cc+1] LDU_l\n```\n\n#### `D70Acc` PLDI\n\nPreloads a signed `cc+1`-bit integer from _Slice_ `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[cc+1] PLDI\n```\n\n#### `D70Bcc` PLDU\n\nPreloads an unsigned `cc+1`-bit integer from `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[cc+1] PLDU\n```\n\n#### `D70Ccc` LDIQ\n\nA quiet version of `LDI`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[cc+1] LDIQ\n```\n\n#### `D70Dcc` LDUQ\n\nA quiet version of `LDU`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[cc+1] LDUQ\n```\n\n#### `D70Ecc` PLDIQ\n\nA quiet version of `PLDI`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[cc+1] PLDIQ\n```\n\n#### `D70Fcc` PLDUQ\n\nA quiet version of `PLDU`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[cc+1] PLDUQ\n```\n\n#### `D714_c` PLDUZ\n\nPreloads the first `32(c+1)` bits of _Slice_ `s` into an unsigned integer `x`, for `0 <= c <= 7`. If `s` is shorter than necessary, missing bits are assumed to be zero. This operation is intended to be used along with `IFBITJMP` and similar instructions.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[32(c+1)] PLDUZ\n```\n\n#### `D718` LDSLICEX\n\nLoads the first `0 <= l <= 1023` bits from _Slice_ `s` into a separate _Slice_ `s''`, returning the remainder of `s` as `s'`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nLDSLICEX\n```\n\n#### `D719` PLDSLICEX\n\nReturns the first `0 <= l <= 1023` bits of `s` as `s''`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nPLDSLICEX\n```\n\n#### `D71A` LDSLICEXQ\n\nA quiet version of `LDSLICEX`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nLDSLICEXQ\n```\n\n#### `D71B` PLDSLICEXQ\n\nA quiet version of `LDSLICEXQ`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nPLDSLICEXQ\n```\n\n#### `D71Ccc` LDSLICE_ALT\n\nA longer encoding for `LDSLICE`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[cc+1] LDSLICE_l\n```\n\n#### `D71Dcc` PLDSLICE\n\nReturns the first `0 < cc+1 <= 256` bits of `s` as `s''`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[cc+1] PLDSLICE\n```\n\n#### `D71Ecc` LDSLICEQ\n\nA quiet version of `LDSLICE`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[cc+1] LDSLICEQ\n```\n\n#### `D71Fcc` PLDSLICEQ\n\nA quiet version of `PLDSLICE`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[cc+1] PLDSLICEQ\n```\n\n#### `D720` SDCUTFIRST\n\nReturns the first `0 <= l <= 1023` bits of `s`. It is equivalent to `PLDSLICEX`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSDCUTFIRST\n```\n\n#### `D721` SDSKIPFIRST\n\nReturns all but the first `0 <= l <= 1023` bits of `s`. It is equivalent to `LDSLICEX` `NIP`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSDSKIPFIRST\n```\n\n#### `D722` SDCUTLAST\n\nReturns the last `0 <= l <= 1023` bits of `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSDCUTLAST\n```\n\n#### `D723` SDSKIPLAST\n\nReturns all but the last `0 <= l <= 1023` bits of `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSDSKIPLAST\n```\n\n#### `D724` SDSUBSTR\n\nReturns `0 <= l' <= 1023` bits of `s` starting from offset `0 <= l <= 1023`, thus extracting a bit substring out of the data of `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSDSUBSTR\n```\n\n#### `D726` SDBEGINSX\n\nChecks whether `s` begins with (the data bits of) `s'`, and removes `s'` from `s` on success. On failure throws a cell deserialization exception. Primitive `SDPFXREV` can be considered a quiet version of `SDBEGINSX`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSDBEGINSX\n```\n\n#### `D727` SDBEGINSXQ\n\nA quiet version of `SDBEGINSX`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSDBEGINSXQ\n```\n\n#### `D72A_xsss` SDBEGINS\n\nChecks whether `s` begins with constant bitstring `sss` of length `8x+3` (with continuation bit assumed), where `0 <= x <= 127`, and removes `sss` from `s` on success.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[slice] SDBEGINS\n```\n\n#### `D72E_xsss` SDBEGINSQ\n\nA quiet version of `SDBEGINS`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[slice] SDBEGINSQ\n```\n\n#### `D730` SCUTFIRST\n\nReturns the first `0 <= l <= 1023` bits and first `0 <= r <= 4` references of `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSCUTFIRST\n```\n\n#### `D731` SSKIPFIRST\n\nReturns all but the first `l` bits of `s` and `r` references of `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSSKIPFIRST\n```\n\n#### `D732` SCUTLAST\n\nReturns the last `0 <= l <= 1023` data bits and last `0 <= r <= 4` references of `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSCUTLAST\n```\n\n#### `D733` SSKIPLAST\n\nReturns all but the last `l` bits of `s` and `r` references of `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSSKIPLAST\n```\n\n#### `D734` SUBSLICE\n\nReturns `0 <= l' <= 1023` bits and `0 <= r' <= 4` references from _Slice_ `s`, after skipping the first `0 <= l <= 1023` bits and first `0 <= r <= 4` references.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSUBSLICE\n```\n\n#### `D736` SPLIT\n\nSplits the first `0 <= l <= 1023` data bits and first `0 <= r <= 4` references from `s` into `s'`, returning the remainder of `s` as `s''`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSPLIT\n```\n\n#### `D737` SPLITQ\n\nA quiet version of `SPLIT`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSPLITQ\n```\n\n#### `D739` XCTOS\n\nTransforms an ordinary or exotic cell into a _Slice_, as if it were an ordinary cell. A flag is returned indicating whether `c` is exotic. If that be the case, its type can later be deserialized from the first eight bits of `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nXCTOS\n```\n\n#### `D73A` XLOAD\n\nLoads an exotic cell `c` and returns an ordinary cell `c'`. If `c` is already ordinary, does nothing. If `c` cannot be loaded, throws an exception.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nXLOAD\n```\n\n#### `D73B` XLOADQ\n\nLoads an exotic cell `c` and returns an ordinary cell `c'`. If `c` is already ordinary, does nothing. If `c` cannot be loaded, returns 0.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nXLOADQ\n```\n\n#### `D741` SCHKBITS\n\nChecks whether there are at least `l` data bits in _Slice_ `s`. If this is not the case, throws a cell deserialisation (i.e., cell underflow) exception.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSCHKBITS\n```\n\n#### `D742` SCHKREFS\n\nChecks whether there are at least `r` references in _Slice_ `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSCHKREFS\n```\n\n#### `D743` SCHKBITREFS\n\nChecks whether there are at least `l` data bits and `r` references in _Slice_ `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSCHKBITREFS\n```\n\n#### `D745` SCHKBITSQ\n\nChecks whether there are at least `l` data bits in _Slice_ `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSCHKBITSQ\n```\n\n#### `D746` SCHKREFSQ\n\nChecks whether there are at least `r` references in _Slice_ `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSCHKREFSQ\n```\n\n#### `D747` SCHKBITREFSQ\n\nChecks whether there are at least `l` data bits and `r` references in _Slice_ `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSCHKBITREFSQ\n```\n\n#### `D748` PLDREFVAR\n\nReturns the `n`-th cell reference of _Slice_ `s` for `0 <= n <= 3`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nPLDREFVAR\n```\n\n#### `D749` SBITS\n\nReturns the number of data bits in _Slice_ `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSBITS\n```\n\n#### `D74A` SREFS\n\nReturns the number of references in _Slice_ `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSREFS\n```\n\n#### `D74B` SBITREFS\n\nReturns both the number of data bits and the number of references in `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSBITREFS\n```\n\n#### `D74E_n` PLDREFIDX\n\nReturns the `n`-th cell reference of _Slice_ `s`, where `0 <= n <= 3`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[n] PLDREFIDX\n```\n\n**Aliases**:\n- `PLDREF`<br />\n  Preloads the first cell reference of a _Slice_.\n\n#### `D750` LDILE4\n\nLoads a little-endian signed 32-bit integer.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nLDILE4\n```\n\n#### `D751` LDULE4\n\nLoads a little-endian unsigned 32-bit integer.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nLDULE4\n```\n\n#### `D752` LDILE8\n\nLoads a little-endian signed 64-bit integer.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nLDILE8\n```\n\n#### `D753` LDULE8\n\nLoads a little-endian unsigned 64-bit integer.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nLDULE8\n```\n\n#### `D754` PLDILE4\n\nPreloads a little-endian signed 32-bit integer.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nPLDILE4\n```\n\n#### `D755` PLDULE4\n\nPreloads a little-endian unsigned 32-bit integer.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nPLDULE4\n```\n\n#### `D756` PLDILE8\n\nPreloads a little-endian signed 64-bit integer.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nPLDILE8\n```\n\n#### `D757` PLDULE8\n\nPreloads a little-endian unsigned 64-bit integer.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nPLDULE8\n```\n\n#### `D758` LDILE4Q\n\nQuietly loads a little-endian signed 32-bit integer.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nLDILE4Q\n```\n\n#### `D759` LDULE4Q\n\nQuietly loads a little-endian unsigned 32-bit integer.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nLDULE4Q\n```\n\n#### `D75A` LDILE8Q\n\nQuietly loads a little-endian signed 64-bit integer.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nLDILE8Q\n```\n\n#### `D75B` LDULE8Q\n\nQuietly loads a little-endian unsigned 64-bit integer.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nLDULE8Q\n```\n\n#### `D75C` PLDILE4Q\n\nQuietly preloads a little-endian signed 32-bit integer.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nPLDILE4Q\n```\n\n#### `D75D` PLDULE4Q\n\nQuietly preloads a little-endian unsigned 32-bit integer.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nPLDULE4Q\n```\n\n#### `D75E` PLDILE8Q\n\nQuietly preloads a little-endian signed 64-bit integer.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nPLDILE8Q\n```\n\n#### `D75F` PLDULE8Q\n\nQuietly preloads a little-endian unsigned 64-bit integer.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nPLDULE8Q\n```\n\n#### `D760` LDZEROES\n\nReturns the count `n` of leading zero bits in `s`, and removes these bits from `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nLDZEROES\n```\n\n#### `D761` LDONES\n\nReturns the count `n` of leading one bits in `s`, and removes these bits from `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nLDONES\n```\n\n#### `D762` LDSAME\n\nReturns the count `n` of leading bits equal to `0 <= x <= 1` in `s`, and removes these bits from `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nLDSAME\n```\n\n#### `D764` SDEPTH\n\nReturns the depth of _Slice_ `s`. If `s` has no references, then `x=0`; otherwise `x` is one plus the maximum of depths of cells referred to from `s`.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nSDEPTH\n```\n\n#### `D765` CDEPTH\n\nReturns the depth of _Cell_ `c`. If `c` has no references, then `x=0`; otherwise `x` is one plus the maximum of depths of cells referred to from `c`. If `c` is a _Null_ instead of a _Cell_, returns zero.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nCDEPTH\n```\n\n#### `D766` CLEVEL\n\nReturns level of the cell.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nCLEVEL\n```\n\n#### `D767` CLEVELMASK\n\nReturns level mask of the cell.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nCLEVELMASK\n```\n\n#### `D76A_` CHASHI\n\nReturns `i`th hash of the cell.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[i] CHASHI\n```\n\n#### `D76E_` CDEPTHI\n\nReturns `i`th depth of the cell.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\n[i] CDEPTHI\n```\n\n#### `D770` CHASHIX\n\nReturns `i`th hash of the cell.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nCHASHIX\n```\n\n#### `D771` CDEPTHIX\n\nReturns `i`th depth of the cell.<br />\n**Category:** Cell Parse (cell_parse)<br />\n\n```fift Fift\nCDEPTHIX\n```\n\n#### `D8` EXECUTE\n\n_Calls_, or _executes_, continuation `c`.<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\nEXECUTE\nCALLX\n```\n\n#### `D9` JMPX\n\n_Jumps_, or transfers control, to continuation `c`.<br />The remainder of the previous current continuation `cc` is discarded.<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\nJMPX\n```\n\n#### `DApr` CALLXARGS\n\n_Calls_ continuation `c` with `p` parameters and expecting `r` return values<br />`0 <= p <= 15`, `0 <= r <= 15`<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\n[p] [r] CALLXARGS\n```\n\n#### `DB0p` CALLXARGS_VAR\n\n_Calls_ continuation `c` with `0 <= p <= 15` parameters, expecting an arbitrary number of return values.<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\n[p] -1 CALLXARGS\n```\n\n#### `DB1p` JMPXARGS\n\n_Jumps_ to continuation `c`, passing only the top `0 <= p <= 15` values from the current stack to it (the remainder of the current stack is discarded).<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\n[p] JMPXARGS\n```\n\n#### `DB2r` RETARGS\n\n_Returns_ to `c0`, with `0 <= r <= 15` return values taken from the current stack.<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\n[r] RETARGS\n```\n\n#### `DB30` RET\n\n_Returns_ to the continuation at `c0`. The remainder of the current continuation `cc` is discarded.<br />Approximately equivalent to `c0 PUSHCTR` `JMPX`.<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\nRET\nRETTRUE\n```\n\n#### `DB31` RETALT\n\n_Returns_ to the continuation at `c1`.<br />Approximately equivalent to `c1 PUSHCTR` `JMPX`.<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\nRETALT\nRETFALSE\n```\n\n#### `DB32` BRANCH\n\nPerforms `RETTRUE` if integer `f!=0`, or `RETFALSE` if `f=0`.<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\nBRANCH\nRETBOOL\n```\n\n#### `DB34` CALLCC\n\n_Call with current continuation_, transfers control to `c`, pushing the old value of `cc` into `c`'s stack (instead of discarding it or writing it into new `c0`).<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\nCALLCC\n```\n\n#### `DB35` JMPXDATA\n\nSimilar to `CALLCC`, but the remainder of the current continuation (the old value of `cc`) is converted into a _Slice_ before pushing it into the stack of `c`.<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\nJMPXDATA\n```\n\n#### `DB36pr` CALLCCARGS\n\nSimilar to `CALLXARGS`, but pushes the old value of `cc` (along with the top `0 <= p <= 15` values from the original stack) into the stack of newly-invoked continuation `c`, setting `cc.nargs` to `-1 <= r <= 14`.<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\n[p] [r] CALLCCARGS\n```\n\n#### `DB38` CALLXVARARGS\n\nSimilar to `CALLXARGS`, but takes `-1 <= p,r <= 254` from the stack. The next three operations also take `p` and `r` from the stack, both in the range `-1...254`.<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\nCALLXVARARGS\n```\n\n#### `DB39` RETVARARGS\n\nSimilar to `RETARGS`.<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\nRETVARARGS\n```\n\n#### `DB3A` JMPXVARARGS\n\nSimilar to `JMPXARGS`.<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\nJMPXVARARGS\n```\n\n#### `DB3B` CALLCCVARARGS\n\nSimilar to `CALLCCARGS`.<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\nCALLCCVARARGS\n```\n\n#### `DB3C` CALLREF\n\nEquivalent to `PUSHREFCONT` `CALLX`.<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\n[ref] CALLREF\n```\n\n#### `DB3D` JMPREF\n\nEquivalent to `PUSHREFCONT` `JMPX`.<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\n[ref] JMPREF\n```\n\n#### `DB3E` JMPREFDATA\n\nEquivalent to `PUSHREFCONT` `JMPXDATA`.<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\n[ref] JMPREFDATA\n```\n\n#### `DB3F` RETDATA\n\nEquivalent to `c0 PUSHCTR` `JMPXDATA`. In this way, the remainder of the current continuation is converted into a _Slice_ and returned to the caller.<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\nRETDATA\n```\n\n#### `DB4fff` RUNVM\n\nRuns child VM with code `code` and stack `x_1...x_n`. Returns the resulting stack `x'_1...x'_m` and exitcode. Other arguments and return values are enabled by flags.<br /><br />Flags operate similarly to `RUNVMX` in Fift:<br />- `+1`: sets `c3` to code.<br />- `+2`: pushes an implicit `0` before executing the code.<br />- `+4`: takes persistent data `c4` from the stack and returns its final value.<br />- `+8`: takes the gas limit `g_l` from the stack and returns the consumed gas `g_c`.<br />- `+16`: takes `c7` (smart contract context) from the stack.<br />- `+32`: returns the final value of `c5` (actions).<br />- `+64`: pops the hard gas limit `g_m` enabled by `ACCEPT` from the stack.<br />- `+128`: enables \"isolated gas consumption\", meaning the child VM maintains a separate set of visited cells and a `chksgn` counter.<br />- `+256`: pops an integer `r` and ensures exactly `r` values are returned from the top of the stack:<br />  - If `RUNVM` call succeeds and `r` is set, it returns `r` elements. If `r` is not set, it returns all available elements.<br />  - If `RUNVM` is successful but lacks elements on the stack, meaning the stack depth is less than `r`, it is treated as an exception in the child VM. The `exit_code` is set to `-3`, and `exit_arg` is set to `0`, so `0` is returned as the only stack element.<br />  - If `RUNVM` fails with an exception, only one element is returned, `exit_arg`, which should not be confused with `exit_code`.<br />  - In the case of running out of gas, `exit_code` is set to `-14`, and `exit_arg` contains the amount of gas.<br /><br />Gas cost:<br />- 66 gas;<br />- 1 gas for each stack element passed to the child VM (the first 32 elements are free);<br />- 1 gas for each stack element returned from the child VM (the first 32 elements are free).<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\nflags RUNVM\n```\n\n#### `DB50` RUNVMX\n\nRuns child VM with code `code` and stack `x_1...x_n`. Returns the resulting stack `x'_1...x'_m` and exitcode. Other arguments and return values are enabled by flags.<br /><br />Flags operate similarly to `RUNVMX` in Fift:<br />- `+1`: sets `c3` to code.<br />- `+2`: pushes an implicit `0` before executing the code.<br />- `+4`: takes persistent data `c4` from the stack and returns its final value.<br />- `+8`: takes the gas limit `g_l` from the stack and returns the consumed gas `g_c`.<br />- `+16`: takes `c7` (smart contract context) from the stack.<br />- `+32`: returns the final value of `c5` (actions).<br />- `+64`: pops the hard gas limit `g_m` enabled by `ACCEPT` from the stack.<br />- `+128`: enables \"isolated gas consumption\", meaning the child VM maintains a separate set of visited cells and a `chksgn` counter.<br />- `+256`: pops an integer `r` and ensures exactly `r` values are returned from the top of the stack:<br />  - If `RUNVM` call succeeds and `r` is set, it returns `r` elements. If `r` is not set, it returns all available elements.<br />  - If `RUNVM` is successful but lacks elements on the stack, meaning the stack depth is less than `r`, it is treated as an exception in the child VM. The `exit_code` is set to `-3`, and `exit_arg` is set to `0`, so `0` is returned as the only stack element.<br />  - If `RUNVM` fails with an exception, only one element is returned, `exit_arg`, which should not be confused with `exit_code`.<br />  - In the case of running out of gas, `exit_code` is set to `-14`, and `exit_arg` contains the amount of gas.<br /><br />Gas cost:<br />- 66 gas;<br />- 1 gas for each stack element passed to the child VM (the first 32 elements are free);<br />- 1 gas for each stack element returned from the child VM (the first 32 elements are free).<br />\n**Category:** Cont Basic (cont_basic)<br />\n\n```fift Fift\nRUNVMX\n```\n\n#### `DC` IFRET\n\nPerforms a `RET`, but only if integer `f` is non-zero. If `f` is a `NaN`, throws an integer overflow exception.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\nIFRET\nIFNOT:\n```\n\n#### `DD` IFNOTRET\n\nPerforms a `RET`, but only if integer `f` is zero.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\nIFNOTRET\nIF:\n```\n\n#### `DE` IF\n\nPerforms `EXECUTE` for `c` (i.e., _executes_ `c`), but only if integer `f` is non-zero. Otherwise simply discards both values.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\nIF\n```\n\n#### `DF` IFNOT\n\nExecutes continuation `c`, but only if integer `f` is zero. Otherwise simply discards both values.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\nIFNOT\n```\n\n#### `E0` IFJMP\n\nJumps to `c` (similarly to `JMPX`), but only if `f` is non-zero.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\nIFJMP\n```\n\n#### `E1` IFNOTJMP\n\nJumps to `c` (similarly to `JMPX`), but only if `f` is zero.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\nIFNOTJMP\n```\n\n#### `E2` IFELSE\n\nIf integer `f` is non-zero, executes `c`, otherwise executes `c'`. Equivalent to `CONDSELCHK` `EXECUTE`.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\nIFELSE\n```\n\n#### `E300` IFREF\n\nEquivalent to `PUSHREFCONT` `IF`, with the optimization that the cell reference is not actually loaded into a _Slice_ and then converted into an ordinary _Continuation_ if `f=0`.<br />Gas consumption of this primitive depends on whether `f=0` and whether the reference was loaded before.<br />Similar remarks apply other primitives that accept a continuation as a reference.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\n[ref] IFREF\n```\n\n#### `E301` IFNOTREF\n\nEquivalent to `PUSHREFCONT` `IFNOT`.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\n[ref] IFNOTREF\n```\n\n#### `E302` IFJMPREF\n\nEquivalent to `PUSHREFCONT` `IFJMP`.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\n[ref] IFJMPREF\n```\n\n#### `E303` IFNOTJMPREF\n\nEquivalent to `PUSHREFCONT` `IFNOTJMP`.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\n[ref] IFNOTJMPREF\n```\n\n#### `E304` CONDSEL\n\nIf integer `f` is non-zero, returns `x`, otherwise returns `y`. Notice that no type checks are performed on `x` and `y`; as such, it is more like a conditional stack operation. Roughly equivalent to `ROT` `ISZERO` `INC` `ROLLX` `NIP`.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\nCONDSEL\n```\n\n#### `E305` CONDSELCHK\n\nSame as `CONDSEL`, but first checks whether `x` and `y` have the same type.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\nCONDSELCHK\n```\n\n#### `E308` IFRETALT\n\nPerforms `RETALT` if integer `f!=0`.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\nIFRETALT\n```\n\n#### `E309` IFNOTRETALT\n\nPerforms `RETALT` if integer `f=0`.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\nIFNOTRETALT\n```\n\n#### `E30D` IFREFELSE\n\nEquivalent to `PUSHREFCONT` `SWAP` `IFELSE`, with the optimization that the cell reference is not actually loaded into a _Slice_ and then converted into an ordinary _Continuation_ if `f=0`. Similar remarks apply to the next two primitives: cells are converted into continuations only when necessary.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\n[ref] IFREFELSE\n```\n\n#### `E30E` IFELSEREF\n\nEquivalent to `PUSHREFCONT` `IFELSE`.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\n[ref] IFELSEREF\n```\n\n#### `E30F` IFREFELSEREF\n\nEquivalent to `PUSHREFCONT` `PUSHREFCONT` `IFELSE`.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\n[ref] [ref] IFREFELSEREF\n```\n\n#### `E39_n` IFBITJMP\n\nChecks whether bit `0 <= n <= 31` is set in integer `x`, and if so, performs `JMPX` to continuation `c`. Value `x` is left in the stack.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\n[n] IFBITJMP\n```\n\n#### `E3B_n` IFNBITJMP\n\nJumps to `c` if bit `0 <= n <= 31` is not set in integer `x`.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\n[n] IFNBITJMP\n```\n\n#### `E3D_n` IFBITJMPREF\n\nPerforms a `JMPREF` if bit `0 <= n <= 31` is set in integer `x`.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\n[ref] [n] IFBITJMPREF\n```\n\n#### `E3F_n` IFNBITJMPREF\n\nPerforms a `JMPREF` if bit `0 <= n <= 31` is not set in integer `x`.<br />\n**Category:** Cont Conditional (cont_conditional)<br />\n\n```fift Fift\n[ref] [n] IFNBITJMPREF\n```\n\n#### `E4` REPEAT\n\nExecutes continuation `c` `n` times, if integer `n` is non-negative. If `n>=2^31` or `n<-2^31`, generates a range check exception.<br />Notice that a `RET` inside the code of `c` works as a `continue`, not as a `break`. One should use either alternative (experimental) loops or alternative `RETALT` (along with a `SETEXITALT` before the loop) to `break` out of a loop.<br />\n**Category:** Cont Loops (cont_loops)<br />\n\n```fift Fift\nREPEAT\n```\n\n#### `E5` REPEATEND\n\nSimilar to `REPEAT`, but it is applied to the current continuation `cc`.<br />\n**Category:** Cont Loops (cont_loops)<br />\n\n```fift Fift\nREPEATEND\nREPEAT:\n```\n\n#### `E6` UNTIL\n\nExecutes continuation `c`, then pops an integer `x` from the resulting stack. If `x` is zero, performs another iteration of this loop. The actual implementation of this primitive involves an extraordinary continuation `ec_until` with its arguments set to the body of the loop (continuation `c`) and the original current continuation `cc`. This extraordinary continuation is then saved into the savelist of `c` as `c.c0` and the modified `c` is then executed. The other loop primitives are implemented similarly with the aid of suitable extraordinary continuations.<br />\n**Category:** Cont Loops (cont_loops)<br />\n\n```fift Fift\nUNTIL\n```\n\n#### `E7` UNTILEND\n\nSimilar to `UNTIL`, but executes the current continuation `cc` in a loop. When the loop exit condition is satisfied, performs a `RET`.<br />\n**Category:** Cont Loops (cont_loops)<br />\n\n```fift Fift\nUNTILEND\nUNTIL:\n```\n\n#### `E8` WHILE\n\nExecutes `c'` and pops an integer `x` from the resulting stack. If `x` is zero, exists the loop and transfers control to the original `cc`. If `x` is non-zero, executes `c`, and then begins a new iteration.<br />\n**Category:** Cont Loops (cont_loops)<br />\n\n```fift Fift\nWHILE\n```\n\n#### `E9` WHILEEND\n\nSimilar to `WHILE`, but uses the current continuation `cc` as the loop body.<br />\n**Category:** Cont Loops (cont_loops)<br />\n\n```fift Fift\nWHILEEND\n```\n\n#### `EA` AGAIN\n\nSimilar to `REPEAT`, but executes `c` infinitely many times. A `RET` only begins a new iteration of the infinite loop, which can be exited only by an exception, or a `RETALT` (or an explicit `JMPX`).<br />\n**Category:** Cont Loops (cont_loops)<br />\n\n```fift Fift\nAGAIN\n```\n\n#### `EB` AGAINEND\n\nSimilar to `AGAIN`, but performed with respect to the current continuation `cc`.<br />\n**Category:** Cont Loops (cont_loops)<br />\n\n```fift Fift\nAGAINEND\nAGAIN:\n```\n\n#### `E314` REPEATBRK\n\nSimilar to `REPEAT`, but also sets `c1` to the original `cc` after saving the old value of `c1` into the savelist of the original `cc`. In this way `RETALT` could be used to break out of the loop body.<br />\n**Category:** Cont Loops (cont_loops)<br />\n\n```fift Fift\nREPEATBRK\n```\n\n#### `E315` REPEATENDBRK\n\nSimilar to `REPEATEND`, but also sets `c1` to the original `c0` after saving the old value of `c1` into the savelist of the original `c0`. Equivalent to `SAMEALTSAVE` `REPEATEND`.<br />\n**Category:** Cont Loops (cont_loops)<br />\n\n```fift Fift\nREPEATENDBRK\n```\n\n#### `E316` UNTILBRK\n\nSimilar to `UNTIL`, but also modifies `c1` in the same way as `REPEATBRK`.<br />\n**Category:** Cont Loops (cont_loops)<br />\n\n```fift Fift\nUNTILBRK\n```\n\n#### `E317` UNTILENDBRK\n\nEquivalent to `SAMEALTSAVE` `UNTILEND`.<br />\n**Category:** Cont Loops (cont_loops)<br />\n\n```fift Fift\nUNTILENDBRK\nUNTILBRK:\n```\n\n#### `E318` WHILEBRK\n\nSimilar to `WHILE`, but also modifies `c1` in the same way as `REPEATBRK`.<br />\n**Category:** Cont Loops (cont_loops)<br />\n\n```fift Fift\nWHILEBRK\n```\n\n#### `E319` WHILEENDBRK\n\nEquivalent to `SAMEALTSAVE` `WHILEEND`.<br />\n**Category:** Cont Loops (cont_loops)<br />\n\n```fift Fift\nWHILEENDBRK\n```\n\n#### `E31A` AGAINBRK\n\nSimilar to `AGAIN`, but also modifies `c1` in the same way as `REPEATBRK`.<br />\n**Category:** Cont Loops (cont_loops)<br />\n\n```fift Fift\nAGAINBRK\n```\n\n#### `E31B` AGAINENDBRK\n\nEquivalent to `SAMEALTSAVE` `AGAINEND`.<br />\n**Category:** Cont Loops (cont_loops)<br />\n\n```fift Fift\nAGAINENDBRK\nAGAINBRK:\n```\n\n#### `ECrn` SETCONTARGS_N\n\nPushes `0 <= r <= 15` values `x_1...x_r` into the stack of (a copy of) the continuation `c`, starting with `x_1`. When `n` is 15 (-1 in Fift notation), does nothing with `c.nargs`. For `0 <= n <= 14`, sets `c.nargs` to the final size of the stack of `c'` plus `n`. In other words, transforms `c` into a _closure_ or a _partially applied function_, with `0 <= n <= 14` arguments missing.<br />\n**Category:** Cont Stack (cont_stack)<br />\n\n```fift Fift\n[r] [n] SETCONTARGS\n```\n\n**Aliases**:\n- `SETNUMARGS`<br />\n  Sets `c.nargs` to `n` plus the current depth of `c`'s stack, where `0 <= n <= 14`. If `c.nargs` is already set to a non-negative value, does nothing.\n- `SETCONTARGS`<br />\n  Pushes `0 <= r <= 15` values `x_1...x_r` into the stack of (a copy of) the continuation `c`, starting with `x_1`. If the final depth of `c`'s stack turns out to be greater than `c.nargs`, a stack overflow exception is generated.\n\n#### `ED0p` RETURNARGS\n\nLeaves only the top `0 <= p <= 15` values in the current stack (somewhat similarly to `ONLYTOPX`), with all the unused bottom values not discarded, but saved into continuation `c0` in the same way as `SETCONTARGS` does.<br />\n**Category:** Cont Stack (cont_stack)<br />\n\n```fift Fift\n[p] RETURNARGS\n```\n\n#### `ED10` RETURNVARARGS\n\nSimilar to `RETURNARGS`, but with Integer `0 <= p <= 255` taken from the stack.<br />\n**Category:** Cont Stack (cont_stack)<br />\n\n```fift Fift\nRETURNVARARGS\n```\n\n#### `ED11` SETCONTVARARGS\n\nSimilar to `SETCONTARGS`, but with `0 <= r <= 255` and `-1 <= n <= 255` taken from the stack.<br />\n**Category:** Cont Stack (cont_stack)<br />\n\n```fift Fift\nSETCONTVARARGS\n```\n\n#### `ED12` SETNUMVARARGS\n\n`-1 <= n <= 255`<br />If `n=-1`, this operation does nothing (`c'=c`).<br />Otherwise its action is similar to `[n] SETNUMARGS`, but with `n` taken from the stack.<br />\n**Category:** Cont Stack (cont_stack)<br />\n\n```fift Fift\nSETNUMVARARGS\n```\n\n#### `ED1E` BLESS\n\nTransforms a _Slice_ `s` into a simple ordinary continuation `c`, with `c.code=s` and an empty stack and savelist.<br />\n**Category:** Cont Create (cont_create)<br />\n\n```fift Fift\nBLESS\n```\n\n#### `ED1F` BLESSVARARGS\n\nEquivalent to `ROT` `BLESS` `ROTREV` `SETCONTVARARGS`.<br />\n**Category:** Cont Create (cont_create)<br />\n\n```fift Fift\nBLESSVARARGS\n```\n\n#### `EErn` BLESSARGS\n\n`0 <= r <= 15`, `-1 <= n <= 14`<br />Equivalent to `BLESS` `[r] [n] SETCONTARGS`.<br />The value of `n` is represented inside the instruction by the 4-bit integer `n mod 16`.<br />\n**Category:** Cont Create (cont_create)<br />\n\n```fift Fift\n[r] [n] BLESSARGS\n```\n\n**Aliases**:\n- `BLESSNUMARGS`<br />\n  Also transforms a _Slice_ `s` into a _Continuation_ `c`, but sets `c.nargs` to `0 <= n <= 14`.\n\n#### `ED4i` PUSHCTR\n\nPushes the current value of control register `c(i)`. If the control register is not supported in the current codepage, or if it does not have a value, an exception is triggered.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nc[i] PUSHCTR\nc[i] PUSH\n```\n\n**Aliases**:\n- `PUSHROOT`<br />\n  Pushes the ''global data root'' cell reference, thus enabling access to persistent smart-contract data.\n\n#### `ED5i` POPCTR\n\nPops a value `x` from the stack and stores it into control register `c(i)`, if supported in the current codepage. Notice that if a control register accepts only values of a specific type, a type-checking exception may occur.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nc[i] POPCTR\nc[i] POP\n```\n\n**Aliases**:\n- `POPROOT`<br />\n  Sets the ''global data root'' cell reference, thus allowing modification of persistent smart-contract data.\n\n#### `ED6i` SETCONTCTR\n\nStores `x` into the savelist of continuation `c` as `c(i)`, and returns the resulting continuation `c'`. Almost all operations with continuations may be expressed in terms of `SETCONTCTR`, `POPCTR`, and `PUSHCTR`.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nc[i] SETCONT\nc[i] SETCONTCTR\n```\n\n#### `ED7i` SETRETCTR\n\nEquivalent to `c0 PUSHCTR` `c[i] SETCONTCTR` `c0 POPCTR`.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nc[i] SETRETCTR\n```\n\n#### `ED8i` SETALTCTR\n\nEquivalent to `c1 PUSHCTR` `c[i] SETCONTCTR` `c1 POPCTR`.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nc[i] SETALTCTR\n```\n\n#### `ED9i` POPSAVE\n\nSimilar to `c[i] POPCTR`, but also saves the old value of `c[i]` into continuation `c0`.<br />Equivalent (up to exceptions) to `c[i] SAVECTR` `c[i] POPCTR`.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nc[i] POPSAVE\nc[i] POPCTRSAVE\n```\n\n#### `EDAi` SAVE\n\nSaves the current value of `c(i)` into the savelist of continuation `c0`. If an entry for `c[i]` is already present in the savelist of `c0`, nothing is done. Equivalent to `c[i] PUSHCTR` `c[i] SETRETCTR`.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nc[i] SAVE\nc[i] SAVECTR\n```\n\n#### `EDBi` SAVEALT\n\nSimilar to `c[i] SAVE`, but saves the current value of `c[i]` into the savelist of `c1`, not `c0`.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nc[i] SAVEALT\nc[i] SAVEALTCTR\n```\n\n#### `EDCi` SAVEBOTH\n\nEquivalent to `c[i] SAVE` `c[i] SAVEALT`.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nc[i] SAVEBOTH\nc[i] SAVEBOTHCTR\n```\n\n#### `EDE0` PUSHCTRX\n\nSimilar to `c[i] PUSHCTR`, but with `i`, `0 <= i <= 255`, taken from the stack.<br />Notice that this primitive is one of the few ''exotic'' primitives, which are not polymorphic like stack manipulation primitives, and at the same time do not have well-defined types of parameters and return values, because the type of `x` depends on `i`.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nPUSHCTRX\n```\n\n#### `EDE1` POPCTRX\n\nSimilar to `c[i] POPCTR`, but with `0 <= i <= 255` from the stack.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nPOPCTRX\n```\n\n#### `EDE2` SETCONTCTRX\n\nSimilar to `c[i] SETCONTCTR`, but with `0 <= i <= 255` from the stack.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nSETCONTCTRX\n```\n\n#### `EDE3mm` SETCONTCTRMANY\n\nTakes continuation, performs the equivalent of `c[i] PUSHCTR SWAP c[i] SETCONTCNR` for each `i` that is set in `mask` (mask is in `0..255`).<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nSETCONTCTRMANY\nSETCONTMANY\n```\n\n#### `EDE4` SETCONTCTRMANYX\n\nTakes continuation, performs the equivalent of `c[i] PUSHCTR SWAP c[i] SETCONTCNR` for each `i` that is set in `mask` (mask is in `0..255`).<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nSETCONTCTRMANYX\nSETCONTMANYX\n```\n\n#### `EDF0` COMPOS\n\nComputes the composition `compose0(c, c')`, which has the meaning of ''perform `c`, and, if successful, perform `c'`'' (if `c` is a boolean circuit) or simply ''perform `c`, then `c'`''. Equivalent to `SWAP` `c0 SETCONT`.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nCOMPOS\nBOOLAND\n```\n\n#### `EDF1` COMPOSALT\n\nComputes the alternative composition `compose1(c, c')`, which has the meaning of ''perform `c`, and, if not successful, perform `c'`'' (if `c` is a boolean circuit). Equivalent to `SWAP` `c1 SETCONT`.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nCOMPOSALT\nBOOLOR\n```\n\n#### `EDF2` COMPOSBOTH\n\nComputes composition `compose1(compose0(c, c'), c')`, which has the meaning of ''compute boolean circuit `c`, then compute `c'`, regardless of the result of `c`''.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nCOMPOSBOTH\n```\n\n#### `EDF3` ATEXIT\n\nSets `c0` to `compose0(c, c0)`. In other words, `c` will be executed before exiting current subroutine.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nATEXIT\n```\n\n#### `EDF4` ATEXITALT\n\nSets `c1` to `compose1(c, c1)`. In other words, `c` will be executed before exiting current subroutine by its alternative return path.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nATEXITALT\n```\n\n#### `EDF5` SETEXITALT\n\nSets `c1` to `compose1(compose0(c, c0), c1)`,<br />In this way, a subsequent `RETALT` will first execute `c`, then transfer control to the original `c0`. This can be used, for instance, to exit from nested loops.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nSETEXITALT\n```\n\n#### `EDF6` THENRET\n\nComputes `compose0(c, c0)`.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nTHENRET\n```\n\n#### `EDF7` THENRETALT\n\nComputes `compose0(c, c1)`<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nTHENRETALT\n```\n\n#### `EDF8` INVERT\n\nInterchanges `c0` and `c1`.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nINVERT\n```\n\n#### `EDF9` BOOLEVAL\n\nPerforms `cc:=compose1(compose0(c, compose0(-1 PUSHINT, cc)), compose0(0 PUSHINT, cc))`. If `c` represents a boolean circuit, the net effect is to evaluate it and push either `-1` or `0` into the stack before continuing.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nBOOLEVAL\n```\n\n#### `EDFA` SAMEALT\n\nSets `c1` to `c0`. Equivalent to `c0 PUSHCTR` `c1 POPCTR`.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nSAMEALT\n```\n\n#### `EDFB` SAMEALTSAVE\n\nSets `c1` to `c0`, but first saves the old value of `c1` into the savelist of `c0`.<br />Equivalent to `c1 SAVE` `SAMEALT`.<br />\n**Category:** Cont Registers (cont_registers)<br />\n\n```fift Fift\nSAMEALTSAVE\n```\n\n#### `F0nn` CALLDICT\n\nCalls the continuation in `c3`, pushing integer `0 <= nn <= 255` into its stack as an argument.<br />Approximately equivalent to `[nn] PUSHINT` `c3 PUSHCTR` `EXECUTE`.<br />\n**Category:** Cont Dict (cont_dict)<br />\n\n```fift Fift\n[nn] CALL\n[nn] CALLDICT\n```\n\n#### `F12_n` CALLDICT_LONG\n\nFor `0 <= n < 2^14`, an encoding of `[n] CALL` for larger values of `n`.<br />\n**Category:** Cont Dict (cont_dict)<br />\n\n```fift Fift\n[n] CALL\n[n] CALLDICT\n```\n\n#### `F16_n` JMPDICT\n\nJumps to the continuation in `c3`, pushing integer `0 <= n < 2^14` as its argument.<br />Approximately equivalent to `n PUSHINT` `c3 PUSHCTR` `JMPX`.<br />\n**Category:** Cont Dict (cont_dict)<br />\n\n```fift Fift\n[n] JMP\n```\n\n#### `F1A_n` PREPAREDICT\n\nEquivalent to `n PUSHINT` `c3 PUSHCTR`, for `0 <= n < 2^14`.<br />In this way, `[n] CALL` is approximately equivalent to `[n] PREPARE` `EXECUTE`, and `[n] JMP` is approximately equivalent to `[n] PREPARE` `JMPX`.<br />One might use, for instance, `CALLXARGS` or `CALLCC` instead of `EXECUTE` here.<br />\n**Category:** Cont Dict (cont_dict)<br />\n\n```fift Fift\n[n] PREPARE\n[n] PREPAREDICT\n```\n\n#### `F22_n` THROW_SHORT\n\nThrows exception `0 <= n <= 63` with parameter zero.<br />In other words, it transfers control to the continuation in `c2`, pushing `0` and `n` into its stack, and discarding the old stack altogether.<br />\n**Category:** Exceptions (exceptions)<br />\n\n```fift Fift\n[n] THROW\n```\n\n#### `F26_n` THROWIF_SHORT\n\nThrows exception `0 <= n <= 63` with  parameter zero only if integer `f!=0`.<br />\n**Category:** Exceptions (exceptions)<br />\n\n```fift Fift\n[n] THROWIF\n```\n\n#### `F2A_n` THROWIFNOT_SHORT\n\nThrows exception `0 <= n <= 63` with parameter zero only if integer `f=0`.<br />\n**Category:** Exceptions (exceptions)<br />\n\n```fift Fift\n[n] THROWIFNOT\n```\n\n#### `F2C4_n` THROW\n\nFor `0 <= n < 2^11`, an encoding of `[n] THROW` for larger values of `n`.<br />\n**Category:** Exceptions (exceptions)<br />\n\n```fift Fift\n[n] THROW\n```\n\n#### `F2CC_n` THROWARG\n\nThrows exception `0 <= n <  2^11` with parameter `x`, by copying `x` and `n` into the stack of `c2` and transferring control to `c2`.<br />\n**Category:** Exceptions (exceptions)<br />\n\n```fift Fift\n[n] THROWARG\n```\n\n#### `F2D4_n` THROWIF\n\nFor `0 <= n < 2^11`, an encoding of `[n] THROWIF` for larger values of `n`.<br />\n**Category:** Exceptions (exceptions)<br />\n\n```fift Fift\n[n] THROWIF\n```\n\n#### `F2DC_n` THROWARGIF\n\nThrows exception `0 <= nn < 2^11` with parameter `x` only if integer `f!=0`.<br />\n**Category:** Exceptions (exceptions)<br />\n\n```fift Fift\n[n] THROWARGIF\n```\n\n#### `F2E4_n` THROWIFNOT\n\nFor `0 <= n < 2^11`, an encoding of `[n] THROWIFNOT` for larger values of `n`.<br />\n**Category:** Exceptions (exceptions)<br />\n\n```fift Fift\n[n] THROWIFNOT\n```\n\n#### `F2EC_n` THROWARGIFNOT\n\nThrows exception `0 <= n < 2^11` with parameter `x` only if integer `f=0`.<br />\n**Category:** Exceptions (exceptions)<br />\n\n```fift Fift\n[n] THROWARGIFNOT\n```\n\n#### `F2F0` THROWANY\n\nThrows exception `0 <= n < 2^16` with parameter zero.<br />Approximately equivalent to `ZERO` `SWAP` `THROWARGANY`.<br />\n**Category:** Exceptions (exceptions)<br />\n\n```fift Fift\nTHROWANY\n```\n\n#### `F2F1` THROWARGANY\n\nThrows exception `0 <= n < 2^16` with parameter `x`, transferring control to the continuation in `c2`.<br />Approximately equivalent to `c2 PUSHCTR` `2 JMPXARGS`.<br />\n**Category:** Exceptions (exceptions)<br />\n\n```fift Fift\nTHROWARGANY\n```\n\n#### `F2F2` THROWANYIF\n\nThrows exception `0 <= n < 2^16` with parameter zero only if `f!=0`.<br />\n**Category:** Exceptions (exceptions)<br />\n\n```fift Fift\nTHROWANYIF\n```\n\n#### `F2F3` THROWARGANYIF\n\nThrows exception `0 <= n<2^16` with parameter `x` only if `f!=0`.<br />\n**Category:** Exceptions (exceptions)<br />\n\n```fift Fift\nTHROWARGANYIF\n```\n\n#### `F2F4` THROWANYIFNOT\n\nThrows exception `0 <= n<2^16` with parameter zero only if `f=0`.<br />\n**Category:** Exceptions (exceptions)<br />\n\n```fift Fift\nTHROWANYIFNOT\n```\n\n#### `F2F5` THROWARGANYIFNOT\n\nThrows exception `0 <= n<2^16` with parameter `x` only if `f=0`.<br />\n**Category:** Exceptions (exceptions)<br />\n\n```fift Fift\nTHROWARGANYIFNOT\n```\n\n#### `F2FF` TRY\n\nSets `c2` to `c'`, first saving the old value of `c2` both into the savelist of `c'` and into the savelist of the current continuation, which is stored into `c.c0` and `c'.c0`. Then runs `c` similarly to `EXECUTE`. If `c` does not throw any exceptions, the original value of `c2` is automatically restored on return from `c`. If an exception occurs, the execution is transferred to `c'`, but the original value of `c2` is restored in the process, so that `c'` can re-throw the exception by `THROWANY` if it cannot handle it by itself.<br />\n**Category:** Exceptions (exceptions)<br />\n\n```fift Fift\nTRY\n```\n\n#### `F3pr` TRYARGS\n\nSimilar to `TRY`, but with `[p] [r] CALLXARGS` internally used instead of `EXECUTE`.<br />In this way, all but the top `0 <= p <= 15` stack elements will be saved into current continuation's stack, and then restored upon return from either `c` or `c'`, with the top `0 <= r <= 15` values of the resulting stack of `c` or `c'` copied as return values.<br />\n**Category:** Exceptions (exceptions)<br />\n\n```fift Fift\n[p] [r] TRYARGS\n```\n\n#### `F400` STDICT\n\nStores dictionary `D` into _Builder_ `b`, returning the resulting _Builder_ `b'`.<br />In other words, if `D` is a cell, performs `STONE` and `STREF`; if `D` is _Null_, performs `NIP` and `STZERO`; otherwise throws a type checking exception.<br />\n**Category:** Dict Serial (dict_serial)<br />\n\n```fift Fift\nSTDICT\nSTOPTREF\n```\n\n#### `F401` SKIPDICT\n\nEquivalent to `LDDICT` `NIP`.<br />\n**Category:** Dict Serial (dict_serial)<br />\n\n```fift Fift\nSKIPDICT\nSKIPOPTREF\n```\n\n#### `F402` LDDICTS\n\nLoads (parses) a (_Slice_-represented) dictionary `s'` from _Slice_ `s`, and returns the remainder of `s` as `s''`.<br />This is a ''split function'' for all `HashmapE(n,X)` dictionary types.<br />\n**Category:** Dict Serial (dict_serial)<br />\n\n```fift Fift\nLDDICTS\n```\n\n#### `F403` PLDDICTS\n\nPreloads a (_Slice_-represented) dictionary `s'` from _Slice_ `s`.<br />Approximately equivalent to `LDDICTS` `DROP`.<br />\n**Category:** Dict Serial (dict_serial)<br />\n\n```fift Fift\nPLDDICTS\n```\n\n#### `F404` LDDICT\n\nLoads (parses) a dictionary `D` from _Slice_ `s`, and returns the remainder of `s` as `s'`. May be applied to dictionaries or to values of arbitrary `(^Y)?` types.<br />\n**Category:** Dict Serial (dict_serial)<br />\n\n```fift Fift\nLDDICT\nLDOPTREF\n```\n\n#### `F405` PLDDICT\n\nPreloads a dictionary `D` from _Slice_ `s`.<br />Approximately equivalent to `LDDICT` `DROP`.<br />\n**Category:** Dict Serial (dict_serial)<br />\n\n```fift Fift\nPLDDICT\nPLDOPTREF\n```\n\n#### `F406` LDDICTQ\n\nA quiet version of `LDDICT`.<br />\n**Category:** Dict Serial (dict_serial)<br />\n\n```fift Fift\nLDDICTQ\n```\n\n#### `F407` PLDDICTQ\n\nA quiet version of `PLDDICT`.<br />\n**Category:** Dict Serial (dict_serial)<br />\n\n```fift Fift\nPLDDICTQ\n```\n\n#### `F40A` DICTGET\n\nLooks up key `k` (represented by a _Slice_, the first `0 <= n <= 1023` data bits of which are used as a key) in dictionary `D` of type `HashmapE(n,X)` with `n`-bit keys.<br />On success, returns the value found as a _Slice_ `x`.<br />\n**Category:** Dict Get (dict_get)<br />\n\n```fift Fift\nDICTGET\n```\n\n#### `F40B` DICTGETREF\n\nSimilar to `DICTGET`, but with a `LDREF` `ENDS` applied to `x` on success.<br />This operation is useful for dictionaries of type `HashmapE(n,^Y)`.<br />\n**Category:** Dict Get (dict_get)<br />\n\n```fift Fift\nDICTGETREF\n```\n\n#### `F40C` DICTIGET\n\nSimilar to `DICTGET`, but with a signed (big-endian) `n`-bit _Integer_ `i` as a key. If `i` does not fit into `n` bits, returns `0`. If `i` is a `NaN`, throws an integer overflow exception.<br />\n**Category:** Dict Get (dict_get)<br />\n\n```fift Fift\nDICTIGET\n```\n\n#### `F40D` DICTIGETREF\n\nCombines `DICTIGET` with `DICTGETREF`: it uses signed `n`-bit _Integer_ `i` as a key and returns a _Cell_ instead of a _Slice_ on success.<br />\n**Category:** Dict Get (dict_get)<br />\n\n```fift Fift\nDICTIGETREF\n```\n\n#### `F40E` DICTUGET\n\nSimilar to `DICTIGET`, but with _unsigned_ (big-endian) `n`-bit _Integer_ `i` used as a key.<br />\n**Category:** Dict Get (dict_get)<br />\n\n```fift Fift\nDICTUGET\n```\n\n#### `F40F` DICTUGETREF\n\nSimilar to `DICTIGETREF`, but with an unsigned `n`-bit _Integer_ key `i`.<br />\n**Category:** Dict Get (dict_get)<br />\n\n```fift Fift\nDICTUGETREF\n```\n\n#### `F412` DICTSET\n\nSets the value associated with `n`-bit key `k` (represented by a _Slice_ as in `DICTGET`) in dictionary `D` (also represented by a _Slice_) to value `x` (again a _Slice_), and returns the resulting dictionary as `D'`.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTSET\n```\n\n#### `F413` DICTSETREF\n\nSimilar to `DICTSET`, but with the value set to a reference to _Cell_ `c`.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTSETREF\n```\n\n#### `F414` DICTISET\n\nSimilar to `DICTSET`, but with the key represented by a (big-endian) signed `n`-bit integer `i`. If `i` does not fit into `n` bits, a range check exception is generated.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTISET\n```\n\n#### `F415` DICTISETREF\n\nSimilar to `DICTSETREF`, but with the key a signed `n`-bit integer as in `DICTISET`.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTISETREF\n```\n\n#### `F416` DICTUSET\n\nSimilar to `DICTISET`, but with `i` an _unsigned_ `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTUSET\n```\n\n#### `F417` DICTUSETREF\n\nSimilar to `DICTISETREF`, but with `i` unsigned.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTUSETREF\n```\n\n#### `F41A` DICTSETGET\n\nCombines `DICTSET` with `DICTGET`: it sets the value corresponding to key `k` to `x`, but also returns the old value `y` associated with the key in question, if present.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTSETGET\n```\n\n#### `F41B` DICTSETGETREF\n\nCombines `DICTSETREF` with `DICTGETREF` similarly to `DICTSETGET`.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTSETGETREF\n```\n\n#### `F41C` DICTISETGET\n\n`DICTISETGET`, but with `i` a signed `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTISETGET\n```\n\n#### `F41D` DICTISETGETREF\n\n`DICTISETGETREF`, but with `i` a signed `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTISETGETREF\n```\n\n#### `F41E` DICTUSETGET\n\n`DICTISETGET`, but with `i` an unsigned `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTUSETGET\n```\n\n#### `F41F` DICTUSETGETREF\n\n`DICTISETGETREF`, but with `i` an unsigned `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTUSETGETREF\n```\n\n#### `F422` DICTREPLACE\n\nA _Replace_ operation, which is similar to `DICTSET`, but sets the value of key `k` in dictionary `D` to `x` only if the key `k` was already present in `D`.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTREPLACE\n```\n\n#### `F423` DICTREPLACEREF\n\nA _Replace_ counterpart of `DICTSETREF`.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTREPLACEREF\n```\n\n#### `F424` DICTIREPLACE\n\n`DICTREPLACE`, but with `i` a signed `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTIREPLACE\n```\n\n#### `F425` DICTIREPLACEREF\n\n`DICTREPLACEREF`, but with `i` a signed `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTIREPLACEREF\n```\n\n#### `F426` DICTUREPLACE\n\n`DICTREPLACE`, but with `i` an unsigned `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTUREPLACE\n```\n\n#### `F427` DICTUREPLACEREF\n\n`DICTREPLACEREF`, but with `i` an unsigned `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTUREPLACEREF\n```\n\n#### `F42A` DICTREPLACEGET\n\nA _Replace_ counterpart of `DICTSETGET`: on success, also returns the old value associated with the key in question.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTREPLACEGET\n```\n\n#### `F42B` DICTREPLACEGETREF\n\nA _Replace_ counterpart of `DICTSETGETREF`.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTREPLACEGETREF\n```\n\n#### `F42C` DICTIREPLACEGET\n\n`DICTREPLACEGET`, but with `i` a signed `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTIREPLACEGET\n```\n\n#### `F42D` DICTIREPLACEGETREF\n\n`DICTREPLACEGETREF`, but with `i` a signed `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTIREPLACEGETREF\n```\n\n#### `F42E` DICTUREPLACEGET\n\n`DICTREPLACEGET`, but with `i` an unsigned `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTUREPLACEGET\n```\n\n#### `F42F` DICTUREPLACEGETREF\n\n`DICTREPLACEGETREF`, but with `i` an unsigned `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTUREPLACEGETREF\n```\n\n#### `F432` DICTADD\n\nAn _Add_ counterpart of `DICTSET`: sets the value associated with key `k` in dictionary `D` to `x`, but only if it is not already present in `D`.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTADD\n```\n\n#### `F433` DICTADDREF\n\nAn _Add_ counterpart of `DICTSETREF`.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTADDREF\n```\n\n#### `F434` DICTIADD\n\n`DICTADD`, but with `i` a signed `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTIADD\n```\n\n#### `F435` DICTIADDREF\n\n`DICTADDREF`, but with `i` a signed `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTIADDREF\n```\n\n#### `F436` DICTUADD\n\n`DICTADD`, but with `i` an unsigned `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTUADD\n```\n\n#### `F437` DICTUADDREF\n\n`DICTADDREF`, but with `i` an unsigned `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTUADDREF\n```\n\n#### `F43A` DICTADDGET\n\nAn _Add_ counterpart of `DICTSETGET`: sets the value associated with key `k` in dictionary `D` to `x`, but only if key `k` is not already present in `D`. Otherwise, just returns the old value `y` without changing the dictionary.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTADDGET\n```\n\n#### `F43B` DICTADDGETREF\n\nAn _Add_ counterpart of `DICTSETGETREF`.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTADDGETREF\n```\n\n#### `F43C` DICTIADDGET\n\n`DICTADDGET`, but with `i` a signed `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTIADDGET\n```\n\n#### `F43D` DICTIADDGETREF\n\n`DICTADDGETREF`, but with `i` a signed `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTIADDGETREF\n```\n\n#### `F43E` DICTUADDGET\n\n`DICTADDGET`, but with `i` an unsigned `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTUADDGET\n```\n\n#### `F43F` DICTUADDGETREF\n\n`DICTADDGETREF`, but with `i` an unsigned `n`-bit integer.<br />\n**Category:** Dict Set (dict_set)<br />\n\n```fift Fift\nDICTUADDGETREF\n```\n\n#### `F441` DICTSETB\n\n<br />\n**Category:** Dict Set Builder (dict_set_builder)<br />\n\n```fift Fift\nDICTSETB\n```\n\n#### `F442` DICTISETB\n\n<br />\n**Category:** Dict Set Builder (dict_set_builder)<br />\n\n```fift Fift\nDICTISETB\n```\n\n#### `F443` DICTUSETB\n\n<br />\n**Category:** Dict Set Builder (dict_set_builder)<br />\n\n```fift Fift\nDICTUSETB\n```\n\n#### `F445` DICTSETGETB\n\n<br />\n**Category:** Dict Set Builder (dict_set_builder)<br />\n\n```fift Fift\nDICTSETGETB\n```\n\n#### `F446` DICTISETGETB\n\n<br />\n**Category:** Dict Set Builder (dict_set_builder)<br />\n\n```fift Fift\nDICTISETGETB\n```\n\n#### `F447` DICTUSETGETB\n\n<br />\n**Category:** Dict Set Builder (dict_set_builder)<br />\n\n```fift Fift\nDICTUSETGETB\n```\n\n#### `F449` DICTREPLACEB\n\n<br />\n**Category:** Dict Set Builder (dict_set_builder)<br />\n\n```fift Fift\nDICTREPLACEB\n```\n\n#### `F44A` DICTIREPLACEB\n\n<br />\n**Category:** Dict Set Builder (dict_set_builder)<br />\n\n```fift Fift\nDICTIREPLACEB\n```\n\n#### `F44B` DICTUREPLACEB\n\n<br />\n**Category:** Dict Set Builder (dict_set_builder)<br />\n\n```fift Fift\nDICTUREPLACEB\n```\n\n#### `F44D` DICTREPLACEGETB\n\n<br />\n**Category:** Dict Set Builder (dict_set_builder)<br />\n\n```fift Fift\nDICTREPLACEGETB\n```\n\n#### `F44E` DICTIREPLACEGETB\n\n<br />\n**Category:** Dict Set Builder (dict_set_builder)<br />\n\n```fift Fift\nDICTIREPLACEGETB\n```\n\n#### `F44F` DICTUREPLACEGETB\n\n<br />\n**Category:** Dict Set Builder (dict_set_builder)<br />\n\n```fift Fift\nDICTUREPLACEGETB\n```\n\n#### `F451` DICTADDB\n\n<br />\n**Category:** Dict Set Builder (dict_set_builder)<br />\n\n```fift Fift\nDICTADDB\n```\n\n#### `F452` DICTIADDB\n\n<br />\n**Category:** Dict Set Builder (dict_set_builder)<br />\n\n```fift Fift\nDICTIADDB\n```\n\n#### `F453` DICTUADDB\n\n<br />\n**Category:** Dict Set Builder (dict_set_builder)<br />\n\n```fift Fift\nDICTUADDB\n```\n\n#### `F455` DICTADDGETB\n\n<br />\n**Category:** Dict Set Builder (dict_set_builder)<br />\n\n```fift Fift\nDICTADDGETB\n```\n\n#### `F456` DICTIADDGETB\n\n<br />\n**Category:** Dict Set Builder (dict_set_builder)<br />\n\n```fift Fift\nDICTIADDGETB\n```\n\n#### `F457` DICTUADDGETB\n\n<br />\n**Category:** Dict Set Builder (dict_set_builder)<br />\n\n```fift Fift\nDICTUADDGETB\n```\n\n#### `F459` DICTDEL\n\nDeletes `n`-bit key, represented by a _Slice_ `k`, from dictionary `D`. If the key is present, returns the modified dictionary `D'` and the success flag `-1`. Otherwise, returns the original dictionary `D` and `0`.<br />\n**Category:** Dict Delete (dict_delete)<br />\n\n```fift Fift\nDICTDEL\n```\n\n#### `F45A` DICTIDEL\n\nA version of `DICTDEL` with the key represented by a signed `n`-bit _Integer_ `i`. If `i` does not fit into `n` bits, simply returns `D` `0` (''key not found, dictionary unmodified'').<br />\n**Category:** Dict Delete (dict_delete)<br />\n\n```fift Fift\nDICTIDEL\n```\n\n#### `F45B` DICTUDEL\n\nSimilar to `DICTIDEL`, but with `i` an unsigned `n`-bit integer.<br />\n**Category:** Dict Delete (dict_delete)<br />\n\n```fift Fift\nDICTUDEL\n```\n\n#### `F462` DICTDELGET\n\nDeletes `n`-bit key, represented by a _Slice_ `k`, from dictionary `D`. If the key is present, returns the modified dictionary `D'`, the original value `x` associated with the key `k` (represented by a _Slice_), and the success flag `-1`. Otherwise, returns the original dictionary `D` and `0`.<br />\n**Category:** Dict Delete (dict_delete)<br />\n\n```fift Fift\nDICTDELGET\n```\n\n#### `F463` DICTDELGETREF\n\nSimilar to `DICTDELGET`, but with `LDREF` `ENDS` applied to `x` on success, so that the value returned `c` is a _Cell_.<br />\n**Category:** Dict Delete (dict_delete)<br />\n\n```fift Fift\nDICTDELGETREF\n```\n\n#### `F464` DICTIDELGET\n\n`DICTDELGET`, but with `i` a signed `n`-bit integer.<br />\n**Category:** Dict Delete (dict_delete)<br />\n\n```fift Fift\nDICTIDELGET\n```\n\n#### `F465` DICTIDELGETREF\n\n`DICTDELGETREF`, but with `i` a signed `n`-bit integer.<br />\n**Category:** Dict Delete (dict_delete)<br />\n\n```fift Fift\nDICTIDELGETREF\n```\n\n#### `F466` DICTUDELGET\n\n`DICTDELGET`, but with `i` an unsigned `n`-bit integer.<br />\n**Category:** Dict Delete (dict_delete)<br />\n\n```fift Fift\nDICTUDELGET\n```\n\n#### `F467` DICTUDELGETREF\n\n`DICTDELGETREF`, but with `i` an unsigned `n`-bit integer.<br />\n**Category:** Dict Delete (dict_delete)<br />\n\n```fift Fift\nDICTUDELGETREF\n```\n\n#### `F469` DICTGETOPTREF\n\nA variant of `DICTGETREF` that returns _Null_ instead of the value `c^?` if the key `k` is absent from dictionary `D`.<br />\n**Category:** Dict Mayberef (dict_mayberef)<br />\n\n```fift Fift\nDICTGETOPTREF\n```\n\n#### `F46A` DICTIGETOPTREF\n\n`DICTGETOPTREF`, but with `i` a signed `n`-bit integer. If the key `i` is out of range, also returns _Null_.<br />\n**Category:** Dict Mayberef (dict_mayberef)<br />\n\n```fift Fift\nDICTIGETOPTREF\n```\n\n#### `F46B` DICTUGETOPTREF\n\n`DICTGETOPTREF`, but with `i` an unsigned `n`-bit integer. If the key `i` is out of range, also returns _Null_.<br />\n**Category:** Dict Mayberef (dict_mayberef)<br />\n\n```fift Fift\nDICTUGETOPTREF\n```\n\n#### `F46D` DICTSETGETOPTREF\n\nA variant of both `DICTGETOPTREF` and `DICTSETGETREF` that sets the value corresponding to key `k` in dictionary `D` to `c^?` (if `c^?` is _Null_, then the key is deleted instead), and returns the old value `~c^?` (if the key `k` was absent before, returns _Null_ instead).<br />\n**Category:** Dict Mayberef (dict_mayberef)<br />\n\n```fift Fift\nDICTSETGETOPTREF\n```\n\n#### `F46E` DICTISETGETOPTREF\n\nSimilar to primitive `DICTSETGETOPTREF`, but using signed `n`-bit _Integer_ `i` as a key. If `i` does not fit into `n` bits, throws a range checking exception.<br />\n**Category:** Dict Mayberef (dict_mayberef)<br />\n\n```fift Fift\nDICTISETGETOPTREF\n```\n\n#### `F46F` DICTUSETGETOPTREF\n\nSimilar to primitive `DICTSETGETOPTREF`, but using unsigned `n`-bit _Integer_ `i` as a key.<br />\n**Category:** Dict Mayberef (dict_mayberef)<br />\n\n```fift Fift\nDICTUSETGETOPTREF\n```\n\n#### `F470` PFXDICTSET\n\n<br />\n**Category:** Dict Prefix (dict_prefix)<br />\n\n```fift Fift\nPFXDICTSET\n```\n\n#### `F471` PFXDICTREPLACE\n\n<br />\n**Category:** Dict Prefix (dict_prefix)<br />\n\n```fift Fift\nPFXDICTREPLACE\n```\n\n#### `F472` PFXDICTADD\n\n<br />\n**Category:** Dict Prefix (dict_prefix)<br />\n\n```fift Fift\nPFXDICTADD\n```\n\n#### `F473` PFXDICTDEL\n\n<br />\n**Category:** Dict Prefix (dict_prefix)<br />\n\n```fift Fift\nPFXDICTDEL\n```\n\n#### `F474` DICTGETNEXT\n\nComputes the minimal key `k'` in dictionary `D` that is lexicographically greater than `k`, and returns `k'` (represented by a _Slice_) along with associated value `x'` (also represented by a _Slice_).<br />\n**Category:** Dict Next (dict_next)<br />\n\n```fift Fift\nDICTGETNEXT\n```\n\n#### `F475` DICTGETNEXTEQ\n\nSimilar to `DICTGETNEXT`, but computes the minimal key `k'` that is lexicographically greater than or equal to `k`.<br />\n**Category:** Dict Next (dict_next)<br />\n\n```fift Fift\nDICTGETNEXTEQ\n```\n\n#### `F476` DICTGETPREV\n\nSimilar to `DICTGETNEXT`, but computes the maximal key `k'` lexicographically smaller than `k`.<br />\n**Category:** Dict Next (dict_next)<br />\n\n```fift Fift\nDICTGETPREV\n```\n\n#### `F477` DICTGETPREVEQ\n\nSimilar to `DICTGETPREV`, but computes the maximal key `k'` lexicographically smaller than or equal to `k`.<br />\n**Category:** Dict Next (dict_next)<br />\n\n```fift Fift\nDICTGETPREVEQ\n```\n\n#### `F478` DICTIGETNEXT\n\nSimilar to `DICTGETNEXT`, but interprets all keys in dictionary `D` as big-endian signed `n`-bit integers, and computes the minimal key `i'` that is larger than _Integer_ `i` (which does not necessarily fit into `n` bits).<br />\n**Category:** Dict Next (dict_next)<br />\n\n```fift Fift\nDICTIGETNEXT\n```\n\n#### `F479` DICTIGETNEXTEQ\n\nSimilar to `DICTGETNEXTEQ`, but interprets keys as signed `n`-bit integers.<br />\n**Category:** Dict Next (dict_next)<br />\n\n```fift Fift\nDICTIGETNEXTEQ\n```\n\n#### `F47A` DICTIGETPREV\n\nSimilar to `DICTGETPREV`, but interprets keys as signed `n`-bit integers.<br />\n**Category:** Dict Next (dict_next)<br />\n\n```fift Fift\nDICTIGETPREV\n```\n\n#### `F47B` DICTIGETPREVEQ\n\nSimilar to `DICTGETPREVEQ`, but interprets keys as signed `n`-bit integers.<br />\n**Category:** Dict Next (dict_next)<br />\n\n```fift Fift\nDICTIGETPREVEQ\n```\n\n#### `F47C` DICTUGETNEXT\n\nSimilar to `DICTGETNEXT`, but interprets all keys in dictionary `D` as big-endian unsigned `n`-bit integers, and computes the minimal key `i'` that is larger than _Integer_ `i` (which does not necessarily fit into `n` bits, and is not necessarily non-negative).<br />\n**Category:** Dict Next (dict_next)<br />\n\n```fift Fift\nDICTUGETNEXT\n```\n\n#### `F47D` DICTUGETNEXTEQ\n\nSimilar to `DICTGETNEXTEQ`, but interprets keys as unsigned `n`-bit integers.<br />\n**Category:** Dict Next (dict_next)<br />\n\n```fift Fift\nDICTUGETNEXTEQ\n```\n\n#### `F47E` DICTUGETPREV\n\nSimilar to `DICTGETPREV`, but interprets keys as unsigned `n`-bit integers.<br />\n**Category:** Dict Next (dict_next)<br />\n\n```fift Fift\nDICTUGETPREV\n```\n\n#### `F47F` DICTUGETPREVEQ\n\nSimilar to `DICTGETPREVEQ`, but interprets keys a unsigned `n`-bit integers.<br />\n**Category:** Dict Next (dict_next)<br />\n\n```fift Fift\nDICTUGETPREVEQ\n```\n\n#### `F482` DICTMIN\n\nComputes the minimal key `k` (represented by a _Slice_ with `n` data bits) in dictionary `D`, and returns `k` along with the associated value `x`.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTMIN\n```\n\n#### `F483` DICTMINREF\n\nSimilar to `DICTMIN`, but returns the only reference in the value as a _Cell_ `c`.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTMINREF\n```\n\n#### `F484` DICTIMIN\n\nSimilar to `DICTMIN`, but computes the minimal key `i` under the assumption that all keys are big-endian signed `n`-bit integers. Notice that the key and value returned may differ from those computed by `DICTMIN` and `DICTUMIN`.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTIMIN\n```\n\n#### `F485` DICTIMINREF\n\nSimilar to `DICTIMIN`, but returns the only reference in the value.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTIMINREF\n```\n\n#### `F486` DICTUMIN\n\nSimilar to `DICTMIN`, but returns the key as an unsigned `n`-bit _Integer_ `i`.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTUMIN\n```\n\n#### `F487` DICTUMINREF\n\nSimilar to `DICTUMIN`, but returns the only reference in the value.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTUMINREF\n```\n\n#### `F48A` DICTMAX\n\nComputes the maximal key `k` (represented by a _Slice_ with `n` data bits) in dictionary `D`, and returns `k` along with the associated value `x`.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTMAX\n```\n\n#### `F48B` DICTMAXREF\n\nSimilar to `DICTMAX`, but returns the only reference in the value.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTMAXREF\n```\n\n#### `F48C` DICTIMAX\n\nSimilar to `DICTMAX`, but computes the maximal key `i` under the assumption that all keys are big-endian signed `n`-bit integers. Notice that the key and value returned may differ from those computed by `DICTMAX` and `DICTUMAX`.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTIMAX\n```\n\n#### `F48D` DICTIMAXREF\n\nSimilar to `DICTIMAX`, but returns the only reference in the value.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTIMAXREF\n```\n\n#### `F48E` DICTUMAX\n\nSimilar to `DICTMAX`, but returns the key as an unsigned `n`-bit _Integer_ `i`.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTUMAX\n```\n\n#### `F48F` DICTUMAXREF\n\nSimilar to `DICTUMAX`, but returns the only reference in the value.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTUMAXREF\n```\n\n#### `F492` DICTREMMIN\n\nComputes the minimal key `k` (represented by a _Slice_ with `n` data bits) in dictionary `D`, removes `k` from the dictionary, and returns `k` along with the associated value `x` and the modified dictionary `D'`.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTREMMIN\n```\n\n#### `F493` DICTREMMINREF\n\nSimilar to `DICTREMMIN`, but returns the only reference in the value as a _Cell_ `c`.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTREMMINREF\n```\n\n#### `F494` DICTIREMMIN\n\nSimilar to `DICTREMMIN`, but computes the minimal key `i` under the assumption that all keys are big-endian signed `n`-bit integers. Notice that the key and value returned may differ from those computed by `DICTREMMIN` and `DICTUREMMIN`.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTIREMMIN\n```\n\n#### `F495` DICTIREMMINREF\n\nSimilar to `DICTIREMMIN`, but returns the only reference in the value.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTIREMMINREF\n```\n\n#### `F496` DICTUREMMIN\n\nSimilar to `DICTREMMIN`, but returns the key as an unsigned `n`-bit _Integer_ `i`.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTUREMMIN\n```\n\n#### `F497` DICTUREMMINREF\n\nSimilar to `DICTUREMMIN`, but returns the only reference in the value.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTUREMMINREF\n```\n\n#### `F49A` DICTREMMAX\n\nComputes the maximal key `k` (represented by a _Slice_ with `n` data bits) in dictionary `D`, removes `k` from the dictionary, and returns `k` along with the associated value `x` and the modified dictionary `D'`.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTREMMAX\n```\n\n#### `F49B` DICTREMMAXREF\n\nSimilar to `DICTREMMAX`, but returns the only reference in the value as a _Cell_ `c`.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTREMMAXREF\n```\n\n#### `F49C` DICTIREMMAX\n\nSimilar to `DICTREMMAX`, but computes the minimal key `i` under the assumption that all keys are big-endian signed `n`-bit integers. Notice that the key and value returned may differ from those computed by `DICTREMMAX` and `DICTUREMMAX`.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTIREMMAX\n```\n\n#### `F49D` DICTIREMMAXREF\n\nSimilar to `DICTIREMMAX`, but returns the only reference in the value.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTIREMMAXREF\n```\n\n#### `F49E` DICTUREMMAX\n\nSimilar to `DICTREMMAX`, but returns the key as an unsigned `n`-bit _Integer_ `i`.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTUREMMAX\n```\n\n#### `F49F` DICTUREMMAXREF\n\nSimilar to `DICTUREMMAX`, but returns the only reference in the value.<br />\n**Category:** Dict Min (dict_min)<br />\n\n```fift Fift\nDICTUREMMAXREF\n```\n\n#### `F4A0` DICTIGETJMP\n\nSimilar to `DICTIGET`, but with `x` `BLESS`ed into a continuation with a subsequent `JMPX` to it on success. On failure, does nothing. This is useful for implementing `switch`/`case` constructions.<br />\n**Category:** Dict Special (dict_special)<br />\n\n```fift Fift\nDICTIGETJMP\n```\n\n#### `F4A1` DICTUGETJMP\n\nSimilar to `DICTIGETJMP`, but performs `DICTUGET` instead of `DICTIGET`.<br />\n**Category:** Dict Special (dict_special)<br />\n\n```fift Fift\nDICTUGETJMP\n```\n\n#### `F4A2` DICTIGETEXEC\n\nSimilar to `DICTIGETJMP`, but with `EXECUTE` instead of `JMPX`.<br />\n**Category:** Dict Special (dict_special)<br />\n\n```fift Fift\nDICTIGETEXEC\n```\n\n#### `F4A3` DICTUGETEXEC\n\nSimilar to `DICTUGETJMP`, but with `EXECUTE` instead of `JMPX`.<br />\n**Category:** Dict Special (dict_special)<br />\n\n```fift Fift\nDICTUGETEXEC\n```\n\n#### `F4A6_n` DICTPUSHCONST\n\nPushes a non-empty constant dictionary `D` (as a `Cell^?`) along with its key length `0 <= n <= 1023`, stored as a part of the instruction. The dictionary itself is created from the first of remaining references of the current continuation. In this way, the complete `DICTPUSHCONST` instruction can be obtained by first serializing `xF4A4_`, then the non-empty dictionary itself (one `1` bit and a cell reference), and then the unsigned 10-bit integer `n` (as if by a `STU 10` instruction). An empty dictionary can be pushed by a `NEWDICT` primitive instead.<br />\n**Category:** Dict Special (dict_special)<br />\n\n```fift Fift\n[ref] [n] DICTPUSHCONST\n```\n\n#### `F4A8` PFXDICTGETQ\n\nLooks up the unique prefix of _Slice_ `s` present in the prefix code dictionary represented by `Cell^?` `D` and `0 <= n <= 1023`. If found, the prefix of `s` is returned as `s'`, and the corresponding value (also a _Slice_) as `x`. The remainder of `s` is returned as a _Slice_ `s''`. If no prefix of `s` is a key in prefix code dictionary `D`, returns the unchanged `s` and a zero flag to indicate failure.<br />\n**Category:** Dict Special (dict_special)<br />\n\n```fift Fift\nPFXDICTGETQ\n```\n\n#### `F4A9` PFXDICTGET\n\nSimilar to `PFXDICTGET`, but throws a cell deserialization failure exception on failure.<br />\n**Category:** Dict Special (dict_special)<br />\n\n```fift Fift\nPFXDICTGET\n```\n\n#### `F4AA` PFXDICTGETJMP\n\nSimilar to `PFXDICTGETQ`, but on success `BLESS`es the value `x` into a _Continuation_ and transfers control to it as if by a `JMPX`. On failure, returns `s` unchanged and continues execution.<br />\n**Category:** Dict Special (dict_special)<br />\n\n```fift Fift\nPFXDICTGETJMP\n```\n\n#### `F4AB` PFXDICTGETEXEC\n\nSimilar to `PFXDICTGETJMP`, but `EXEC`utes the continuation found instead of jumping to it. On failure, throws a cell deserialization exception.<br />\n**Category:** Dict Special (dict_special)<br />\n\n```fift Fift\nPFXDICTGETEXEC\n```\n\n#### `F4AE_n` PFXDICTCONSTGETJMP\n\nCombines `[n] DICTPUSHCONST` for `0 <= n <= 1023` with `PFXDICTGETJMP`.<br />\n**Category:** Dict Special (dict_special)<br />\n\n```fift Fift\n[ref] [n] PFXDICTCONSTGETJMP\n[ref] [n] PFXDICTSWITCH\n```\n\n#### `F4BC` DICTIGETJMPZ\n\nA variant of `DICTIGETJMP` that returns index `i` on failure.<br />\n**Category:** Dict Special (dict_special)<br />\n\n```fift Fift\nDICTIGETJMPZ\n```\n\n#### `F4BD` DICTUGETJMPZ\n\nA variant of `DICTUGETJMP` that returns index `i` on failure.<br />\n**Category:** Dict Special (dict_special)<br />\n\n```fift Fift\nDICTUGETJMPZ\n```\n\n#### `F4BE` DICTIGETEXECZ\n\nA variant of `DICTIGETEXEC` that returns index `i` on failure.<br />\n**Category:** Dict Special (dict_special)<br />\n\n```fift Fift\nDICTIGETEXECZ\n```\n\n#### `F4BF` DICTUGETEXECZ\n\nA variant of `DICTUGETEXEC` that returns index `i` on failure.<br />\n**Category:** Dict Special (dict_special)<br />\n\n```fift Fift\nDICTUGETEXECZ\n```\n\n#### `F4B1` SUBDICTGET\n\nConstructs a subdictionary consisting of all keys beginning with prefix `k` (represented by a _Slice_, the first `0 <= l <= n <= 1023` data bits of which are used as a key) of length `l` in dictionary `D` of type `HashmapE(n,X)` with `n`-bit keys. On success, returns the new subdictionary of the same type `HashmapE(n,X)` as a _Slice_ `D'`.<br />\n**Category:** Dict Sub (dict_sub)<br />\n\n```fift Fift\nSUBDICTGET\n```\n\n#### `F4B2` SUBDICTIGET\n\nVariant of `SUBDICTGET` with the prefix represented by a signed big-endian `l`-bit _Integer_ `x`, where necessarily `l <= 257`.<br />\n**Category:** Dict Sub (dict_sub)<br />\n\n```fift Fift\nSUBDICTIGET\n```\n\n#### `F4B3` SUBDICTUGET\n\nVariant of `SUBDICTGET` with the prefix represented by an unsigned big-endian `l`-bit _Integer_ `x`, where necessarily `l <= 256`.<br />\n**Category:** Dict Sub (dict_sub)<br />\n\n```fift Fift\nSUBDICTUGET\n```\n\n#### `F4B5` SUBDICTRPGET\n\nSimilar to `SUBDICTGET`, but removes the common prefix `k` from all keys of the new dictionary `D'`, which becomes of type `HashmapE(n-l,X)`.<br />\n**Category:** Dict Sub (dict_sub)<br />\n\n```fift Fift\nSUBDICTRPGET\n```\n\n#### `F4B6` SUBDICTIRPGET\n\nVariant of `SUBDICTRPGET` with the prefix represented by a signed big-endian `l`-bit _Integer_ `x`, where necessarily `l <= 257`.<br />\n**Category:** Dict Sub (dict_sub)<br />\n\n```fift Fift\nSUBDICTIRPGET\n```\n\n#### `F4B7` SUBDICTURPGET\n\nVariant of `SUBDICTRPGET` with the prefix represented by an unsigned big-endian `l`-bit _Integer_ `x`, where necessarily `l <= 256`.<br />\n**Category:** Dict Sub (dict_sub)<br />\n\n```fift Fift\nSUBDICTURPGET\n```\n\n#### `F800` ACCEPT\n\nSets current gas limit `g_l` to its maximal allowed value `g_m`, and resets the gas credit `g_c` to zero, decreasing the value of `g_r` by `g_c` in the process.<br />In other words, the current smart contract agrees to buy some gas to finish the current transaction. This action is required to process external messages, which bring no value (hence no gas) with themselves.<br />\n**Category:** App Gas (app_gas)<br />\n\n```fift Fift\nACCEPT\n```\n\n#### `F801` SETGASLIMIT\n\nSets current gas limit `g_l` to the minimum of `g` and `g_m`, and resets the gas credit `g_c` to zero. If the gas consumed so far (including the present instruction) exceeds the resulting value of `g_l`, an (unhandled) out of gas exception is thrown before setting new gas limits. Notice that `SETGASLIMIT` with an argument `g >= 2^63-1` is equivalent to `ACCEPT`.<br />\n**Category:** App Gas (app_gas)<br />\n\n```fift Fift\nSETGASLIMIT\n```\n\n#### `F807` GASCONSUMED\n\nReturns gas consumed by VM so far (including this instruction).<br />\n**Category:** App Gas (app_gas)<br />\n\n```fift Fift\nGASCONSUMED\n```\n\n#### `F80F` COMMIT\n\nCommits the current state of registers `c4` (''persistent data'') and `c5` (''actions'') so that the current execution is considered ''successful'' with the saved values even if an exception is thrown later.<br />\n**Category:** App Gas (app_gas)<br />\n\n```fift Fift\nCOMMIT\n```\n\n#### `F810` RANDU256\n\nGenerates a new pseudo-random unsigned 256-bit _Integer_ `x`. The algorithm is as follows: if `r` is the old value of the random seed, considered as a 32-byte array (by constructing the big-endian representation of an unsigned 256-bit integer), then its `sha512(r)` is computed; the first 32 bytes of this hash are stored as the new value `r'` of the random seed, and the remaining 32 bytes are returned as the next random value `x`.<br />\n**Category:** App Rnd (app_rnd)<br />\n\n```fift Fift\nRANDU256\n```\n\n#### `F811` RAND\n\nGenerates a new pseudo-random integer `z` in the range `0...y-1` (or `y...-1`, if `y<0`). More precisely, an unsigned random value `x` is generated as in `RAND256U`; then `z:=floor(x*y/2^256)` is computed.<br />Equivalent to `RANDU256` `256 MULRSHIFT`.<br />\n**Category:** App Rnd (app_rnd)<br />\n\n```fift Fift\nRAND\n```\n\n#### `F814` SETRAND\n\nSets the random seed to unsigned 256-bit _Integer_ `x`.<br />\n**Category:** App Rnd (app_rnd)<br />\n\n```fift Fift\nSETRAND\n```\n\n#### `F815` ADDRAND\n\nMixes unsigned 256-bit _Integer_ `x` into the random seed `r` by setting the random seed to `Sha` of the concatenation of two 32-byte strings: the first with the big-endian representation of the old seed `r`, and the second with the big-endian representation of `x`.<br />\n**Category:** App Rnd (app_rnd)<br />\n\n```fift Fift\nADDRAND\nRANDOMIZE\n```\n\n#### `F82i` GETPARAM\n\nReturns the `i`-th parameter from the _Tuple_ provided at `c7` for `0 <= i <= 15`. Equivalent to `c7 PUSHCTR` `FIRST` `[i] INDEX`.<br />If one of these internal operations fails, throws an appropriate type checking or range checking exception.<br />\n**Category:** App Config (app_config)<br />\n\n```fift Fift\n[i] GETPARAM\n```\n\n**Aliases**:\n- `NOW`<br />\n  Returns the current Unix time as an _Integer_. If it is impossible to recover the requested value starting from `c7`, throws a type checking or range checking exception as appropriate.<br />Equivalent to `3 GETPARAM`.\n- `BLOCKLT`<br />\n  Returns the starting logical time of the current block.<br />Equivalent to `4 GETPARAM`.\n- `LTIME`<br />\n  Returns the logical time of the current transaction.<br />Equivalent to `5 GETPARAM`.\n- `RANDSEED`<br />\n  Returns the current random seed as an unsigned 256-bit _Integer_.<br />Equivalent to `6 GETPARAM`.\n- `BALANCE`<br />\n  Returns the remaining balance of the smart contract as a _Tuple_ consisting of an _Integer_ (the remaining Gram balance in nanograms) and a _Maybe Cell_ (a dictionary with 32-bit keys representing the balance of ''extra currencies'').<br />Equivalent to `7 GETPARAM`.<br />Note that `RAW` primitives such as `SENDRAWMSG` do not update this field.\n- `MYADDR`<br />\n  Returns the internal address of the current smart contract as a _Slice_ with a `MsgAddressInt`. If necessary, it can be parsed further using primitives such as `PARSEMSGADDR` or `REWRITESTDADDR`.<br />Equivalent to `8 GETPARAM`.\n- `CONFIGROOT`<br />\n  Returns the _Maybe Cell_ `D` with the current global configuration dictionary. Equivalent to `9 GETPARAM `.\n- `MYCODE`<br />\n  Retrieves code of smart-contract from c7. Equivalent to `10 GETPARAM `.\n- `INCOMINGVALUE`<br />\n  Retrieves value of incoming message from c7. Equivalent to `11 GETPARAM `.\n- `STORAGEFEES`<br />\n  Retrieves value of storage phase fees from c7. Equivalent to `12 GETPARAM `.\n- `PREVBLOCKSINFOTUPLE`<br />\n  Retrives PrevBlocksInfo: `[last_mc_blocks, prev_key_block]` from c7. Equivalent to `13 GETPARAM `.\n- `UNPACKEDCONFIGTUPLE`<br />\n  Retrives tuple that contains some config parameters as cell slices. If the parameter is absent from the config, the value is null. Values: <br />* **0**: `StoragePrices` from `ConfigParam 18`. Not the whole dict, but only the one StoragePrices entry (one which corresponds to the current time).<br />  * **1**: `ConfigParam 19` (global id).<br />  * **2**: `ConfigParam 20` (mc gas prices).<br />  * **3**: `ConfigParam 21` (gas prices).<br />  * **4**: `ConfigParam 24` (mc fwd fees).<br />  * **5**: `ConfigParam 25` (fwd fees).<br />  * **6**: `ConfigParam 43` (size limits).\n- `DUEPAYMENT`<br />\n  Retrives current debt for storage fee (nanotons).\n\n#### `F830` CONFIGDICT\n\nReturns the global configuration dictionary along with its key length (32).<br />Equivalent to `CONFIGROOT` `32 PUSHINT`.<br />\n**Category:** App Config (app_config)<br />\n\n```fift Fift\nCONFIGDICT\n```\n\n#### `F832` CONFIGPARAM\n\nReturns the value of the global configuration parameter with integer index `i` as a _Cell_ `c`, and a flag to indicate success.<br />Equivalent to `CONFIGDICT` `DICTIGETREF`.<br />\n**Category:** App Config (app_config)<br />\n\n```fift Fift\nCONFIGPARAM\n```\n\n#### `F833` CONFIGOPTPARAM\n\nReturns the value of the global configuration parameter with integer index `i` as a _Maybe Cell_ `c^?`.<br />Equivalent to `CONFIGDICT` `DICTIGETOPTREF`.<br />\n**Category:** App Config (app_config)<br />\n\n```fift Fift\nCONFIGOPTPARAM\n```\n\n#### `F83400` PREVMCBLOCKS\n\nRetrives `last_mc_blocks` part of PrevBlocksInfo from c7 (parameter 13).<br />\n**Category:** App Config (app_config)<br />\n\n```fift Fift\nPREVMCBLOCKS\n```\n\n#### `F83401` PREVKEYBLOCK\n\nRetrives `prev_key_block` part of PrevBlocksInfo from c7 (parameter 13).<br />\n**Category:** App Config (app_config)<br />\n\n```fift Fift\nPREVKEYBLOCK\n```\n\n#### `F83402` PREVMCBLOCKS_100\n\nRetrives `last_mc_blocks_divisible_by_100` part of PrevBlocksInfo from c7 (parameter 13).<br />\n**Category:** App Config (app_config)<br />\n\n```fift Fift\nPREVMCBLOCKS_100\n```\n\n#### `F835` GLOBALID\n\nRetrieves `global_id` from 19 network config.<br />\n**Category:** App Config (app_config)<br />\n\n```fift Fift\nGLOBALID\n```\n\n#### `F836` GETGASFEE\n\nCalculates gas fee<br />\n**Category:** App Config (app_config)<br />\n\n```fift Fift\nGETGASFEE\n```\n\n#### `F837` GETSTORAGEFEE\n\nCalculates storage fees (only current StoragePrices entry is used).<br />\n**Category:** App Config (app_config)<br />\n\n```fift Fift\nGETSTORAGEFEE\n```\n\n#### `F838` GETFORWARDFEE\n\nCalculates forward fee.<br />\n**Category:** App Config (app_config)<br />\n\n```fift Fift\nGETFORWARDFEE\n```\n\n#### `F839` GETPRECOMPILEDGAS\n\nReturns gas usage for the current contract if it is precompiled, `null` otherwise.<br />\n**Category:** App Config (app_config)<br />\n\n```fift Fift\nGETPRECOMPILEDGAS\n```\n\n#### `F83A` GETORIGINALFWDFEE\n\nCalculate `(fwd_fee * 2^16) / (2^16 - first_frac)`. Can be used to get the original `fwd_fee` of the message.<br />\n**Category:** App Config (app_config)<br />\n\n```fift Fift\nGETORIGINALFWDFEE\n```\n\n#### `F83B` GETGASFEESIMPLE\n\nSame as `GETGASFEE`, but without flat price (just `(gas_used * price) / 2^16)`.<br />\n**Category:** App Config (app_config)<br />\n\n```fift Fift\nGETGASFEESIMPLE\n```\n\n#### `F83C` GETFORWARDFEESIMPLE\n\nSame as `GETFORWARDFEE`, but without lump price (just (`bits*bit_price + cells*cell_price) / 2^16`).<br />\n**Category:** App Config (app_config)<br />\n\n```fift Fift\nGETFORWARDFEESIMPLE\n```\n\n#### `F840` GETGLOBVAR\n\nReturns the `k`-th global variable for `0 <= k < 255`.<br />Equivalent to `c7 PUSHCTR` `SWAP` `INDEXVARQ`.<br />\n**Category:** App Global (app_global)<br />\n\n```fift Fift\nGETGLOBVAR\n```\n\n#### `F85_k` GETGLOB\n\nReturns the `k`-th global variable for `1 <= k <= 31`.<br />Equivalent to `c7 PUSHCTR` `[k] INDEXQ`.<br />\n**Category:** App Global (app_global)<br />\n\n```fift Fift\n[k] GETGLOB\n```\n\n#### `F860` SETGLOBVAR\n\nAssigns `x` to the `k`-th global variable for `0 <= k < 255`.<br />Equivalent to `c7 PUSHCTR` `ROTREV` `SETINDEXVARQ` `c7 POPCTR`.<br />\n**Category:** App Global (app_global)<br />\n\n```fift Fift\nSETGLOBVAR\n```\n\n#### `F87_k` SETGLOB\n\nAssigns `x` to the `k`-th global variable for `1 <= k <= 31`.<br />Equivalent to `c7 PUSHCTR` `SWAP` `k SETINDEXQ` `c7 POPCTR`.<br />\n**Category:** App Global (app_global)<br />\n\n```fift Fift\n[k] SETGLOB\n```\n\n#### `F880` GETEXTRABALANCE\n\nTakes id of the extra currency (integer in range `0..2^32-1`), returns the amount of this extra currency on the account balance. The first `5` executions of `GETEXTRABALANCE` consume at most `26 + 200` gas each. The subsequent executions incur the full gas cost of `26` (normal instruction cost) plus gas for loading cells (up to `3300` if the dictionary has maximum depth).<br />\n**Category:** App Global (app_global)<br />\n\n```fift Fift\nGETEXTRABALANCE\n```\n\n#### `F881ii` GETPARAMLONG\n\nReturns the `i`-th parameter from the _Tuple_ provided at `c7` for `0 <= i <= 255`. Equivalent to `c7 PUSHCTR` `FIRST` `[i] INDEX`.<br />If one of these internal operations fails, throws an appropriate type checking or range checking exception.<br />\n**Category:** App Config (app_config)<br />\n\n```fift Fift\n[i] GETPARAMLONG\n```\n\n#### `F89i` INMSGPARAM\n\nEquivalent to `INMSGPARAMS` `i INDEX`<br />\n**Category:** App Config (app_config)<br />\n\n```fift Fift\n[i] INMSGPARAM\n```\n\n**Aliases**:\n- `INMSG_BOUNCE`<br />\n  Retrives `bounce` flag of incoming message.\n- `INMSG_BOUNCED`<br />\n  Retrives `bounced` flag of incoming message.\n- `INMSG_SRC`<br />\n  Retrives `src` flag of incoming message.\n- `INMSG_FWDFEE`<br />\n  Retrives `fwd_fee` field of incoming message.\n- `INMSG_LT`<br />\n  Retrives `lt` field of incoming message.\n- `INMSG_UTIME`<br />\n  Retrives `utime` field of incoming message.\n- `INMSG_ORIGVALUE`<br />\n  Retrives original value of the message. This is sometimes different from the value in `INCOMINGVALUE` and TVM stack because of storage fees.\n- `INMSG_VALUE`<br />\n  Retrives value of the message after deducting storage fees. This is same as in `INCOMINGVALUE` and TVM stack.\n- `INMSG_VALUEEXTRA`<br />\n  Same as in `INCOMINGVALUE`.\n- `INMSG_STATEINIT`<br />\n  Retrieves `init` field of the incoming message.\n\n#### `F900` HASHCU\n\nComputes the representation hash of a _Cell_ `c` and returns it as a 256-bit unsigned integer `x`. Useful for signing and checking signatures of arbitrary entities represented by a tree of cells.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHCU\n```\n\n#### `F901` HASHSU\n\nComputes the hash of a _Slice_ `s` and returns it as a 256-bit unsigned integer `x`. The result is the same as if an ordinary cell containing only data and references from `s` had been created and its hash computed by `HASHCU`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHSU\n```\n\n#### `F902` SHA256U\n\nComputes `Sha` of the data bits of _Slice_ `s`. If the bit length of `s` is not divisible by eight, throws a cell underflow exception. The hash value is returned as a 256-bit unsigned integer `x`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nSHA256U\n```\n\n#### `F90400` HASHEXT_SHA256\n\nCalculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHEXT_SHA256\n```\n\n#### `F90401` HASHEXT_SHA512\n\nCalculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHEXT_SHA512\n```\n\n#### `F90402` HASHEXT_BLAKE2B\n\nCalculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHEXT_BLAKE2B\n```\n\n#### `F90403` HASHEXT_KECCAK256\n\nCalculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHEXT_KECCAK256\n```\n\n#### `F90404` HASHEXT_KECCAK512\n\nCalculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHEXT_KECCAK512\n```\n\n#### `F90500` HASHEXTR_SHA256\n\nCalculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHEXTR_SHA256\n```\n\n#### `F90501` HASHEXTR_SHA512\n\nCalculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHEXTR_SHA512\n```\n\n#### `F90502` HASHEXTR_BLAKE2B\n\nCalculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHEXTR_BLAKE2B\n```\n\n#### `F90503` HASHEXTR_KECCAK256\n\nCalculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHEXTR_KECCAK256\n```\n\n#### `F90504` HASHEXTR_KECCAK512\n\nCalculates and returns hash of the concatenation of slices (or builders) `s_1...s_n`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHEXTR_KECCAK512\n```\n\n#### `F90600` HASHEXTA_SHA256\n\nCalculates hash of the concatenation of slices (or builders) `s_1...s_n`. Appends the resulting hash to a builder `b`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHEXTA_SHA256\n```\n\n#### `F90601` HASHEXTA_SHA512\n\nCalculates hash of the concatenation of slices (or builders) `s_1...s_n`. Appends the resulting hash to a builder `b`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHEXTA_SHA512\n```\n\n#### `F90602` HASHEXTA_BLAKE2B\n\nCalculates hash of the concatenation of slices (or builders) `s_1...s_n`. Appends the resulting hash to a builder `b`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHEXTA_BLAKE2B\n```\n\n#### `F90603` HASHEXTA_KECCAK256\n\nCalculates hash of the concatenation of slices (or builders) `s_1...s_n`. Appends the resulting hash to a builder `b`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHEXTA_KECCAK256\n```\n\n#### `F90604` HASHEXTA_KECCAK512\n\nCalculates hash of the concatenation of slices (or builders) `s_1...s_n`. Appends the resulting hash to a builder `b`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHEXTA_KECCAK512\n```\n\n#### `F90700` HASHEXTAR_SHA256\n\nCalculates hash of the concatenation of slices (or builders) `s_1...s_n`. Appends the resulting hash to a builder `b`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHEXTAR_SHA256\n```\n\n#### `F90701` HASHEXTAR_SHA512\n\nCalculates hash of the concatenation of slices (or builders) `s_1...s_n`. Appends the resulting hash to a builder `b`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHEXTAR_SHA512\n```\n\n#### `F90702` HASHEXTAR_BLAKE2B\n\nCalculates hash of the concatenation of slices (or builders) `s_1...s_n`. Appends the resulting hash to a builder `b`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHEXTAR_BLAKE2B\n```\n\n#### `F90703` HASHEXTAR_KECCAK256\n\nCalculates hash of the concatenation of slices (or builders) `s_1...s_n`. Appends the resulting hash to a builder `b`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHEXTAR_KECCAK256\n```\n\n#### `F90704` HASHEXTAR_KECCAK512\n\nCalculates hash of the concatenation of slices (or builders) `s_1...s_n`. Appends the resulting hash to a builder `b`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHEXTAR_KECCAK512\n```\n\n#### `F910` CHKSIGNU\n\nChecks the Ed25519-signature `s` of a hash `h` (a 256-bit unsigned integer, usually computed as the hash of some data) using public key `k` (also represented by a 256-bit unsigned integer).<br />The signature `s` must be a _Slice_ containing at least 512 data bits; only the first 512 bits are used. The result is `-1` if the signature is valid, `0` otherwise.<br />Notice that `CHKSIGNU` is equivalent to `ROT` `NEWC` `256 STU` `ENDC` `ROTREV` `CHKSIGNS`, i.e., to `CHKSIGNS` with the first argument `d` set to 256-bit _Slice_ containing `h`. Therefore, if `h` is computed as the hash of some data, these data are hashed _twice_, the second hashing occurring inside `CHKSIGNS`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nCHKSIGNU\n```\n\n#### `F911` CHKSIGNS\n\nChecks whether `s` is a valid Ed25519-signature of the data portion of _Slice_ `d` using public key `k`, similarly to `CHKSIGNU`. If the bit length of _Slice_ `d` is not divisible by eight, throws a cell underflow exception. The verification of Ed25519 signatures is the standard one, with `Sha` used to reduce `d` to the 256-bit number that is actually signed.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nCHKSIGNS\n```\n\n#### `F912` ECRECOVER\n\nRecovers the public key from a secp256k1 signature, identical to Bitcoin/Ethereum operations. Takes a 32-byte hash as `uint256 hash` and a 65-byte signature as `uint8 v`, `uint256 r`, and `uint256 s`. In TON, the `v` value is strictly 0 or 1; no extra flags or extended values are supported. If the public key cannot be recovered, the instruction returns `0`. On success, it returns the recovered 65-byte public key as `uint8 h`, `uint256 x1`, and `uint256 x2`, followed by `-1`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nECRECOVER\n```\n\n#### `F913` SECP256K1_XONLY_PUBKEY_TWEAK_ADD\n\nperforms [`secp256k1_xonly_pubkey_tweak_add`](https://github.com/bitcoin-core/secp256k1/blob/master/include/secp256k1_extrakeys.h#L120). `key` and `tweak` are 256-bit unsigned integers. 65-byte public key is returned as `uint8 f`, `uint256 x, y` (as in `ECRECOVER`).<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nSECP256K1_XONLY_PUBKEY_TWEAK_ADD\n```\n\n#### `F914` P256_CHKSIGNU\n\nChecks seck256r1-signature `sig` of a number `h` (a 256-bit unsigned integer, usually computed as the hash of some data) and public key `k`. Returns -1 on success, 0 on failure. Public key is a 33-byte slice (encoded according to Sec. 2.3.4 point 2 of [SECG SEC 1](https://www.secg.org/sec1-v2.pdf)). Signature `sig` is a 64-byte slice (two 256-bit unsigned integers `r` and `s`).<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nP256_CHKSIGNU\n```\n\n#### `F915` P256_CHKSIGNS\n\nChecks seck256r1-signature `sig` of data portion of slice `d` and public key `k`. Returns -1 on success, 0 on failure. Public key is a 33-byte slice (encoded according to Sec. 2.3.4 point 2 of [SECG SEC 1](https://www.secg.org/sec1-v2.pdf)). Signature `sig` is a 64-byte slice (two 256-bit unsigned integers `r` and `s`).<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nP256_CHKSIGNS\n```\n\n#### `F916` HASHBU\n\nSame as `ENDC HASHCU`, but without gas cost for cell creation.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nHASHBU\n```\n\n#### `F920` RIST255_FROMHASH\n\nDeterministically generates a valid point `x` from a 512-bit hash (given as two 256-bit integers).<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nRIST255_FROMHASH\n```\n\n#### `F921` RIST255_VALIDATE\n\nChecks that integer `x` is a valid representation of some curve point. Throws range_chk on error.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nRIST255_VALIDATE\n```\n\n#### `F922` RIST255_ADD\n\nAddition of two points on a curve.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nRIST255_ADD\n```\n\n#### `F923` RIST255_SUB\n\nSubtraction of two points on curve.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nRIST255_SUB\n```\n\n#### `F924` RIST255_MUL\n\nMultiplies point `x` by a scalar `n`. Any `n` is valid, including negative.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nRIST255_MUL\n```\n\n#### `F925` RIST255_MULBASE\n\nMultiplies the generator point `g` by a scalar `n`. Any `n` is valid, including negative.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nRIST255_MULBASE\n```\n\n#### `F926` RIST255_PUSHL\n\nPushes integer l=2^252+27742317777372353535851937790883648493, which is the order of the group.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nRIST255_PUSHL\n```\n\n#### `B7F921` RIST255_QVALIDATE\n\nChecks that integer `x` is a valid representation of some curve point. Returns -1 on success and 0 on failure.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nRIST255_QVALIDATE\n```\n\n#### `B7F922` RIST255_QADD\n\nAddition of two points on a curve. Returns -1 on success and 0 on failure.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nRIST255_QADD\n```\n\n#### `B7F923` RIST255_QSUB\n\nSubtraction of two points on curve. Returns -1 on success and 0 on failure.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nRIST255_QSUB\n```\n\n#### `B7F924` RIST255_QMUL\n\nMultiplies point `x` by a scalar `n`. Any `n` is valid, including negative. Returns -1 on success and 0 on failure.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nRIST255_QMUL\n```\n\n#### `B7F925` RIST255_QMULBASE\n\nMultiplies the generator point `g` by a scalar `n`. Any `n` is valid, including negative.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nRIST255_QMULBASE\n```\n\n#### `F93000` BLS_VERIFY\n\nChecks BLS signature, return true on success, false otherwise.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_VERIFY\n```\n\n#### `F93001` BLS_AGGREGATE\n\nAggregates signatures. `n>0`. Throw exception if `n=0` or if some `sig_i` is not a valid signature.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_AGGREGATE\n```\n\n#### `F93002` BLS_FASTAGGREGATEVERIFY\n\nChecks aggregated BLS signature for keys `pk_1...pk_n` and message `msg`. Return true on success, false otherwise. Return false if `n=0`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_FASTAGGREGATEVERIFY\n```\n\n#### `F93003` BLS_AGGREGATEVERIFY\n\nChecks aggregated BLS signature for key-message pairs `pk_1 msg_1...pk_n msg_n`. Return true on success, false otherwise. Return false if `n=0`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_AGGREGATEVERIFY\n```\n\n#### `F93010` BLS_G1_ADD\n\nAddition on G1.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_G1_ADD\n```\n\n#### `F93011` BLS_G1_SUB\n\nSubtraction on G1.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_G1_SUB\n```\n\n#### `F93012` BLS_G1_NEG\n\nNegation on G1.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_G1_NEG\n```\n\n#### `F93013` BLS_G1_MUL\n\nMultiplies G1 point `x` by scalar `s`. Any `s` is valid, including negative.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_G1_MUL\n```\n\n#### `F93014` BLS_G1_MULTIEXP\n\nCalculates `x_1*s_1+...+x_n*s_n` for G1 points `x_i` and scalars `s_i`. Returns zero point if `n=0`. Any `s_i` is valid, including negative.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_G1_MULTIEXP\n```\n\n#### `F93015` BLS_G1_ZERO\n\nPushes zero point in G1.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_G1_ZERO\n```\n\n#### `F93016` BLS_MAP_TO_G1\n\nConverts FP element `f` to a G1 point.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_MAP_TO_G1\n```\n\n#### `F93017` BLS_G1_INGROUP\n\nChecks that slice `x` represents a valid element of G1.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_G1_INGROUP\n```\n\n#### `F93018` BLS_G1_ISZERO\n\nChecks that G1 point `x` is equal to zero.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_G1_ISZERO\n```\n\n#### `F93020` BLS_G2_ADD\n\nAddition on G2.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_G2_ADD\n```\n\n#### `F93021` BLS_G2_SUB\n\nSubtraction on G2.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_G2_SUB\n```\n\n#### `F93022` BLS_G2_NEG\n\nNegation on G2.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_G2_NEG\n```\n\n#### `F93023` BLS_G2_MUL\n\nMultiplies G2 point `x` by scalar `s`. Any `s` is valid, including negative.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_G2_MUL\n```\n\n#### `F93024` BLS_G2_MULTIEXP\n\nCalculates `x_1*s_1+...+x_n*s_n` for G2 points `x_i` and scalars `s_i`. Returns zero point if `n=0`. Any `s_i` is valid, including negative.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_G2_MULTIEXP\n```\n\n#### `F93025` BLS_G2_ZERO\n\nPushes zero point in G2.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_G2_ZERO\n```\n\n#### `F93026` BLS_MAP_TO_G2\n\nConverts FP2 element `f` to a G2 point.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_MAP_TO_G2\n```\n\n#### `F93027` BLS_G2_INGROUP\n\nChecks that slice `x` represents a valid element of G2.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_G2_INGROUP\n```\n\n#### `F93028` BLS_G2_ISZERO\n\nChecks that G2 point `x` is equal to zero.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_G2_ISZERO\n```\n\n#### `F93030` BLS_PAIRING\n\nGiven G1 points `x_i` and G2 points `y_i`, calculates and multiply pairings of `x_i,y_i`. Returns true if the result is the multiplicative identity in FP12, false otherwise. Returns false if `n=0`.<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_PAIRING\n```\n\n#### `F93031` BLS_PUSHR\n\nPushes the order of G1 and G2 (approx. `2^255`).<br />\n**Category:** App Crypto (app_crypto)<br />\n\n```fift Fift\nBLS_PUSHR\n```\n\n#### `F940` CDATASIZEQ\n\nRecursively computes the count of distinct cells `x`, data bits `y`, and cell references `z` in the dag rooted at _Cell_ `c`, effectively returning the total storage used by this dag taking into account the identification of equal cells. The values of `x`, `y`, and `z` are computed by a depth-first traversal of this dag, with a hash table of visited cell hashes used to prevent visits of already-visited cells. The total count of visited cells `x` cannot exceed non-negative _Integer_ `n`; otherwise the computation is aborted before visiting the `(n+1)`-st cell and a zero is returned to indicate failure. If `c` is _Null_, returns `x=y=z=0`.<br />\n**Category:** App Misc (app_misc)<br />\n\n```fift Fift\nCDATASIZEQ\n```\n\n#### `F941` CDATASIZE\n\nA non-quiet version of `CDATASIZEQ` that throws a cell overflow exception (8) on failure.<br />\n**Category:** App Misc (app_misc)<br />\n\n```fift Fift\nCDATASIZE\n```\n\n#### `F942` SDATASIZEQ\n\nSimilar to `CDATASIZEQ`, but accepting a _Slice_ `s` instead of a _Cell_. The returned value of `x` does not take into account the cell that contains the slice `s` itself; however, the data bits and the cell references of `s` are accounted for in `y` and `z`.<br />\n**Category:** App Misc (app_misc)<br />\n\n```fift Fift\nSDATASIZEQ\n```\n\n#### `F943` SDATASIZE\n\nA non-quiet version of `SDATASIZEQ` that throws a cell overflow exception (8) on failure.<br />\n**Category:** App Misc (app_misc)<br />\n\n```fift Fift\nSDATASIZE\n```\n\n#### `FA00` LDGRAMS\n\nLoads (deserializes) a `Gram` or `VarUInteger 16` amount from _Slice_ `s`, and returns the amount as _Integer_ `x` along with the remainder `s'` of `s`. The expected serialization of `x` consists of a 4-bit unsigned big-endian integer `l`, followed by an `8l`-bit unsigned big-endian representation of `x`.<br />The net effect is approximately equivalent to `4 LDU` `SWAP` `3 LSHIFT#` `LDUX`.<br />\n**Category:** App Currency (app_currency)<br />\n\n```fift Fift\nLDGRAMS\nLDVARUINT16\n```\n\n#### `FA01` LDVARINT16\n\nSimilar to `LDVARUINT16`, but loads a _signed_ _Integer_ `x`.<br />Approximately equivalent to `4 LDU` `SWAP` `3 LSHIFT#` `LDIX`.<br />\n**Category:** App Currency (app_currency)<br />\n\n```fift Fift\nLDVARINT16\n```\n\n#### `FA02` STGRAMS\n\nStores (serializes) an _Integer_ `x` in the range `0...2^120-1` into _Builder_ `b`, and returns the resulting _Builder_ `b'`. The serialization of `x` consists of a 4-bit unsigned big-endian integer `l`, which is the smallest integer `l>=0`, such that `x<2^(8l)`, followed by an `8l`-bit unsigned big-endian representation of `x`. If `x` does not belong to the supported range, a range check exception is thrown.<br />\n**Category:** App Currency (app_currency)<br />\n\n```fift Fift\nSTGRAMS\nSTVARUINT16\n```\n\n#### `FA03` STVARINT16\n\nSimilar to `STVARUINT16`, but serializes a _signed_ _Integer_ `x` in the range `-2^119...2^119-1`.<br />\n**Category:** App Currency (app_currency)<br />\n\n```fift Fift\nSTVARINT16\n```\n\n#### `FA04` LDVARUINT32\n\nLoads (deserializes) a `VarUInteger 32` amount from _Slice_ `s`, and returns the amount as _Integer_ `x` along with the remainder `s'` of `s`. The expected serialization of `x` consists of a 5-bit unsigned big-endian integer `l`, followed by an `8l`-bit unsigned big-endian representation of `x`.<br />The net effect is approximately equivalent to `4 LDU` `SWAP` `3 LSHIFT#` `LDUX`.<br />\n**Category:** App Currency (app_currency)<br />\n\n```fift Fift\nLDVARUINT32\n```\n\n#### `FA05` LDVARINT32\n\nSimilar to `LDVARUINT32`, but loads a _signed_ _Integer_ `x`.<br />Approximately equivalent to `5 LDU` `SWAP` `3 LSHIFT#` `LDIX`.<br />\n**Category:** App Currency (app_currency)<br />\n\n```fift Fift\nLDVARINT32\n```\n\n#### `FA06` STVARUINT32\n\nStores (serializes) an _Integer_ `x` in the range `0...2^248-1` into _Builder_ `b`, and returns the resulting _Builder_ `b'`. The serialization of `x` consists of a 5-bit unsigned big-endian integer `l`, which is the smallest integer `l>=0`, such that `x<2^(8l)`, followed by an `8l`-bit unsigned big-endian representation of `x`. If `x` does not belong to the supported range, a range check exception is thrown.<br />\n**Category:** App Currency (app_currency)<br />\n\n```fift Fift\nSTVARUINT32\n```\n\n#### `FA07` STVARINT32\n\nSimilar to `STVARUINT32`, but serializes a _signed_ _Integer_ `x` in the range `-2^247...2^247-1`.<br />\n**Category:** App Currency (app_currency)<br />\n\n```fift Fift\nSTVARINT32\n```\n\n#### `FA40` LDMSGADDR\n\nLoads from _Slice_ `s` the only prefix that is a valid `MsgAddress`, and returns both this prefix `s'` and the remainder `s''` of `s` as slices.<br />\n**Category:** App Addr (app_addr)<br />\n\n```fift Fift\nLDMSGADDR\n```\n\n#### `FA41` LDMSGADDRQ\n\nA quiet version of `LDMSGADDR`: on success, pushes an extra `-1`; on failure, pushes the original `s` and a zero.<br />\n**Category:** App Addr (app_addr)<br />\n\n```fift Fift\nLDMSGADDRQ\n```\n\n#### `FA42` PARSEMSGADDR\n\nDecomposes _Slice_ `s` containing a valid `MsgAddress` into a _Tuple_ `t` with separate fields of this `MsgAddress`. If `s` is not a valid `MsgAddress`, a cell deserialization exception is thrown.<br />\n**Category:** App Addr (app_addr)<br />\n\n```fift Fift\nPARSEMSGADDR\n```\n\n#### `FA43` PARSEMSGADDRQ\n\nA quiet version of `PARSEMSGADDR`: returns a zero on error instead of throwing an exception.<br />\n**Category:** App Addr (app_addr)<br />\n\n```fift Fift\nPARSEMSGADDRQ\n```\n\n#### `FA44` REWRITESTDADDR\n\nParses _Slice_ `s` containing a valid `MsgAddressInt` (usually a `msg_addr_std`), applies rewriting from the `anycast` (if present) to the same-length prefix of the address, and returns both the workchain `x` and the 256-bit address `y` as integers. If the address is not 256-bit, or if `s` is not a valid serialization of `MsgAddressInt`, throws a cell deserialization exception.<br />\n**Category:** App Addr (app_addr)<br />\n\n```fift Fift\nREWRITESTDADDR\n```\n\n#### `FA45` REWRITESTDADDRQ\n\nA quiet version of primitive `REWRITESTDADDR`.<br />\n**Category:** App Addr (app_addr)<br />\n\n```fift Fift\nREWRITESTDADDRQ\n```\n\n#### `FA46` REWRITEVARADDR\n\n`msg_addr_var` not allowed since TVM v10, so it behaves like `REWRITESTDADDR`, but returns account id in `Slice`, not `Integer`: parses address `s` into workchain `x` and account id `s`.<br />\n**Category:** App Addr (app_addr)<br />\n\n```fift Fift\nREWRITEVARADDR\n```\n\n#### `FA47` REWRITEVARADDRQ\n\nA quiet version of primitive `REWRITEVARADDR`.<br />\n**Category:** App Addr (app_addr)<br />\n\n```fift Fift\nREWRITEVARADDRQ\n```\n\n#### `FA48` LDSTDADDR\n\nLoads `addr_std$10`, if address is not `addr_std`, throws an error 9 (`cannot load a MsgAddressInt`).<br />\n**Category:** App Addr (app_addr)<br />\n\n```fift Fift\nLDSTDADDR\n```\n\n#### `FA49` LDSTDADDRQ\n\nA quiet version of primitive `LDSTDADDR`.<br />\n**Category:** App Addr (app_addr)<br />\n\n```fift Fift\nLDSTDADDRQ\n```\n\n#### `FA50` LDOPTSTDADDR\n\nLoads `addr_std$10` or `addr_none$00`, if address is `addr_none$00` pushes a Null, if address is not `addr_std` or `addr_none`, throws an error 9 (`cannot load a MsgAddressInt`).<br />\n**Category:** App Addr (app_addr)<br />\n\n```fift Fift\nLDOPTSTDADDR\n```\n\n#### `FA51` LDOPTSTDADDRQ\n\nA quiet version of primitive `LDOPTSTDADDR`.<br />\n**Category:** App Addr (app_addr)<br />\n\n```fift Fift\nLDOPTSTDADDRQ\n```\n\n#### `FA52` STSTDADDR\n\nStores `addr_std$10`, if address is not `addr_std`, throws an error 9 (`cannot load a MsgAddressInt`).<br />\n**Category:** App Addr (app_addr)<br />\n\n```fift Fift\nSTSTDADDR\n```\n\n#### `FA53` STSTDADDRQ\n\nA quiet version of primitive `STSTDADDR`.<br />\n**Category:** App Addr (app_addr)<br />\n\n```fift Fift\nSTSTDADDRQ\n```\n\n#### `FA54` STOPTSTDADDR\n\nstores `addr_std$10` or Null. Null is stored as `addr_none$00`, if address is not `addr_std`, throws an error 9 (`cannot load a MsgAddressInt`).<br />\n**Category:** App Addr (app_addr)<br />\n\n```fift Fift\nSTOPTSTDADDR\n```\n\n#### `FA55` STOPTSTDADDRQ\n\nA quiet version of primitive `STOPTSTDADDR`.<br />\n**Category:** App Addr (app_addr)<br />\n\n```fift Fift\nSTOPTSTDADDRQ\n```\n\n#### `FB00` SENDRAWMSG\n\nSends a raw message contained in _Cell `c`_, which should contain a correctly serialized object `Message X`, with the only exception that the source address is allowed to have dummy value `addr_none` (to be automatically replaced with the current smart-contract address), and `ihr_fee`, `fwd_fee`, `created_lt` and `created_at` fields can have arbitrary values (to be rewritten with correct values during the action phase of the current transaction). Integer parameter `x` contains the flags. Currently `x=0` is used for ordinary messages; `x=128` is used for messages that are to carry all the remaining balance of the current smart contract (instead of the value originally indicated in the message); `x=64` is used for messages that carry all the remaining value of the inbound message in addition to the value initially indicated in the new message (if bit 0 is not set, the gas fees are deducted from this amount); `x'=x+1` means that the sender wants to pay transfer fees separately; `x'=x+2` means that any errors arising while processing this message during the action phase should be ignored. Finally, `x'=x+32` means that the current account must be destroyed if its resulting balance is zero. This flag is usually employed together with `+128`.<br />\n**Category:** App Actions (app_actions)<br />\n\n```fift Fift\nSENDRAWMSG\n```\n\n#### `FB02` RAWRESERVE\n\nCreates an output action which would reserve exactly `x` nanograms (if `y=0`), at most `x` nanograms (if `y=2`), or all but `x` nanograms (if `y=1` or `y=3`), from the remaining balance of the account. It is roughly equivalent to creating an outbound message carrying `x` nanograms (or `b-x` nanograms, where `b` is the remaining balance) to oneself, so that the subsequent output actions would not be able to spend more money than the remainder. Bit `+2` in `y` means that the external action does not fail if the specified amount cannot be reserved; instead, all remaining balance is reserved. Bit `+8` in `y` means `x:=-x` before performing any further actions. Bit `+4` in `y` means that `x` is increased by the original balance of the current account (before the compute phase), including all extra currencies, before performing any other checks and actions. Currently `x` must be a non-negative integer, and `y` must be in the range `0...15`.<br />\n**Category:** App Actions (app_actions)<br />\n\n```fift Fift\nRAWRESERVE\n```\n\n#### `FB03` RAWRESERVEX\n\nSimilar to `RAWRESERVE`, but also accepts a dictionary `D` (represented by a _Cell_ or _Null_) with extra currencies. In this way currencies other than Grams can be reserved.<br />\n**Category:** App Actions (app_actions)<br />\n\n```fift Fift\nRAWRESERVEX\n```\n\n#### `FB04` SETCODE\n\nCreates an output action that would change this smart contract code to that given by _Cell_ `c`. Notice that this change will take effect only after the successful termination of the current run of the smart contract.<br />\n**Category:** App Actions (app_actions)<br />\n\n```fift Fift\nSETCODE\n```\n\n#### `FB06` SETLIBCODE\n\nCreates an output action that would modify the collection of this smart contract libraries by adding or removing library with code given in _Cell_ `c`. If `x=0`, the library is actually removed if it was previously present in the collection (if not, this action does nothing). If `x=1`, the library is added as a private library, and if `x=2`, the library is added as a public library (and becomes available to all smart contracts if the current smart contract resides in the masterchain); if the library was present in the collection before, its public/private status is changed according to `x`. Values of `x` other than `0...2` are invalid.<br />\n**Category:** App Actions (app_actions)<br />\n\n```fift Fift\nSETLIBCODE\n```\n\n#### `FB07` CHANGELIB\n\nCreates an output action similarly to `SETLIBCODE`, but instead of the library code accepts its hash as an unsigned 256-bit integer `h`. If `x!=0` and the library with hash `h` is absent from the library collection of this smart contract, this output action will fail.<br />\n**Category:** App Actions (app_actions)<br />\n\n```fift Fift\nCHANGELIB\n```\n\n#### `FB08` SENDMSG\n\nCreates an output action and returns a fee for creating a message. Mode has the same effect as in the case of `SENDRAWMSG`. Additionally `+1024` means - do not create an action, only estimate fee. Other modes affect the fee calculation as follows: `+64` substitutes the entire balance of the incoming message as an outcoming value (slightly inaccurate, gas expenses that cannot be estimated before the computation is completed are not taken into account), `+128` substitutes the value of the entire balance of the contract before the start of the computation phase (slightly inaccurate, since gas expenses that cannot be estimated before the completion of the computation phase are not taken into account).<br />\n**Category:** App Actions (app_actions)<br />\n\n```fift Fift\nSENDMSG\n```\n\n#### `FEij` DEBUG\n\n<br />\n**Category:** Debug (debug)<br />\n\n```fift Fift\n{i*16+j} DEBUG\n```\n\n**Aliases**:\n- `DUMPSTK`<br />\n  Dumps the stack (at most the top 255 values) and shows the total stack depth. Does nothing on production versions of TVM.\n- `STRDUMP`<br />\n  Dumps slice with length divisible by 8 from top of stack as a string. Does nothing on production versions of TVM.\n- `DUMP`<br />\n  Dumps slice with length divisible by 8 from top of stack as a string. Does nothing on production versions of TVM.\n\n#### `FEFnssss` DEBUGSTR\n\n`0 <= n < 16`. Length of `ssss` is `n+1` bytes.<br />`{string}` is a [string literal](https://github.com/Piterden/TON-docs/blob/master/Fift.%20A%20Brief%20Introduction.md#user-content-29-string-literals).<br />`DEBUGSTR`: `ssss` is the given string.<br />`DEBUGSTRI`: `ssss` is one-byte integer `0 <= x <= 255` followed by the given string.<br />\n**Category:** Debug (debug)<br />\n\n```fift Fift\n{string} DEBUGSTR\n{string} {x} DEBUGSTRI\n```\n\n#### `FFnn` SETCP\n\nSelects TVM codepage `0 <= nn < 240`. If the codepage is not supported, throws an invalid opcode exception.<br />\n**Category:** Codepage (codepage)<br />\n\n```fift Fift\n[nn] SETCP\n```\n\n**Aliases**:\n- `SETCP0`<br />\n  Selects TVM (test) codepage zero as described in this document.\n\n#### `FFFz` SETCP_SPECIAL\n\nSelects TVM codepage `z-16` for `1 <= z <= 15`. Negative codepages `-13...-1` are reserved for restricted versions of TVM needed to validate runs of TVM in other codepages. Negative codepage `-14` is reserved for experimental codepages, not necessarily compatible between different TVM implementations, and should be disabled in the production versions of TVM.<br />\n**Category:** Codepage (codepage)<br />\n\n```fift Fift\n[z-16] SETCP\n```\n\n#### `FFF0` SETCPX\n\nSelects codepage `c` with `-2^15 <= c < 2^15` passed in the top of the stack.<br />\n**Category:** Codepage (codepage)<br />\n\n```fift Fift\nSETCPX\n```\n</div>\n{/* STATIC_END tvm_instructions */}\n"
  },
  {
    "path": "tvm/overview.mdx",
    "content": "---\ntitle: \"TVM overview\"\nsidebarTitle: \"Overview\"\n---\n\nimport { Aside } from '/snippets/aside.jsx';\n\nTON Virtual Machine (TVM) is a [stack-based](https://en.wikipedia.org/wiki/Stack_machine) virtual machine which executes smart contracts on TON blockchain.\n\nTVM is invoked when a message is sent to an account that has deployed contract code, when a get method is called on an account, and in some [more rare cases](/tvm/initialization#stack).\n\nExecuting code on same inputs and prior state deterministically produces same outputs, so that validators can agree on whether code was executed correctly.\n\nEvery instruction consumes [gas](/tvm/gas). Gas exhaustion stops execution. This limit is imposed so that expensive computations (i.e. infinite loops) cannot be used to exhaust validators' computation resources, causing [denial of service](https://en.wikipedia.org/wiki/Denial-of-service_attack).\n\n## Data model\n\n- TVM has no [random-access memory](https://en.wikipedia.org/wiki/Random-access_memory). Instead it uses a stack of values as a scratchpad.\n- There are no memory addresses. Most instructions either store their parameters directly in the code, or take them from the top of the stack.\n- All values are [immutable](https://en.wikipedia.org/wiki/Immutable_object).\n  Most of the data is stored as immutable tree of [cells](/foundations/serialization/cells).\n- Reading and writing of cells is done with [slices and builders](/tvm/builders-and-slices).\n- There are no function addresses or function pointers. Code is executed from bitcode inside [continuations](/tvm/continuations).\n\n## TVM state\n\nOn incoming messages or get method call, a new instance of TVM is started, with a new state. Derivation of the initial state from the message is described in [its own article](/tvm/initialization).\n\nThe total state of TVM consists of the following components:\n\n- **Stack**. A regular [stack data structure](https://en.wikipedia.org/wiki/Stack_\\(abstract_data_type\\)). The vast majority of instructions `pop()` operands from the top and `push()` results back.\n- [**Control registers**](/tvm/registers). A small fixed set of special registers, denoted as `c0`, `c1`, ..., `c5`, and `c7` (`c6` does not exist).\n- [**Gas counter**](/tvm/gas). Tracks remaining computation budget. Each instruction decrements gas. When counter hits zero/negative value, an exception is raised, and the run aborts.\n- **Current continuation (`cc`)**. A special register that stores a list of the next instructions to execute. Similar to the instruction pointer in traditional architectures.\n- **Current codepage (`cp`)**. Determines how to decode the next instruction in `cc`. Different codepages may implement different instruction sets, allowing for adding new features to TVM without affecting old smart contracts. Currently, only codepage `0` (`cp0`) is implemented. Smart contract runs [`SETCP0`](/tvm/instructions#ff-setcp) instruction to explicitly use codepage `0`.\n\n## TVM data types\n\nValues on the stack and inside of registers are of one of the following seven types:\n\n| Type         | Description                                                                                                                 |\n| ------------ | --------------------------------------------------------------------------------------------------------------------------- |\n| Integer      | 257-bit signed integer. Has the special `NaN` value representing arithmetic faults.                                         |\n| Cell         | Node of a tree with bit string on it (\\<= 1023 bits), and up to 4 arrows (refs).                                            |\n| Slice        | Read cursor over a Cell.                                                                                                    |\n| Builder      | Write cursor to construct a new Cell.                                                                                       |\n| Tuple        | List of 0..255 elements of any of seven types. Types of elements can be distinct.                                           |\n| Continuation | Executable Slice with TVM bitcode. [Continuations](https://en.wikipedia.org/wiki/Continuation) are callable like functions. |\n| Null         | Empty value.                                                                                                                |\n\n## Example of a smart contract: counter\n\nHere is a sample contract, written in [Fift](/languages/fift/overview). It implements the following logic:\n\n- If an event is not an internal message, stop execution.\n- Read 32-bit number (`msg_counter`) from internal message's body.\n- Check that it is equal to the 32-bit number stored in `c4` (persistent account storage).\n- Increment it.\n- Save it back to `c4`.\n\nWhen an account with this code gets an internal message, TVM stack [is initialized](/tvm/initialization#stack) with these values:\n\n1. `s0` (top of the stack), function selector, is `0`. For other events, e.g., external messages or get method calls, selector will be non-zero.\n1. `s1`, message body. The example contract expects exactly 32 bits here.\n1. Three more values `s2`, `s3`, `s4` [are pushed](/tvm/initialization#external%2Finternal-message) by TVM onto a stack. They won't be used in the example. After execution finishes, they'll still be on the stack, and will be silently ignored.\n\nIn `Current stack` comments, we represent stack at that moment of execution, keeping its top to the right (e.g., `s2 s1 s0`, where `s0` is the top of the stack).\n\n```fift Fift\n<{\n// Current stack: msg_body selector\n\n// Use codepage 0. Picks the only available instruction set.\nSETCP0\n// This instruction does not affect the stack.\n// Current stack: msg_body selector\n\n// Consume `selector` from the top of the stack.\n// Stop execution if `selector != 0`,\n// i.e. \"is not an internal message\".\nIFRET\n// Continue execution if we received an internal message.\n// Current stack: msg_body\n\n// Load (LD) unsigned (U) 32-bit integer from a slice.\n// This instruction pops (consumes) a slice from the stack,\n// pushes an integer, and then pushes a new slice with\n// 32 bits cut from it\n32 LDU\n// Current stack: msg_counter msg_body'\n// msg_body' is a slice whose read cursor was moved by 32 bits\n// when we loaded a 32-bit integer.\n// For example, if we had slice x{00000001} on the stack and\n// then invoked 32 LDU, there will be integer `1` and `x{}`\n// (empty slice) on the stack\n\n// Assert the END of a slice (S).\n// These instructions consume a slice and check that it is\n// empty (no more data to read), otherwise it throws an\n// exception, because there was more data than we expected.\nENDS\n// Current stack: msg_counter\n\n// Push c4 (persistent storage) on the stack.\n// `storage` is a cell\nc4 PUSH\n// Current stack: msg_counter storage\n\n// Convert Cell to a Slice, i.e. make it readable\nCTOS\n// Current stack: msg_counter storage_slice\n\n// Read 32-bit unsigned integer from `storage_slice`\n32 LDU\n// Current stack: msg_counter storage_counter storage_slice'\n\n// Assert there is no more data in the storage\nENDS\n// Current stack: msg_counter storage_counter\n\n// Duplicate s0 (top of stack) under two top values\nTUCK\n// Current stack: storage_counter msg_counter storage_counter\n\n// Check counters are equal\nEQUAL\n// Current stack: storage_counter msg_counter==storage_counter?\n\n// Throw an exception with code 33 if it is not equal\n33 THROWIFNOT\n// Current stack: storage_counter\n\n// Increase counter\nINC\n// Current stack: storage_counter+1\n\n// Create an empty Builder\nNEWC\n// Current stack: storage_counter+1 builder\n\n// Store (ST) unsigned (U) 32-bit integer `storage_counter+1` to a builder\n32 STU\n// Current stack: builder'\n\n// Finalize Builder to a Cell\nENDC\n// Current stack: new_storage\n\n// Save `new_storage` to c4 (persistent storage)\nc4 POP\n// Current stack: (no values)\n}>\n```\n"
  },
  {
    "path": "tvm/registers.mdx",
    "content": "---\ntitle: \"Registers\"\n---\n\nTVM registers hold special values, such as contract storage, list of output actions, or exception handler\n\nOnly `c4` (new state) and `c5` (final actions) represent durable effects of a successful on‑chain run. Everything else is transient.\n\n## `c0` — return continuation\n\n**Type**: `Continuation`\n\n**Initial value**: `Quit` — extraordinary continuation which terminates TVM with exit code `0`.\n\nWhen [`RET`](/tvm/instructions#db30-ret) is called or the current continuation remains no instructions (_implicit ret_), `c0` is invoked. Call-like instructions use it to store the current continuation in order to return to it after executing the inner function.\n\n## `c1` — alternative return continuation\n\n**Type**: Continuation\n\n**Initial value**: `Quit` — extraordinary continuation which terminates TVM with exit code `1`. Both exit codes `0` and `1` are considered successful terminations of TVM.\n\nSame as `c0`, but invoked only in special control flow instructions, such as [`RETALT`](/tvm/instructions#db31-retalt), [`IFRETALT`](/tvm/instructions#e308-ifretalt), and others.\n\n## `c2` — exception handler\n\n**Type**: Continuation\n\n**Initial value**: `ExcQuit` — extraordinary continuation which terminates TVM with an exception. In this case, the exit code is an exception number.\n\nInvoked implicitly on any exception that occurs during TVM execution. Can be invoked explicitly by [`THROW`](/tvm/instructions#f2c4_-throw)-like instructions. To set a custom exception handler, use [TRY](/tvm/instructions#f2ff-try).\n\n## `c3` — function selector\n\n**Type**: Continuation\n\n**Initial value**: Root cell of code currently executing in TVM.\n\nInvoked by [`CALLDICT`](/tvm/instructions#f0-calldict) instruction with a function ID (integer) passed on the stack. The function selector should jump to a function with that ID.\n\nFift-ASM assembler constructs following function selector ([`Asm.fif`:1624](https://github.com/ton-blockchain/ton/blob/4ebd7412c52248360464c2df5f434c8aaa3edfe1/crypto/fift/lib/Asm.fif#L1624)):\n\n```fift Fift\nSETCP0\n<{\n    // a dictionary which maps 19-bit function id (integer) => function code (slice)\n}> DICTPUSHCONST\nDICTIGETJMPZ  // get a function with given id from dictionary and execute it\n11 THROWARG  // if no function found, throw with exit code 11 and function id as additional argument\n```\n\n## `c4` — persistent account storage\n\n**Type**: Cell\n\n**Initial value**: Root cell of account data.\n\nThis register helps to store some information between smart contract invocations. When the transaction succeeds, the final value of `c4` is saved as new account data.\n\n## `c5` — outbound actions accumulator\n\n**Type**: Cell\n\n**Initial value**: Empty cell.\n\nList of actions to perform in the action phase after TVM execution: send a message, reserve funds, update code, and install libraries.\n\n`c5` has an `OutList` structure:\n\n```tlb title=\"TL-B\"\nout_list_empty$_ = OutList 0;\nout_list$_ {n:#} prev:^(OutList n) action:OutAction = OutList (n + 1);\n\naction_send_msg#0ec3c86d mode:(## 8) out_msg:^(MessageRelaxed Any) = OutAction;\naction_set_code#ad4de08e new_code:^Cell = OutAction;\naction_reserve_currency#36e6b809 mode:(## 8) currency:CurrencyCollection = OutAction;\n\nlibref_hash$0 lib_hash:bits256 = LibRef;\nlibref_ref$1 library:^Cell = LibRef;\naction_change_library#26fa1dd4 mode:(## 7) libref:LibRef = OutAction;\n```\n\nThe previous action is always the first reference of the next one. If action itself has a reference, it is stored as the second reference in the list. At the beginning of the list, an empty cell is stored as the first reference of the first action.\n\n## `c7` — environment information and global variables\n\n**Type**: Tuple\n\n**Initial value**: `Tuple[Tuple[0x076ef1ea, 0, 0, ...]]`.\n\nThe zero element of the `c7` tuple is an environment information (which itself is also a tuple). The remaining 255 slots are used for global variables. [`[i] SETGLOB`](/tvm/instructions#f87_-setglob) modifies `c7`, inserting an element with index `i`, [`[i] GETGLOB`](/tvm/instructions#f85_-getglob) reads `i`-th element from `c7`.\n\n### Structure of environment information tuple\n\n<table>\n  <thead>\n    <tr\n      class=\"text-left\"\n    >\n      <th>#</th>\n      <th>Instruction</th>\n      <th>Field</th>\n      <th>Type</th>\n      <th>Description</th>\n    </tr>\n  </thead>\n\n  <tbody>\n    <tr>\n      <td>0</td>\n      <td>-</td>\n      <td>0x076ef1ea</td>\n      <td>integer</td>\n      <td>tag of the <code>SmartContractInfo</code> TL-B structure</td>\n    </tr>\n\n    <tr>\n      <td>1</td>\n      <td>-</td>\n      <td>actions count</td>\n      <td>integer</td>\n      <td>increments when new action is pushed to `c5`.</td>\n    </tr>\n\n    <tr>\n      <td>2</td>\n      <td>-</td>\n      <td>messages sent</td>\n      <td>integer</td>\n      <td>increments when new `action_send_msg` is pushed to `c5`</td>\n    </tr>\n\n    <tr>\n      <td>3</td>\n      <td>NOW</td>\n      <td>unix time</td>\n      <td>integer</td>\n      <td>current time (timestamp of block collation)</td>\n    </tr>\n\n    <tr>\n      <td>4</td>\n      <td>BLOCKLT</td>\n      <td>current block LT (logical time)</td>\n      <td>integer</td>\n\n      <td />\n    </tr>\n\n    <tr>\n      <td>5</td>\n      <td>LTIME</td>\n      <td>current transaction LT</td>\n      <td>integer</td>\n\n      <td />\n    </tr>\n\n    <tr>\n      <td>6</td>\n      <td>RANDSEED</td>\n      <td>random seed</td>\n      <td>integer</td>\n      <td>`sha256(block_rand_seed . account_address)`</td>\n    </tr>\n\n    <tr>\n      <td>7</td>\n      <td>BALANCE</td>\n      <td>smart contract balance</td>\n      <td>tuple</td>\n      <td>tuple of integer (TON balance) and cell or `null` (extra currencies dictionary)</td>\n    </tr>\n\n    <tr>\n      <td>8</td>\n      <td>MYADDR</td>\n      <td>smart contract address</td>\n      <td>slice</td>\n\n      <td />\n    </tr>\n\n    <tr>\n      <td>9</td>\n      <td>CONFIGROOT</td>\n      <td>global blockchain configuration</td>\n      <td>cell or `null` (dictionary)</td>\n\n      <td />\n    </tr>\n\n    <tr>\n      <td>10</td>\n      <td>MYCODE</td>\n      <td>smart contract code</td>\n      <td>cell</td>\n\n      <td />\n    </tr>\n\n    <tr>\n      <td>11</td>\n      <td>INCOMINGVALUE</td>\n      <td>value of incoming message</td>\n      <td>tuple</td>\n      <td>tuple of integer (TON value) and cell or `null` (extra currencies dictionary)</td>\n    </tr>\n\n    <tr>\n      <td>12</td>\n      <td>STORAGEFEES</td>\n      <td>fees collected during storage phase</td>\n      <td>integer</td>\n\n      <td />\n    </tr>\n\n    <tr>\n      <td>13</td>\n      <td>PREVBLOCKSINFOTUPLE, PREVMCBLOCKS\\_100</td>\n      <td>last 16 masterchain blocks, last keyblock, and last 16 masterchain blocks with seqno divisible by 100</td>\n      <td>tuple</td>\n\n      <td>\n        tuple has following `PrevBlocksInfo` structure:\n\n        ```tlb\n        [ wc:Integer\n          shard:Integer\n          seqno:Integer\n          root_hash:Integer\n          file_hash:Integer ]\n        = BlockId;\n\n        [ last_mc_blocks:BlockId[]\n          prev_key_block:BlockId\n          last_mc_blocks_divisible_by_100:BlockId[] ]\n        = PrevBlocksInfo;\n        ```\n      </td>\n    </tr>\n\n    <tr>\n      <td>14</td>\n      <td>UNPACKEDCONFIGTUPLE</td>\n      <td>unpacked config values</td>\n      <td>tuple</td>\n\n      <td>\n        - 0: `StoragePrices` from the `ConfigParam 18` — not the whole dictionary, but only the one `StoragePrices` entry which corresponds to the current time\n        - 1: `ConfigParam 19`, global ID\n        - 2: `ConfigParam 20`, masterchain gas prices\n        - 3: `ConfigParam 21`, non-masterchain gas prices\n        - 4: `ConfigParam 24`, masterchain forward fees\n        - 5: `ConfigParam 25`, non-masterchain forward fees\n        - 6: `ConfigParam 43`, size limits\n      </td>\n    </tr>\n\n    <tr>\n      <td>15</td>\n      <td>DUEPAYMENT</td>\n      <td>current debt for storage fee in nanotons</td>\n      <td>integer</td>\n\n      <td />\n    </tr>\n\n    <tr>\n      <td>16</td>\n      <td>GETPRECOMPILEDGAS</td>\n      <td>gas usage for the current contract if it is precompiled, <code>null</code> otherwise</td>\n      <td>integer or `null`</td>\n      <td>see `ConfigParam 45`</td>\n    </tr>\n\n    <tr>\n      <td>17</td>\n      <td>INMSGPARAMS</td>\n      <td>inbound message parameters</td>\n      <td>tuple</td>\n\n      <td>\n        - 0: `bounce: boolean` — can bounce\n        - 1: `bounced: boolean` — did bounce\n        - 2: `src_addr: slice` — sender\n        - 3: `fwd_fee: int`\n        - 4: `created_lt: int`\n        - 5: `created_at: int`\n        - 6: `orig_value: int` — this is sometimes different from the value in `INCOMINGVALUE` and TVM stack because of storage fees\n        - 7: `value: int` — same as in `INCOMINGVALUE` and on the initial TVM stack\n        - 8: `value_extra: cell or null` — same as in `INCOMINGVALUE`\n        - 9: `state_init: cell or null`\n\n        For external messages, tick-tock transactions and get methods: `bounce`, `bounced`, `fwd_fee`, `created_lt`, `created_at`, `orig_value`, `value` are 0, `value_extra` is null.<br /><br /> For tick-tock transactions and get methods, `src_addr` is `addr_none`.\n      </td>\n    </tr>\n  </tbody>\n</table>\n"
  },
  {
    "path": "tvm/tools/retracer.mdx",
    "content": "---\ntitle: \"Retracer\"\n---\n\nimport { Image } from '/snippets/image.jsx';\n\n[Retracer](https://retracer.ton.org/) is a classic TVM transaction tracing tool that provides detailed inspection of transaction execution. It's useful for:\n\n- Understanding complex transaction flows;\n- Debugging smart contract behavior;\n- Analyzing gas usage and performance.\n\nSome explorers display links to Retracer on their transaction pages. Otherwise it's recommended to use a more modern [TxTracer](/tvm/tools/txtracer) tool.\n\nIts source code can be found on [GitHub](https://github.com/ton-blockchain/tvm-web-viewer/).\n\n<Image\n  src=\"/resources/images/retracer.png\"\n  darkSrc=\"/resources/images/retracer.png\"\n  alt=\"Retracer screenshot\"\n/>\n\nOn this screenshot, key elements of its interface are visible:\n\n- Transaction details — Sender, contract, amounts, time, LT, fees, and balances;\n- **C5** button — Display action list: complete details of all actions performed during the transaction;\n- **Logs** button — Detailed logs for deeper debugging;\n- List of instructions (on the left) — Steps taken by execution of the contract on TVM;\n- Stack (on the right) — Stack during execution of current instruction.\n"
  },
  {
    "path": "tvm/tools/ton-decompiler.mdx",
    "content": "---\ntitle: \"TON Decompiler\"\n---\n\n[TON Decompiler](https://github.com/tact-lang/ton-opcode) is an utility for converting [BoC](/foundations/serialization/boc) of the contract into a [Fift](/languages/fift/overview)-like pseudocode.\n\nDecompiled code cannot match match the original source. At the very least, variable names and high-level structure is removed during compilation. Variables and methods will get some generated names, for example, `?fun_ref_12345678`.\n\nThe resulting pseudocode might not compile back to the same BoC either.\n\n## CLI usage\n\nInstall Tact language tool suite.\n\n```bash\nnpm install -g @tact-lang/compiler\n```\n\nThen run it on a BoC file:\n\n```bash\nunboc example.boc\n```\n\n## API usage\n\nAdd it to the project\n\n```bash\nnpm install @tact-lang/ton-decompiler\n```\n\nThen call a disassembler to decompile it, and a writer to put the result back into Fift-like pseudocode.\n\n```ts\nimport { Cell } from \"@ton/core\";\nimport { disassembleRoot } from \"./decompiler/disasm\";\nimport { AssemblyWriter } from \"./printer/assembly-writer\";\n\nconst cell: Cell = ...; // your TVM contract bytecode\nconst program = disassembleRoot(cell);\nconst writer = new AssemblyWriter();\nconst code = writer.write(program);\nconsole.log(code);\n```\n"
  },
  {
    "path": "tvm/tools/tvm-explorer.mdx",
    "content": "---\ntitle: \"TVM Explorer\"\n---\n\nimport { Image } from '/snippets/image.jsx';\n\n[TVM Explorer](https://tvm-explorer.netlify.app/) is an interactive tool for exploring TVM assembly. Use it to see how your [Fift](/languages/fift) code compiles to TVM assembly. It allows\n\n- examining TVM bitcode and understanding instruction behavior;\n- seeing how Fift code translates to TVM instructions.\n\nFor more modern languages use TxTracer's [Playground](/tvm/tools/txtracer#2-playground).\n\n<Image\n  src=\"/resources/images/tvm-explorer.png\"\n  darkSrc=\"/resources/images/tvm-explorer.png\"\n  alt=\"TVM Explorer interface\"\n/>\n"
  },
  {
    "path": "tvm/tools/txtracer.mdx",
    "content": "---\ntitle: \"TxTracer\"\n---\n\nimport { Image } from '/snippets/image.jsx';\n\n[TxTracer](https://txtracer.ton.org/) is a multipurpose debugging tool for TVM, Tolk, and FunC.\n\nTools from a screenshot are described below in their separate sections.\n\n<Image\n  src=\"/resources/images/txtracer/root.png\"\n  darkSrc=\"/resources/images/txtracer/root.png\"\n  alt=\"TxTracer screenshot\"\n/>\n\nIts source code can be found on [GitHub](https://github.com/ton-blockchain/txtracer).\n\n## 1. TxTracer\n\nTxTracer's main tool allows stepping over TVM execution by transaction hash.\n\nPut a transaction hash into the input. Use playback controls on the right to step through execution of the TVM bitcode that happened when this transaction was executed. Below those controls, the UI displays a current TVM stack.\n\n<Image\n  src=\"/resources/images/txtracer/transaction-light.png\"\n  darkSrc=\"/resources/images/txtracer/transaction-dark.png\"\n  alt=\"Screenshot of tracing by transaction hash\"\n/>\n\n## 2. Playground\n\nPlayground is for stepping over arbitrary TVM Assembly (TASM) or FunC code.\n\nPut the code into the code editor on the left. Use playback controls on the right to step through execution of the TVM bitcode that happened when this transaction was executed. Below those controls, the UI displays a current TVM stack.\n\n<Image\n  src=\"/resources/images/txtracer/playground-light.png\"\n  darkSrc=\"/resources/images/txtracer/playground-dark.png\"\n  alt=\"Screenshot of tracing some assembly\"\n/>\n\n## 3. Code Explorer\n\nExplorer converts FunC/Tolk code to TVM Assembly (TASM).\n\nPut the code into the code editor on the left. The corresponding assembly code is on the right.\n\n<Image\n  src=\"/resources/images/txtracer/explorer-light.png\"\n  darkSrc=\"/resources/images/txtracer/explorer-dark.png\"\n  alt=\"Screenshot of conversion of FunC to assembly\"\n/>\n\n## 4. TVM Specification\n\nA modern version of TVM Specification.\n\nPut instruction name into the search field. Read about description, stack signature, and other effects of the instruction.\n\n<Image\n  src=\"/resources/images/txtracer/spec-light.png\"\n  darkSrc=\"/resources/images/txtracer/spec-dark.png\"\n  alt=\"Screenshot of search in TVM specification by prefix 'pl'\"\n/>\n\n## 5. Sandbox\n\nWeb interface that displays a trace from local [`@ton/sandbox`](/contract-dev/testing/reference).\n\nFollow instructions on the main page of the tool on how to set it up. The tool displays a trace of what happened during execution of the code in a local `@ton/sandbox`.\n\n<Image\n  src=\"/resources/images/txtracer/sandbox-light.png\"\n  darkSrc=\"/resources/images/txtracer/sandbox-dark.png\"\n  alt=\"Screenshot of a sample trace\"\n/>\n\n## 6. Emulate\n\nWeb interface that displays a trace from its [BoC](/foundations/serialization/boc).\n\n<Image\n  src=\"/resources/images/txtracer/emulate-light.png\"\n  darkSrc=\"/resources/images/txtracer/emulate-dark.png\"\n  alt=\"Screenshot of a sample trace\"\n/>\n"
  }
]