
Research
Malicious npm Packages Impersonate Flashbots SDKs, Targeting Ethereum Wallet Credentials
Four npm packages disguised as cryptographic tools steal developer credentials and send them to attacker-controlled Telegram infrastructure.
@ton/convert-func-to-tolk
Advanced tools
Tolk is a next-generation language for smart contracts in TON. It replaces FunC with modern syntax, strong types, and built-in serialization — while generating even more efficient assembler code.
Using single command, you can transform an exising FunC project to Tolk:
// all .fc files in a folder
npx @ton/convert-func-to-tolk contracts
// or a single file
npx @ton/convert-func-to-tolk jetton-minter.fc
Example input: jetton-minter.fc
Example output: jetton-minter.tolk
This is a syntax-level converter that helps migrate FunC contracts to Tolk. It rewrites your code with 1:1 semantics — so you get a Tolk version of your contract that "looks and smells" like FunC.
The converted contract won't use modern Tolk features like struct
, auto-serialization, or clean message composition. But after some manual fixes, it compiles, runs, and passes tests.
From there, you can gradually modernize the code — step by step, while keeping it functional at every stage.
Not required: just use npx
above.
npx
above uses default options, but here is what you can pass:
--warnings-as-comments
— insert /* _WARNING_ */
comments (not just print warnings to output)--no-camel-case
— don't transform snake_case to camelCase;; comment
→ // comment
#include
→ import
#pragma
int f(slice a)
→ fun f(a: slice): int
global slice cs
→ global cs: slice
int a = 0
→ var a: int = 0
var (int a, slice b) = …
→ var (a: int, b: slice) = …
impure
specifiers (inserting @pure
for asm functions)inline
and inline_ref
specifiers with @
attributesmethod_id
to get methods: int seqno() method_id
→ get seqno(): int
forall
to generics syntax: forall X -> X f()
→ fun f<X>(): X
op:increase
→ `op:increase`
ifnot (x)
→ if (!x)
and similarthrow_unless(condition, excNo)
→ assert(excNo, condition)
and similarnull()
→ null
null?(x)
→ x == null
begin_cell
→ beginCell
, end_parse
→ assertEnd
, etc.~
declarations: (slice, int) ~load_op(slice s) { return s~load_uint(32); }
→ fun slice.loadOp(mutate self): int { return self.loadUint(32); }
~method()
with .method()
recv_internal
→ onInternalMessage
and similar"str"c
→ stringCrc32("str")
and othersaddress
instead of slice
Of course, the convertion result seems quite dirty. For instance, Tolk has logical operators, and therefore if (~ found)
could probably be if (!found)
. For instance, assert(!(a < 0))
is actually assert(a >= 0)
. And so on.
Contracts written in modern Tolk from scratch look much nicer. But that's what exactly expected from auto-conversion.
Helpful link: Tolk vs FunC: in short.
Almost all problems are related to methods. For two reasons:
~methods
and .methods
, Tolk has only .methods
, which may mutate, or may not, the first self
parameter.f(x)
to be called as a method x.f()
, Tolk does not: functions and methods are different, like in other languages.If a method was called strangely in FunC, it becomes an incorrect call in Tolk:
// FunC
int r = n~divmod(10);
// auto-converted, incorrect now
var r: int = n.divMod(10);
This line should be rewritten:
var (newN, r) = divMod(n, 10);
// use newN or assign n = newN
// alternatively, use `redef` keyword:
var (n redef, r) = divMod(n, 10);
Lots of stdlib functions became mutating. This way, cs~load_int(32)
replaced by cs.loadInt(32)
works equally, but cs.skip_bits(8)
(with dot! not tilda) replaced by cs.skipBits(8)
works differently, because skipBits()
mutates an object.
Hence, if you used dot-call for .methods
which become mutating, that part should be rewritten (it either won't compile or would work differently). Most common cases are skip
-functions and dict
-functions. Dict API in Tolk is mutating. If you used dict~udict_set(…)
, it was replaced by dict.uDictSet(…)
, and everything is fine. But if you used dict.udict_set(…)
to get a copy, it's a problem.
The converter prints warnings in such cases. Some are falsy, but most are related to this exact problem.
Deep dive: Tolk vs FunC: mutability.
If you had a function in FunC
builder store_msg_flags_and_address_none(builder b, int msg_flags) inline {
return b.store_uint(msg_flags, 6);
}
// and somewhere
begin_cell()
.store_msg_flags_and_address_none(BOUNCEABLE)
...
This will be auto-converted but won't compile:
@inline
fun storeMsgFlagsAndAddressNone(b: builder, msgFlags: int): builder {
return b.storeUint(msgFlags, 6);
}
// and somewhere
beginCell()
.storeMsgFlagsAndAddressNone(NON_BOUNCEABLE) // won't compile
...
It won't compile with a message:
error: method `storeMsgFlagsAndAddressNone` not found for type `builder`
In FunC, cell_hash(c)
and c.cell_hash()
were equivalent. This is a reason why cell_hash
and slice_hash
are different functions.
In Tolk, functions and methods are different. cell.hash()
and slice.hash()
are now different methods (not global functions). Stdlib contains short names: you call tupleVar.size()
instead of tupleVar.tupleSize()
, and so on.
Hence, you should transform storeMsgFlagsAndAddressNone
into a method for builder
. Since it modifies a builder, it's a mutating method. Since it's chainable, it returns self
:
@inline
fun builder.storeMsgFlagsAndAddressNone(mutate self, msgFlags: int): self {
return self.storeUint(msgFlags, 6);
}
Some stdlib functions were removed. For instance, pair(a,b)
removed, as it can be replaced with [a,b]
. As well as various functions working with tuples, which are supposed to be expressed syntactically.
Tolk is null-safe, so you can't assign null
to cell
, only to cell?
. And since some stdlib functions return nullable values, types will most likely mismatch.
Tolk has bool
type (FunC had only int
). Comparison operators == != < >
return bool. Logical operators && ||
return bool. In FunC, you have to write if (~ equal)
. In Tolk, bitwise ~
for bool is an error, write just if (!equal)
. You can't assign bool
to int
directly, only via boolVar as int
(but most likely, it's a bad idea). Remember, that true
is -1, not 1.
Tolk has address
type (FunC had only slice
). You can't assign slice
to address
and vice versa without as
operator. The converter tries to guess whether address
should be used instead. For instance slice sender_address = ...
will be converted to var senderAddress: address = ...
.
Deep dive: Tolk vs FunC: in detail.
This converter gives you a working starting point — a Tolk contract that's still written in a "FunC style," but ready to be modernized step by step.
onInternalMessage(inMsgFull: cell, inMsgBody: slice)
with onInternalMessage(in: InMessage)
and use its fields directlyonBouncedMessage(in: InMessageBounced)
— it's called automaticallyStorage
struct, with toCell/fromCell like in examples, use it everywhere instead of manual functionsval msg = lazy MyUnion.fromSlice(in.body)
and match (msg)
createMessage(...)
The key idea: your tests keep running at every stage. That's what makes this approach safe — you can confidently refactor and modernize the codebase without breaking anything.
Deep dive: Auto-packing to/from cells.
Deep dive: Universal createMessage.
Here: Tolk vs FunC benchmarks. This repository contains several contracts migrated from FunC — preserving original logic and passing the same tests.
If you are familiar with how jettons or NFTs are implemented in FunC, you'll feel right at home. The Tolk versions are significantly clearer and more readable. You can also explore the Git history to see how each contract was gradually rewritten, step by step.
FAQs
Migrate from FunC to Tolk with a single npx command
The npm package @ton/convert-func-to-tolk receives a total of 3 weekly downloads. As such, @ton/convert-func-to-tolk popularity was classified as not popular.
We found that @ton/convert-func-to-tolk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 4 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Four npm packages disguised as cryptographic tools steal developer credentials and send them to attacker-controlled Telegram infrastructure.
Security News
Ruby maintainers from Bundler and rbenv teams are building rv to bring Python uv's speed and unified tooling approach to Ruby development.
Security News
Following last week’s supply chain attack, Nx published findings on the GitHub Actions exploit and moved npm publishing to Trusted Publishers.