Migrating from FunC to Tolk
- Review the list of differences.
- Refer to the reference contracts on GitHub.
- Use the FunC-to-Tolk converter to migrate existing projects.
Gas benchmarks
The tolk-bench repository compares FunC and Tolk across several TEPs. 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
- Both languages compile to Fift assembler.
- Both languages run on TVM after compilation to bitcode.
- Both languages are supported by IDE plugins.
- Both languages are available in Blueprint and other client-side tooling.
- Both support command-line usage.
Key differences
The differences between Tolk and FunC are primarily in language design rather than syntax.Basic syntax
- FunC resembles C, the name stands for “functional C”.
- Tolk resembles TypeScript, Rust, and Kotlin.
Structures
- FunC uses unnamed tensors such as
(int, slice, int, int). - Tolk uses named structures with the same runtime efficiency.
Automatic serialization
- FunC requires manual bit-level serialization using builders and slices.
- Tolk derives serialization from
structusingtoCellandfromCell.
int8, uint64, and coins are TVM integers.
Lazy loading
- FunC requires manual control over preloads and skips for optimization.
- Tolk uses the
lazykeyword to load only accessed fields.
Boolean type
- FunC represents only integers:
-1for true,0for false;ifnot. - Tolk provides a
booltype and logical operators&&,||, and!.
Address type
- FunC represents only slices; bits comparison and parsing.
- Tolk provides a
addresstype with methods and the==operator.
Null safety
- FunC allows any variable to hold
null, which may lead to runtime errors. - Tolk provides nullable types
T?, null safety, and smart casts.
Type system features
- FunC provides several types that expose TVM primitives.
- Tolk provides a type system, including unions, generics, and enums.
Methods for all types
- FunC provides functions in the global scope only.
- Tolk provides both functions and methods, applicable to structures and primitives.
No impure keyword
- In FunC, if
impureis omitted, a function call may be dropped. - In Tolk, user function calls are not removed by the compiler.
No ~ tilde methods
- FunC distinguishes between
x~f()andx.f(). - Tolk uses a dot
.syntax for method calls.
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, for example
m.set(1, 10).
Message handling
- FunC defines
() recv_internal(4 params)and parses a message cell. - Tolk provides
onInternalMessage(in)and usein.senderAddress, etc.
Message routing
- FunC routes incoming messages using
if-elsechecks on theopcode, for exampleif (op == OP_TRANSFER). - Tolk routes messages using union types and pattern matching.
Empty messages handling
- FunC checks for empty message bodies using
if (slice_empty?(...))at the beginning ofrecv_internal(). - Tolk handles empty or unknown messages using
elsein alazymatching.
Message composition
- FunC requires manual bit-level message construction, for example
store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1). - Tolk provides
createMessage, which automatically chooses between inline body and body reference.
Deployment and StateInit
- FunC requires manual packing of contract code and data according to TL-B.
- Tolk uses
createMessageto attachStateInitand compute the destination automatically.
Identifier syntax
- FunC allows arbitrary symbols in identifiers, for example
var 2+2 = .... - Tolk allows only alphanumeric identifiers, for example
2+2is4.
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.
return 2 in assembler:
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.
Merging consecutive builder.storeUint
- FunC manually combines constant stores into
b.storeUint(0x18,6). - Tolk merges
b.storeUint(...).storeUint(...)if constant.
Standard library redesigned
There’re differences in a standard library. For example, functions fromstdlib.fc use descriptive naming:
| FunC | Tolk |
|---|---|
cur_lt() | blockchain.logicalTime() |
car(l) | listGetHead(l) |
raw_reserve(coins) | reserveToncoinsOnBalance(coins) |
~dump(x) | debug.print(x) |
| 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]) |
"..."c became built-in functions:
| FunC | Tolk |
|---|---|
"..."c | stringCrc32("...") |
"..."H | stringSha256("...") |
"..."h | stringSha256_32("...") |
"..."a | address("...") |
"..."s | stringHexToSlice("...") |
"..."u | stringToBase256("...") |