TOLK lang
847 subscribers
15 links
Channel devoted to TOLK — "next-generation FunC" — a language for writing smart contracts in TON
Download Telegram
🫧 Tolk v1.0: lazy loading, partial updating, AST inlining — and extremely low gas fees

This is happening today.

I managed not only to finish up the compiler, but also to migrate standard contracts from FunC to Tolk.

I covered every contract with gas metrics to check whether it's more efficient than FunC or not. I didn't believe my eyes. I double-checked, triple-checked, but nothing changed. The results are correct. And now I am ready to present them to you.

🧪 Benchmarks!

Every contract has several metrics. For example, "basic jetton — mint".
FunC: 19278. Tolk: 11611.
Gas savings: -39.77%

|————————————————–-
| 01 — Jetton (mint, transfer, burn, discover)
| -39.77% | -30.32% | -33.66% | -26.75%
|————————————————–-
| 02 — NFT (deploy, transfer, onchain get)
| -43.79% | -37.47% | -44.28%
|————————————————–-
| 03 — Notcoin
| -35.72% | -27.98% | ...
|————————————————–-
| 04 — tgBTC
| -23.94% | -26.99% | ...
|————————————————–-
| 05 — Wallet v5
| -21.66% | -22.92% | ...
|————————————————–-
| 06 — Vesting
| -45.30% | -29.61% | ...
|————————————————–-
| 07 — Telegram gifts
| -54.81% | -39.39% | ...
|————————————————–-

I have migrated 7 contracts — preserving the original behavior and passing the same tests.

All benchmarks are open. No cheating. Just a smart compiler — and a language designed to be optimized.

Even wallet?! But it's very low-level and tricky!

Even wallet. You just express your thoughts without any tricks — and it works automatically.

But how? How is it possible to achieve such numbers?

Of course, I've put a lot of smartness into the compiler. A strong type system. Automatic inlining. Built-in serialization. The magic lazy keyword.

But first of all, Tolk is built for readability. These contracts aren't "just cleaner" than their FunC equivalents — they're elegant. No magic. No low-level intrigues. Just clean, consistent logic — whether it's a Jetton or a Wallet.

And gas savings? They are a consequence. I didn't micro-optimize. Each contract was rewritten in about a day — just focusing on clarity. The core principle is simple: once you make it elegant, it automatically becomes efficient.


Notable changes in Tolk v1.0:

1. Lazy loading — only read what you actually use
2. AST-based inlining — zero-cost getters and methods
3. Peephole optimizations, TVM-11 — smaller code, lower gas

PR on GitHub with detailed info.

Just take a look:

val st = lazy Storage.load();
// the compiler skips everything and loads only what you access
return st.publicKey;


That's it. Lazy loading and partial updates (calculating immutable slices for writing) — one magic lazy keyword to rule them all.

⚙️ The Release. What's inside

- JetBrains IDE plugin — with completion, resolving, etc... ✓ done
- VS Code Extension — with suggestions, stdlib integration, etc... ✓ done
- Language server — for any LSP-compatible editor... ✓ done
- FunC-to-Tolk converter — migrate a project in 10 seconds... ✓ done
- Documentation — for smooth transition from FunC... ✓ done

And the TOLK language itself — exactly as I've visioned it... 7 months ago


📅 The essence of Numbers

At this moment, abstract yourself from the text. Take a look at the calendar.

Today is 07/07/25 (I mean 2+5, of course).

After the TON Gateway, throughout all November, I was laying out the roadmap towards Tolk v1.0. On December 1, I started working. It means, that the journey till now took exactly 7 months 7 days. If you scroll this channel to the top, you'll see an announcement... Of Tolk v0.7

🪐 What's next?

I could have written about my plans — for the language, TVM, ABI, TypeScript wrappers... but I won't.

Because today, instead of rushing into the future, maybe we can allow ourselves to look back.
To pause the endless race — just for a moment.
To notice how many beautiful coincidences pass us by — unnoticed in our constant hurry.

Just step outside.
Close your eyes.
Count to seven.
Feel it.

When you're ready —
Let's Tolk
🔥65👏2522👍72🤯2😱2
🫧 Tolk v1.1: built-in map<K,V>, enums, private and readonly fields, method overloads

Two months have passed — maybe you even started to worry about the silence. The reason is simple: I worked on features that are "nice to have" but complex and time-consuming to implement — and they've only just been finished.

Notable changes in Tolk v1.1:

1. map<K, V> — a convenient zero-overhead wrapper over TVM dictionaries
2. enum — group numeric constants into a distinct type
3. private and readonly fields in structures
4. Overload resolution and partial specialization

PR on GitHub with detailed info.

Built-in maps

Forget about uDictSetBuilder, sDictGetFirstAsRef, and the endless boilerplate of low-level dict helpers. A universal map<K, V> now fully replaces them.


var m: map<int8, int32> = createEmptyMap();
m.set(1, 10);
m.addIfNotExists(9, -90);
m.delete(9); // now: [ 1 => 10 ]
m.exists(1); // true
m.isEmpty(); // false


Just m.get() — no need to care about cells and slices under the hood:

val r = m.get(1);
if (r.isFound) { // true
val v = r.loadValue(); // 10
}

// or if the key 100% exists
val v = m.mustGet(1); // 10


Easily iterate forward and backward:

var r = m.findFirst();
while (r.isFound) {
// use r.getKey() and r.loadValue()
r = m.iterateNext(r);
}


Any serializable keys and values — it just works:

map<address, Point>
map<Point, Cell<Extra>>
map<int32, map<int64, bool>>
...


All in all:
- self-explanatory methods, nicely suggested by IDEs
- DICTISETREF, DICTREPLACE, DICTUREPLACEGET, ... — 100+ asm instructions covered by the type system
- all deserialization to/from cells perfectly hidden by high-level API
- absolutely zero overhead compared to low-level TVM dictionaries

Enums

A long-awaited syntax feature for grouping constants.


// will be 0 1 2
enum Color {
Red
Green
Blue
}


Being integers at runtime, enums have their own place in the type system. They resemble TypeScript/C++ enums. (Unlike Rust, where each variant may have its own shape. In Tolk we have union types — a more powerful solution)


struct Gradient {
from: Color
to: Color? = null
}

var g: Gradient = { from: Color.Blue };
g.from == Color.Red; // false


Compatible with all language features: auto-serialization, exhaustive pattern matching, generics, etc.

Private and readonly fields

Fields can now have modifiers:
* private — accessible only within methods
* readonly — immutable after object creation


struct PosInTuple {
private readonly t: tuple
curIndex: int
}

fun PosInTuple.last(mutate self) {
// `t` is visible only in methods
// and cannot be modified
self.curIndex = self.t.size() - 1;
}


Partial specialization

Now it's possible to overload methods for "more specific" implementations:


// general implementation
fun Iterator<T>.next(self) { ... }

// a more specific one
fun Iterator<Cell<T>>.next(self) { ... }


In complex scenarios, this feature lets you adjust the behavior of specific types while keeping a common interface. It "just works", but internally the compiler was enhanced with shape of types, structural depth, type dominators, and several heuristics.

🌳 After Tolk v1.0 release, many people and companies started migrating from FunC to Tolk. I have received a lot of feedback and requests (and almost zero bug reports, huh). Meanwhile, a bigger roadmap is already in motion. In the near future I'll also try to close long-standing questions around TypeScript wrappers, and deliver proper from-scratch documentation.
🔥2210👏5❤‍🔥3
🫧 Tolk v1.2: rich bounced messages, cheap deployment, and a breaking change that you'll love

Tolk v1.2 is here, aligned with TVM 12 — bringing new assembler instructions that make contracts cheaper and cleaner.

This update introduces one breaking change, several powerful new capabilities, and a few quality-of-life improvements across the compiler.

Notable changes in Tolk v1.2:

1. Breaking change: address is now "internal only"
2. Rich bounces: not 256 bits, but the full body on bounce
3. Cheap builder-to-slice, StateInit, and address composition
4. Improved compilation errors
5. Anonymous functions (lambdas)
6. Borrow checker to catch undefined behavior

PR on GitHub with detailed info.

`address` is now "internal only"

Before:
* address meant internal/external/none

Now:
* address — internal only
* address? (nullable) — internal/none, exactly like "maybe address" in @ton/core
* any_address — internal/external/none

In 99% of contracts only internal addresses are used. External ones are rare, and "none" can be expressed as nullable.


struct Storage {
// internal, checked automatically
owner: address
}


With new TVM 12 instructions, addresses are validated automatically during (de)serialization without extra gas — no more manual isInternal() checks.

So yes, it's technically a breaking change, but it removes a ton of noise.

A short migration guide, as well as technical details, available here.

Rich bounced messages

Historically, a bounced message only returned the first 256 bits of the original body.

Now TVM 12 supports rich bounces — which lets you obtain the entire body instead.


createMessage({
    bounce: BounceMode.RichBounce,
    ...
})


In onBouncedMessage, you get access to the original body, exit code, gas used, and more.

Old true/false bounce flags still work for backward compatibility.

Rich bounces simplify complex message flows and inter-contract communication — one of the most painful aspects of TON until now.

Cheap builder-to-slice and address composition

Previously, converting a builder to a slice (endCell + beginParse) consumed a lot of gas because cells are expensive. Now there's a new instruction — BTOS (builder-to-slice) — without intermediate cell creation.

- b.endCell().beginParse() is now cheap: auto-optimized to BTOS
- "builder-to-address" is the same BTOS; hacks around "return a builder with a valid address" can be removed
- cheaper StateInit hashing and address calculations

Just update to Tolk v1.2 + TVM 12, and you'll immediately save gas.

Anonymous functions (lambdas)

Can be used in general-purpose frameworks, perfectly integrated with the type system:


fun customRead(reader: (slice) -> int) { ... }

customRead(fun(s) {
return s.loadUint(32)
})


Low-level compiler enhancements

Also included: better diagnostics with precise ranges, new peephole optimizations, tuple object conversions, and multiple small fixes. A lightweight borrow checker prevents undefined behavior on concurrent mutations.

As always, all additions are carefully described in a PR.

🌳 We've also started improving TVM itself — new assembler instructions are designed specifically to fit the Tolk type system and optimizer. I have always said: the language is just the beginning. Perfect developer experience requires improving every layer of TON's stack. The road may be sharp and curvy — but we're definitely heading in the right direction.
🔥2318👍12
🫧 Tolk documentation — now complete and available for learning from scratch

From now on, Tolk has full, structured, from-scratch documentation — not just "Tolk vs FunC", but a complete language guide that lets developers approach Tolk directly, without any FunC background.

This is a major milestone. Tolk is the recommended language for TON, and now it finally has documentation that matches this role.

Read →

↓ What's inside

The documentation covers the entire language:

Type system.
Every type on its own page: numbers, addresses, structures, generics, etc. — plus overall explanations for TVM layout and serialization.

Syntax details.
Functions, conditions, loops, exceptions, and more — with minimal descriptions and clear examples.

Language features.
Everything needed for smart-contract development: message sending, contract storage, automatic serialization, etc.

Migration from FunC.
A complete guide for FunC builders — including the mindset shift Tolk encourages.

... And several articles for experienced divers. They reveal compiler internals and the language philosophy. My favourite — Stop thinking in TL-B.

㉈ Hundreds of examples

Every distinct aspect is covered with usage examples — properly highlighted in both light and dark mode.

No matter whether you are new to TON or have been here for years — you'll definitely find a few tricks you've never seen before.

∞ This documentation in numbers

All together, the new Tolk documentation contains:
• 46 pages
• 480 snippets
• 40000 words
• 280000 characters

I invested ~200 hours developing the text and picking every word.
I hope that, cumulatively, this documentation will save noticeably more time for all TON developers.

→ Start reading

https://docs.ton.org/languages/tolk

🌳 Thanks to everyone who reviewed the pull request and pointed out occasional mistakes or misprints. Just imagine the amount of content they had to deal with.
🔥32🏆128👏5🥰2
🫧 Tolk v1.3... not released yet: what's happening inside

I know it has been quiet.

The last public Tolk update was three months ago, so the question is fair:

Where did I go, and why is there still no v1.3?

I did not disappear. I have been working on something much bigger than the next language release.

A huge part of my focus has shifted toward building a TON toolchain together with the team.

Not another small utility. Not another isolated CLI. A full development environment built as one coherent system — around Tolk.

⚙️ So what do I mean by a toolchain?

The core of TON development. A single tool that:

Scaffolds real projects. Contracts, unit tests, integration tests, TypeScript wrappers, and ready-to-use templates.

Runs tests. 50x faster than the current JS sandbox. And even more: tests are native, no Node.js required.

Gives you a real debugger. Test failed with exit code 9? Stop exactly at the exception, inspect the call stack, local variables, lazy fields, and more. One thing I am especially proud of: there is no "compile without optimizations" mode. It works with fully-optimized production contracts.

Visualizes transaction flows. Run a test and immediately see the full chain of generated transactions in a clean local UI.

Covers the rest of the workflow too: code coverage and gas profiling; formatter and language server; verifier and ABI generation; all of it AI-friendly, with agent skills and MCP built-in.

The goal is to reboot development on TON

When Tolk appeared, it made FunC feel like the old world. Tolk is not just "a bit better" — it feels like a different era.

Now we are doing the same for the entire on-chain development stack. Not just to improve existing tools a little — but the current approach will feel fundamentally outdated.

🌳 I originally planned to announce all of this at TON Gateway. But it was cancelled, so I am lifting the curtain a little earlier.

The timeline has not changed: early May.

And early May is very close.
32🔥25👍18🆒3
🫧 Tolk v1.3: moving toward a general-purpose language

After the previous post, this release may feel less surprising — but still a bit unusual.

The reason is simple: Tolk is no longer evolving only as a contract language. It is becoming a foundation for the toolchain I described earlier.

This release focuses on features beyond contracts — introducing general-purpose capabilities needed for libraries and frameworks.

Notable changes in Tolk v1.3:

1. Type array<T> — dynamically sized arrays backed by TVM tuples.
2. Type unknown — a TVM primitive with unknown contents.
3. Type lisp_list<T> — nested two-element tuples (FunC-style).
4. Type string — text chunks backed by snaked cells, with StringBuilder for concatenation.
5. Compile-time string methods: "str".crc32(), "str".sha256(), etc.
6. Null coalescing operator — ?? like in TypeScript.
7. Import path mappings — import "@third_party/utils".
8. Compile-time reflection via @stdlib/reflection.
9. Custom serializers now support structures and generics.
10. The compiler now reports multiple errors at once.
11. Focused on stability — fixed dozens of minor issues found by LLM fuzzing.
12. Extensive internal refactoring towards being stateless and multi-threaded.

PR on GitHub with detailed info.

Arrays: redesigned tuples

Working with TVM tuples has been fully redesigned. There is now array<T> — a dynamically sized container:


// array<int>
var numbers = [1, 2, 3];

// array<Point?>
var optPoints = [
Point { x: 10, y: 20 },
Point { x: 30, y: 40 },
null,
];


- methods push, get(idx), etc.
- any T, including sub-arrays like array<array<int>>
- automatically serialized into snake cells
- max size: 255 (TVM limitation)

The `unknown` type

Raw TVM tuple exists, but it's no longer built-in. It's just an array... of something unknown:


type tuple = array<unknown>


The unknown gives access to the untyped TVM stack, fully integrated into the type system.

The `string` type

TVM has no strings — only binary slices. Strings were always just a convention over binary data.

Now Tolk has strings built-in.


// string
val str = "hello";


- strings are cells (not slices)
- long strings are snake cells under the hood
- methods calculateLength, equalTo, etc.
- on-chain/off-chain encoding for jettons and NFTs to comply with TEPs

StringBuilder encapsulates cell manipulation:


StringBuilder.create()
.append(content.commonContent)
.append(individualNftContent)
.build()


By the way, compile-time functions now look cleaner: "str".crc32() and so on.

Import path mappings

The import statement now accepts @aliases:


import "@common/jettons"
import "@third_party/math-lib"


This is similar to widely used path mappings in TypeScript.

Compile-time reflection

Many additions in v1.3 make sense not for contracts, but for frameworks. For example, take a look at one of reflect features:


fun log(msg: string, loc: SourceLocation = reflect.sourceLocation()) {
debug.print(loc.lineNo);
}

fun demo() {
log("a"); // prints K — current line no
log("b"); // prints K+1
}


Why is this useful? It allows errors to point to the original call site — for example, expect(...) in tests — by carrying source location at compile time.

⚙️ A huge portion of internal refactoring

A lot of work has been done inside the compiler core, peephole optimizations, and memory management.

Final result: tolk compiler is now thread-safe and re-invokable within a single process. It will be embedded into an external toolchain written in Rust, communicating via FFI.

... And more

Dozens of independent improvements. Combined, they cover the requirements not only for contracts, but for abstract libraries and the upcoming toolchain.

Feel free to check the description on GitHub.

🌳 And one more thing! Wallet-v5, compiled with Tolk v1.3, reduces gas usage by 30% compared to FunC. As of Tolk v1.0, the savings were "only" 20%. Take a look at new benchmarks.
🔥2312🤩6👍2🙏2🦄2👏1🍾1
🫧 TON enters a new era of smart-contract development

I promised this would happen in May.

Today we release:

• Tolk v1.4
• Acton — a unified toolchain for TON smart contracts

For more than half a year, we have been building this almost entirely in secret.

And honestly, this is the biggest release we have ever shipped at once.

⚙️ What is Acton?

Acton is an all-in-one CLI built around Tolk — a modern replacement for the fragmented tooling stack TON has today.

✓ Write tests directly in Tolk — including transaction flows and cross-contract interaction. 50x faster than current Sandbox + TypeScript approach.

✓ Automatic TypeScript wrappers. But not for tests! For end-to-end dApp/frontend integration.

✓ A native debugger. Step in, step over, step out, watch variables, and inspect the call stack. A smooth Web2-style developer experience — now inside a Web3 ecosystem.

✓ Entire contract lifecycle. Develop, deploy, verify, configure, and interact with contracts on-chain. Acton manages wallets and faucet top‑ups on testnet.

✓ Security built in. Coverage, fuzzing, mutation testing, gas profiling, and CI help catch regressions early.

🤖 Friendly for AI agents

One interesting thing we discovered while building Acton: good tooling for humans naturally becomes good tooling for AI.

We designed Acton for ourselves first. Every command, every flag, every workflow — polished to feel coherent and predictable.

And it turned out that agents thrive in exactly this kind of environment.

CLI-first by design, Acton becomes an agent's runtime — with structured commands, built-in skills and manuals.

🛠️ Tolk v1.4 as the foundation

None of this would be possible without the kernel behind it all: the compiler itself.

Tolk v1.4 allows external tools to finally understand the contract.

1. It emits ABI — describing how the contract is "seen" by the outside world. Explorers, frontend UI and TypeScript wrappers naturally build on top of ABI.
2. It emits source maps — allowing TVM execution to map back to Tolk source code, local variables, stack layout, and call frames.
3. It enables debugging WITHOUT bytecode modifications — for fully optimized production contracts.

This is an extremely non-trivial problem technically. But it works.

And here is the crazy part:

you can take a failed transaction from the real mainnet — and debug it step-by-step locally in your IDE.

As always — PR on GitHub with detailed info.
As always — very long and caring.

🪐 Where does it all lead?

We have prepared detailed documentation for dozens of Acton features — both for experts and newcomers.

But I am not inviting you to read it.

Instead, I am inviting you to the landing page.

Carefully designed. Written from scratch. A distilled form of the last 7 months of work.

It contains 7 videos.

Open it on desktop.
Turn on the sound.
Watch the videos.

Feel the technical depth hiding behind all this simplicity.

https://ton-blockchain.github.io/acton/

When you're ready —
Act on
🔥48💯16🤩136🤯3🙈2❤‍🔥1🙏1