Skip to main content
Tolk has several types for integers:
  • general int
  • signed int32, int256, etc. — any intN (0 < N ≤ 257)
  • unsigned uint64, uint119, etc. — any uintN (0 < N ≤ 256)
  • coins (representing nanotoncoins, 1 TON = 10^9)
  • (rarely used) varintN and varuintN (N = 16/32)

Syntax: decimal, hex, and binary literals

All the constants below are just int:

intN describes serialization, int does not

To automatically parse binary data, the compiler must correctly load and store integers. When a contract schema is designed, it is described in terms such as “queryID is unsigned 64-bit, counterValue is 32-bit”, and similar. This is expressed directly in Tolk:
As a result, IncMessage can be serialized to a cell and decoded back. A general-purpose type int is “an integer, but no information how to serialize it”. Consider this struct:
Is it valid? Of course, it is! Creating a Point variable is pretty fine. But a call p.toCell() gives an error:
To make it serializable, replace int with a specific integer type. For example:

Overflow happens only at serialization

A natural question is: “What about overflow?”
The answer — no runtime overflow or clamping:
  • arithmetic works as usual – v becomes 256
  • no extra gas cost – no runtime bounds checks
  • overflow only happens at serialization
Analogy: Tolk has mulDivFloor(x,y,z), which uses 513-bit precision internally to prevent rounding errors. Similarly, overflow only occurs at the boundary between the contract and the outside world.

Generic int implicitly cast to and from any intN

  • arithmetic operations on intN degrade to int
  • numeric literals (like 0, 100) are just int
  • direct assignment between intN and intM is disallowed (as a probable error)

Type coins and function ton("0.05")

Similar to int32, Tolk has a dedicated coins type representing nanoton values. The purpose of coins is to have special serialization rules. It’s serialized as “variadic integer”: small values consume a few bits, large values consume more.
  • arithmetic with coins degrades to int, similar to intN (except addition/subtraction)
  • coins can be cast back from int, following the same rules as intN
The ton("0.05") built-in function calculates “nanotoncoins” at compile-time. It only accepts constant values (e.g., ton(some_var) is invalid).

All of them are first-class types

At runtime, all integers are 257-bit. But they are different from the type system’s perspective. For example, they can be nullable, combined within a union, and so on:

No floating-point numbers

Note that only integer types (257-bit) are supported by the virtual machine. There are no floating-point numbers. For example, monetary values are represented as nanotoncoins:

Stack layout and serialization

All numeric types are backed by TVM INT. Serialization happens as follows:
  • int — not serializable, use intN and other types
  • intN — a fixed N-bit signed integer
  • uintN — a fixed N-bit unsigned integer
  • coins — alias to varuint16
  • varintN — variadic N 16/32: 4/5 bits for len + 8*len-bit number
  • varuintN — the same, but unsigned
For details, follow TVM representation and Serialization.