# Tolk vs FunC (https://docs-kyrm16yq7-ton-core-docs.vercel.app/llms/tolk/from-func/tolk-vs-func/content.md)



FunC is the first high-level language for TON smart contracts. Legacy FunC codebases exist, but the compiler is no longer maintained.
Tolk is the primary and only actively supported language in the TON ecosystem.

## Migrating from FunC to Tolk [#migrating-from-func-to-tolk]

1. Review the list of [differences](/llms/languages/tolk/from-func/tolk-vs-func/content.md).
2. See the [Tolk contract examples](/llms/languages/tolk/examples/content.md) page.
3. Use the [FunC-to-Tolk converter](/llms/languages/tolk/from-func/converter/content.md) to migrate existing projects.

## Gas benchmarks [#gas-benchmarks]

The [`tolk-bench` repository](https://github.com/ton-blockchain/tolk-bench) compares FunC and Tolk across several TEP contracts. See the [Tolk contract examples](/llms/languages/tolk/examples/content.md) page for selected cases.

Across all measured metrics, Tolk reduces gas consumption by 30–50% compared to FunC. This reduction is primarily due to differences in language design.

## Common characteristics [#common-characteristics]

* Both languages compile to Fift assembler.
* Both languages run on [TVM](/llms/tvm/overview/content.md) after compilation to bitcode.
* Both languages are supported by [IDE plugins](/llms/contract-dev/ide/overview/content.md).
* Both languages are available in [Blueprint](/llms/contract-dev/blueprint/overview/content.md) and other client-side tooling. However, best support for Tolk is provided in the [Acton](/llms/contract-dev/acton/content.md) development environment.
* Both support command-line usage.

## Key differences [#key-differences]

The differences between Tolk and FunC are primarily in language design rather than syntax.

### Basic syntax [#basic-syntax]

* FunC resembles C, the name stands for "functional C".
* [Tolk resembles](/llms/languages/tolk/basic-syntax/content.md) TypeScript, Rust, and Kotlin.

```tolk
fun sum(a: int, b: int): int {
    return a + b;
}
```

### Structures [#structures]

* FunC uses unnamed tensors such as `(int, slice, int, int)`.
* Tolk uses named [structures](/llms/languages/tolk/syntax/structures-fields/content.md) with the same runtime efficiency.

```tolk
struct Demo {
    previousValue: int256
    ownerAddress: address
    effectsCount: uint32
    totalAmount: coins
}
```

### Automatic serialization [#automatic-serialization]

* FunC requires manual bit-level serialization using builders and slices.
* Tolk derives [serialization](/llms/languages/tolk/features/auto-serialization/content.md) from `struct` using `toCell` and `fromCell`.

```tolk
struct Point {
    x: int8
    y: int8
}

fun demo() {
    var value: Point = { x: 10, y: 20 };

    // makes a cell containing "0A14" (hex)
    var c = value.toCell();
    // back to { x: 10, y: 20 }
    var p = Point.fromCell(c);
}
```

All [integer types](/llms/languages/tolk/types/numbers/content.md) such as `int8`, `uint64`, and `coins` are TVM integers.

### Lazy loading [#lazy-loading]

* FunC requires manual control over preloads and skips for optimization.
* Tolk uses the [`lazy` keyword](/llms/languages/tolk/features/lazy-loading/content.md) to load only accessed fields.

```tolk
get fun publicKey() {
    val st = lazy Storage.load();
    // <-- here "skip 65 bits, preload uint256" is inserted
    return st.publicKey
}
```

### Boolean type [#boolean-type]

* FunC represents only integers: `-1` for true, `0` for false; `ifnot`.
* Tolk provides a [`bool` type](/llms/languages/tolk/types/booleans/content.md) and logical operators `&&`, `||`, and `!`. Conditions of `if`, `while`, ternary, and `assert` must be `bool` — write `if (someInt != 0)` instead of `if (someInt)`.

```tolk
if (trustInput || validate(input)) {
    // ...
}
```

### Address type [#address-type]

* FunC represents only slices; bits comparison and parsing.
* Tolk provides a [`address` type](/llms/languages/tolk/types/address/content.md) with methods and the `==` operator.

```tolk
if (in.senderAddress == storage.ownerAddress) {
    val workchain = storage.ownerAddress.getWorkchain();
    // ...
}
```

### Null safety [#null-safety]

* FunC allows any variable to hold `null`, which may lead to runtime errors.
* Tolk provides [nullable types](/llms/languages/tolk/types/nullable/content.md) `T?`, null safety, and smart casts.

```tolk
fun checkWithOptional(a: int, b: int?): bool {
    if (b == null) {
        return checkSingle(a);
    }
    return b >= 0 && checkDouble(a, b);
}
```

### Type system features [#type-system-features]

* FunC provides several types that expose TVM primitives.
* Tolk provides [a type system](/llms/languages/tolk/types/list-of-types/content.md), including unions, generics, and enums.

```tolk
struct Container<T> {
    element: T?
}

struct Nothing

type Wrapper<T> = Nothing | Container<T>
```

### Methods for all types [#methods-for-all-types]

* FunC provides functions in the global scope only.
* Tolk provides both [functions and methods](/llms/languages/tolk/syntax/functions-methods/content.md), applicable to structures and primitives.

```tolk
// no `self` — static method
fun Point.createZero(): Point {
    return { x: 0, y: 0 }
}

// has `self` — instance method
fun Point.sumCoords(self) {
    return self.x + self.y
}

// even for primitives: cells, integers, tuples, etc.
fun tuple.isEmpty(self) {
    return self.size() == 0
}
```

### No `impure` keyword [#no-impure-keyword]

* In FunC, if `impure` is omitted, a function call may be dropped.
* In Tolk, user function calls are not removed by the compiler.

```tolk
fun validate(input: SomeStruct) {
    // ...
}
```

### No `~` tilde methods [#no--tilde-methods]

* FunC distinguishes between `x~f()` and `x.f()`.
* Tolk uses a dot `.` syntax for method calls.

```tolk
val delta = someSlice.loadUint(32);   // mutates someSlice
val owner = someSlice.loadAddress();
```

### Native maps over TVM dictionaries [#native-maps-over-tvm-dictionaries]

* FunC uses dictionaries, for example `m~idict_set_builder(1,32,begin_cell().store_uint(10,32))`.
* Tolk provides native [maps](/llms/languages/tolk/types/maps/content.md), for example `m.set(1, 10)`.

```tolk
var m: map<int8, int32> = [];
m.set(1, 10);
m.addIfNotExists(2, -20);
m.delete(2);   // now: [ 1 => 10 ]
```

### Message handling [#message-handling]

* FunC defines `() recv_internal(4 params)` and parses a message cell.
* Tolk provides [`onInternalMessage(in)`](/llms/languages/tolk/features/message-handling/content.md) and use `in.senderAddress`, etc.

```tolk
fun onInternalMessage(in: InMessage) {
    // internal non-bounced messages arrive here
    in.senderAddress;
    in.originalForwardFee;
    // and other fields
}

fun onBouncedMessage(in: InMessageBounced) {
    // bounced messages arrive here
}
```

### Message routing [#message-routing]

* FunC routes incoming messages using `if-else` checks on the `opcode`, for example `if (op == OP_TRANSFER)`.
* Tolk routes messages using union types and [pattern matching](/llms/languages/tolk/syntax/pattern-matching/content.md).

```tolk
type MyMessage =
    | CounterIncBy
    | CounterReset
    // ...

fun onInternalMessage(in: InMessage) {
    val msg = lazy MyMessage.fromSlice(in.body);
    match (msg) {
        CounterIncBy => {
            // ...
        }
        CounterReset => {
            // ...
        }
        // ...
    }
}
```

### Empty messages handling [#empty-messages-handling]

* FunC checks for empty message bodies using `if (slice_empty?(...))` at the beginning of `recv_internal()`.
* Tolk handles empty or unknown messages using `else` in a [`lazy` matching](/llms/languages/tolk/features/lazy-loading/content.md).

```tolk
fun onInternalMessage(in: InMessage) {
    val msg = lazy MyMessage.fromSlice(in.body);
    match (msg) {
        CounterReset => { /* ... */ }
        // ... handle all variants of the union

        else => {
            // for example: ignore empty messages
            if (in.body.isEmpty()) {
                return
            }
            throw 0xFFFF
        }
    }
}
```

### Message composition [#message-composition]

* FunC requires manual bit-level message construction, for example `store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)`.
* Tolk provides [`createMessage`](/llms/languages/tolk/features/message-sending/content.md), which automatically chooses between inline body and body reference.

```tolk
val reply = createMessage({
    bounce: BounceMode.NoBounce,
    value: grams("0.05"),
    dest: senderAddress,
    body: RequestedInfo { ... }
});
reply.send(SEND_MODE_REGULAR);
```

### Deployment and `StateInit` [#deployment-and-stateinit]

* FunC requires manual packing of contract code and data according to TL-B.
* Tolk uses `createMessage` to attach `StateInit` and compute the destination automatically.

```tolk
val deployMsg = createMessage({
    // address auto-calculated, code+data auto-attached
    dest: {
        stateInit: {
            code: contractCodeCell,
            data: emptyStorage.toCell(),
        },
        // optionally control workchains and sharding
    }
});
```

### Identifier syntax [#identifier-syntax]

* FunC allows arbitrary symbols in identifiers, for example `var 2+2 = ...`.
* Tolk allows only [alphanumeric identifiers](/llms/languages/tolk/syntax/variables/content.md), for example  `2+2` is `4`.

```tolk
const OP_INCREASE = 0x12345678
```

### Automatic inlining of small functions [#automatic-inlining-of-small-functions]

* In FunC, prefer larger functions for reduced gas consumption.
* In Tolk, the compiler auto-inlines functions without additional gas cost.

```tolk
fun int.zero() {
    return 0
}

fun int.inc(mutate self, byValue: int = 1): self {
    self += byValue;
    return self;
}

fun main() {
    return int.zero().inc().inc()
}
```

Is reduced to `return 2` in assembler:

```fift
main() PROC:<{
    2 PUSHINT
}>
```

In 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](/llms/languages/tolk/features/compiler-optimizations/content.md).

### Merging consecutive `builder.storeUint` [#merging-consecutive-builderstoreuint]

* FunC manually combines constant stores into `b.storeUint(0x18,6)`.
* Tolk merges `b.storeUint(...).storeUint(...)` if constant.

```tolk
b.storeUint(0, 1)
 .storeUint(1, 1)
 .storeUint(1, 1)
 .storeUint(0, 1)
 .storeUint(0, 2)
```

Translated to:

```fift
b{011000} STSLICECONST
```

### Standard library redesigned [#standard-library-redesigned]

There are [differences between standard libraries](/llms/languages/tolk/from-func/stdlib-fc/content.md). For example, functions from `stdlib.fc` started having descriptive names:

|         FunC         |              Tolk              |
| :------------------: | :----------------------------: |
|      `cur_lt()`      |   `blockchain.logicalTime()`   |
|       `car(l)`       |        `list.getHead()`        |
| `raw_reserve(coins)` | `reserveGramsOnBalance(coins)` |
|      `~dump(x)`      |        `debug.print(x)`        |

Many global-scope functions became methods for primitives:

|            FunC            |         Tolk        |
| :------------------------: | :-----------------: |
|      `s.slice_hash()`      |      `s.hash()`     |
|  `equal_slices_bits(a, b)` |   `a.bitsEqual(b)`  |
|       `t.tuple_len()`      |      `t.size()`     |
| `t~tpush(triple(x, y, z))` | `t.push([x, y, z])` |

String postfixes like `"..."c` became compile-time methods on strings:

|   FunC   |         Tolk         |
| :------: | :------------------: |
| `"..."c` |    `"...".crc32()`   |
| `"..."H` |   `"...".sha256()`   |
| `"..."h` |  `"...".sha256_32()` |
| `"..."s` | `"...".hexToSlice()` |
| `"..."u` |  `"...".toBase256()` |
| `"..."a` |   `address("...")`   |

### Assembler functions [#assembler-functions]

Although Tolk is a high-level language, it exposes [low-level capabilities](/llms/languages/tolk/features/asm-functions/content.md). Code may still be written in a FunC-style with manual builders and slices, and TVM instructions are supported.

```tolk
@pure
fun incThenNegate(v: int): int
    asm "INC" "NEGATE"
```

### ABI, TypeScript wrappers, and a debugger [#abi-typescript-wrappers-and-a-debugger]

* FunC has no machine-readable interface description — clients hand-roll wrappers and rely on heuristics.
* Tolk emits an [ABI JSON](/llms/languages/tolk/features/contract-abi/content.md) directly from sources whenever a file declares a `contract { ... }`. The same metadata drives auto-generated TypeScript wrappers, source maps, and a step-by-step debugger that works on fully-optimized bytecode.
