FunC standard library
This section covers the stdlib.fc library, which provides standard functions for FunC.
The FunC standard library serves as a wrapper around the most commonly used TVM assembly commands that aren’t built-in. For detailed descriptions of these commands, refer to the TVM documentation. Some explanations in this document adapted from there.
Some functions in the library are commented out, meaning they have already been optimized and integrated as built-in operations. However, their type signatures and behaviors remain unchanged.
Additionally, some less frequently used TVM commands are not yet included in the standard library. These may be added in future updates.
Tuple manipulation primitives
Most function names and types in this section are self-explanatory. For more details on polymorphic functions, refer to the Polymorphism with forall section.
Note: Currently, values of atomic type tuple
cannot be converted into composite tuple types (e.g.,[int, cell]
) and vice versa.
Lisp-style lists
Lists can be represented as nested 2-element tuples. Empty list is conventionally represented as TVM null
value (it can be obtained by calling null()
). For example, the tuple (1, (2, (3, null)))
represents the list [1, 2, 3]
. Elements of a list can be of different types.
Lists in FunC are represented as nested two-element tuples. An empty list is conventionally represented by the TVM null
value, which can be obtained using null()
.
For example, the tuple (1, (2, (3, null)))
corresponds to the list [1, 2, 3]
. Lists in FunC can contain elements of different types.
cons
forall X -> tuple cons(X head, tuple tail) asm "CONS";
Adds an element to the beginning of a lisp-style list.
uncons
forall X -> (X, tuple) uncons(tuple list) asm "UNCONS";
Extracts the head and tail of a lisp-style list.
list_next
forall X -> (tuple, X) list_next(tuple list) asm( -> 1 0) "UNCONS";
Extracts the head and tail of a lisp-style list. It can be used as a (non-)modifying method.
Example
() foo(tuple xs) {
(_, int x) = xs.list_next(); ;; get the first element, `_` means do not use tail list
int y = xs~list_next(); ;; pop the first element
int z = xs~list_next(); ;; pop the second element
}
car
forall X -> X car(tuple list) asm "CAR";
Returns the head of a lisp-style list.
cdr
tuple cdr(tuple list) asm "CDR";
Returns the tail of a lisp-style list.
Other tuple primitives
empty_tuple
tuple empty_tuple() asm "NIL";
Creates an empty tuple (0 elements).
tpush
forall X -> tuple tpush(tuple t, X value) asm "TPUSH";
forall X -> (tuple, ()) ~tpush(tuple t, X value) asm "TPUSH";
Appends a value to the tuple (x1, ..., xn)
, forming (x1, ..., xn, x)
. The resulting tuple must not exceed 255 elements,
or a type check exception is thrown.
single
forall X -> [X] single(X x) asm "SINGLE";
Creates a tuple with a single element—singleton
unsingle
forall X -> X unsingle([X] t) asm "UNSINGLE";
Unpacks a singleton.
pair
forall X, Y -> [X, Y] pair(X x, Y y) asm "PAIR";
Creates a two-element tuple (pair).
unpair
forall X, Y -> (X, Y) unpair([X, Y] t) asm "UNPAIR";
Unpacks a pair into two separate values.
triple
forall X, Y, Z -> [X, Y, Z] triple(X x, Y y, Z z) asm "TRIPLE";
Creates a three-element tuple (triple).
untriple
forall X, Y, Z -> (X, Y, Z) untriple([X, Y, Z] t) asm "UNTRIPLE";
Unpacks a triple into three separate values.
tuple4
forall X, Y, Z, W -> [X, Y, Z, W] tuple4(X x, Y y, Z z, W w) asm "4 TUPLE";
Creates a four-element tuple.
untuple4
forall X, Y, Z, W -> (X, Y, Z, W) untuple4([X, Y, Z, W] t) asm "4 UNTUPLE";
Unpacks a four-element tuple into four separate values.
Tuple element access
first
forall X -> X first(tuple t) asm "FIRST";
Returns the first element of a tuple.
second
forall X -> X second(tuple t) asm "SECOND";
Returns the second element of a tuple.
third
forall X -> X third(tuple t) asm "THIRD";
Returns the third element of a tuple.
fourth
forall X -> X fourth(tuple t) asm "3 INDEX";
Returns the fourth element of a tuple.
Pair and triple element access
pair_first
forall X, Y -> X pair_first([X, Y] p) asm "FIRST";
Returns the first element of a pair.
pair_second
forall X, Y -> Y pair_second([X, Y] p) asm "SECOND";
Returns the second element of a pair.
triple_first
forall X, Y, Z -> X triple_first([X, Y, Z] p) asm "FIRST";
Returns the first element of a triple.
triple_second
forall X, Y, Z -> Y triple_second([X, Y, Z] p) asm "SECOND";
Returns the second element of a triple.
triple_third
forall X, Y, Z -> Z triple_third([X, Y, Z] p) asm "THIRD";
Returns the third element of a triple.
Domain specific primitives
Extracting info from c7
The c7 special register holds useful data about smart contract execution. The following primitives facilitate easy retrieval of this information:
now
int now() asm "NOW";
Returns the current Unix timestamp as an integer.
my_address
slice my_address() asm "MYADDR";
Retrieves the smart contract’s internal address as a Slice containing MsgAddressInt
. If needed, it can be further processed using functions like parse_std_addr
.
get_balance
[int, cell] get_balance() asm "BALANCE";
Returns the smart contract's balance as a tuple
:
int
: The remaining balance in nanotoncoins.cell
: A dictionary (with 32-bit keys) containing balances of extra currencies.
Since this is retrieved during the compute phase, the balance reflects the incoming message value
, with storage_fee
and import_fee
already subtracted.
Raw primitives such as send_raw_message
do not update this field.
cur_lt
int cur_lt() asm "LTIME";
Returns the logical time of the current transaction.
block_lt
int block_lt() asm "BLOCKLT";
Returns the logical time at the beginning of the current block.
config_param
cell config_param(int x) asm "CONFIGOPTPARAM";
Returns the value of the global configuration parameter with integer index i
as cell
or null
value.
my_code
cell my_code() asm "MYCODE";
Retrieves the smart contract's code from c7
.
This function is not included in the standard library, but is often sought by developers.
You need to manually add initialization it to your contract system, with the asm
word specified as shown in the snippet above.
Hashes
cell_hash
int cell_hash(cell c) asm "HASHCU";
Calculates the representation hash of the given cell c
and returns it as a 256-bit unsigned integer x
.
This function is handy for signing and verifying signatures of arbitrary entities structured as a tree of cells.
slice_hash
int slice_hash(slice s) asm "HASHSU";
Computes the hash of the given slice s
and returns it as a 256-bit unsigned integer x
.
The result is equivalent to creating a standard cell containing only the data and references
from s
and then computing its hash using cell_hash
.
string_hash
int string_hash(slice s) asm "SHA256U";
Calculates the SHA-256 hash of the data bits in the given slice s
.
A cell underflow exception is thrown if the bit length of s
is not a multiple of eight.
The hash is returned as a 256-bit unsigned integer x
.
Signature checks
check_signature
int check_signature(int hash, slice signature, int public_key) asm "CHKSIGNU";
Checks whether the given signature
is a valid Ed25519 signature of the provided
hash
using the specified public key
. The hash
and public key
are both 256-bit unsigned integers. The signature
must be at least 512 bits long, and only the first 512 bits are used.
If the signature is valid, the function returns -1
; otherwise, it returns 0
.
Remember that CHKSIGNU
converts the hash into a 256-bit slice and then calls CHKSIGNS
.
This means that if the hash
was initially generated from some data,
that data gets hashed twice—the first time when creating the hash and the second time within CHKSIGNS
.
check_data_signature
int check_data_signature(slice data, slice signature, int public_key) asm "CHKSIGNS";
Verifies whether the given signature
is a valid Ed25519 signature for the data contained in the slice data
,
using the specified public key
, just like check_signature
.
A cell underflow exception is thrown if the data's bit length is not a multiple of eight.
The verification follows the standard Ed25519 process,
where SHA-256 is used to derive a 256-bit number from data
, which is then signed.
Computation of BoC size
The following functions help calculate storage fees for user-provided data.
compute_data_size?
(int, int, int, int) compute_data_size?(cell c, int max_cells) asm "CDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT";
Returns (x, y, z, -1)
or (null, null, null, 0)
. It recursively calculates the number of unique cells x
, data bits y
, and cell references z
in the directed acyclic graph (DAG) at cell c
. This provides the total storage used by the DAG while recognizing identical cells.
The computation uses a depth-first traversal with a hash table to track visited cells, preventing redundant visits.
If the total amount of visited cells x
exceeds max_cells
, the process stops before visiting the (max_cells + 1)
-th cell, and the function returns 0
to indicate failure. If c
is null
, the function returns x = y = z = 0
.
slice_compute_data_size?
(int, int, int, int) slice_compute_data_size?(slice s, int max_cells) asm "SDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT";
It works similarly to compute_data_size?
but takes a slice s
instead of a cell
. The result x
does not include the cell that contains the slice s
, but y
and z
account for the data bits and cell references inside s
.
compute_data_size
(int, int, int) compute_data_size(cell c, int max_cells) impure asm "CDATASIZE";
A strict version of compute_data_size?
that throws a cell overflow exception (8) if the computation fails.
slice_compute_data_size
(int, int, int) slice_compute_data_size(slice s, int max_cells) impure asm "SDATASIZE";
A strict version of slice_compute_data_size?
that throws a cell overflow exception (8) if the computation fails.
Persistent storage save and load
get_data
cell get_data() asm "c4 PUSH";
Returns the persistent contract storage cell, which can be later parsed or modified using slice and builder functions.
set_data
() set_data(cell c) impure asm "c4 POP";
Sets cell c
as persistent contract data. You can update the persistent contract storage with this primitive.
Continuation primitives
get_c3
cont get_c3() impure asm "c3 PUSH";
The c3
register typically holds a continuation set up by the contract code.
It is used for function calls.
The primitive returns the current value of c3
.
set_c3
() set_c3(cont c) impure asm "c3 POP";
Updates the c3
value to modify the contract’s execution code at runtime. The current code and function call stack remain unchanged, but future function calls use the updated code.
bless
cont bless(slice s) impure asm "BLESS";
Converts a slice s
into a basic continuation c
, where c.code = s
, an empty stack and a savelist.
Gas related primitives
accept_message
() accept_message() impure asm "ACCEPT";
This function sets the current gas limit gl
to its maximum possible value gm
and resets the gas credit gc
to zero.
At the same time, it deducts the previous gas credit gc
from the remaining gas reserve gr
.
Simply put, the smart contract agrees to purchase gas to complete the transaction.
This function is required when processing external messages that do not carry any value and do not provide gas.
For more details, follow the Accept message effects section.
set_gas_limit
() set_gas_limit(int limit) impure asm "SETGASLIMIT";
This function sets the gas limit gl
to the smaller of two values: the provided limit
or the maximum allowed gas gm
.
It also resets the gas credit gc
to zero. If the contract already uses more gas than this new limit gl
, including the current instruction, an out-of-gas exception is triggered before the new limit is applied.
Remember that if the limit
is 2^63 − 1
or higher, calling set_gas_limit
works the same as calling accept_message
.
For more details, follow the Accept message effects section.
commit
() commit() impure asm "COMMIT";
Saves the current state of persistent storage c4
and action registers c5
, ensuring execution succeeds with these stored values,
even if an exception occurs later.
buy_gas
() buy_gas(int gram) impure asm "BUYGAS";
The BUYGAS
opcode is currently not implemented.
This function calculates how much gas can be purchased for the gram
nanotoncoins and updates the gas limit gl
accordingly,
similar to set_gas_limit
.