Reserved functions of FunC
The official smart contract language of TON Blockchain is Tolk. FunC is now a legacy language, with its compiler no longer maintained.
FunC pages will be moved down in the sidebar in mid-April 2026. Here is the preview of a possible future placement, right between "Blockchain foundations" and "Contribute" sections:


Learn how to migrate from FunC to Tolk.
FunC, or more specifically, the Fift assembler, reserves several function names with predefined IDs:
recv_internalandmainhaveid = 0recv_externalhasid = -1run_ticktockhasid = -2split_preparehasid = -3split_installhasid = -4
Every program must include a function with id = 0, meaning it must define either recv_internal or main, but not both.
Receive internal
The recv_internal function is invoked when a smart contract receives an inbound internal message.
Any of the following recv_internal declarations can be used:
() recv_internal(int balance, int msg_value, cell in_msg_cell, slice in_msg_body)
() recv_internal(int msg_value, cell in_msg_cell, slice in_msg_body)
() recv_internal(cell in_msg_cell, slice in_msg_body)
() recv_internal(slice in_msg_body)
() recv_internal()There,
balanceis the smart contract balance in nanotons after adding the amountmsg_valuein the inbound message. It is an integer.msg_valueis the amount in nanotons included in the inbound message. It is an integer.in_msg_cellis the inbound message, given as a cell.in_msg_bodyis the inbound message body, equal to the body field inin_msg_cell. The body is given as a cell slice.
Each time a contract receives a message, the TVM initializes and pushes into the stack the following four pieces of data, in this order:
- The balance of the contract.
- The coins included in the inbound message.
- The message itself as a cell.
- The message body as a slice.
This means that the message body slice is the value at the top of the stack, since it was pushed last.
At the moment recv_internal executes, its arguments are assigned values from the stack as follows:
() recv_internal(arg_1, arg_2, ....., arg_n-1, arg_n)
;; | | | |
;; | | | value at the top of the stack
;; | | |
;; | | second value from the top of the stack
;; | |
;; | (n-1)-th value from the top of the stack
;; |
;; n-th value from the top of the stackThis means that if, for example, you use the declaration:
() recv_internal(cell in_msg_cell, slice in_msg_body)in_msg_body will get assigned the value at the top of the stack (which corresponds to the message body slice), and in_msg_cell will receive the second value from the top of the stack (which corresponds to the message as a cell). The rest of values in the stack remain unassigned to variables during the execution of recv_internal, meaning that they will remain unused in the stack and will be dropped once the TVM finishes execution.
The declarations of recv_internal with fewer arguments consume slightly less gas, because each unused value in the stack is automatically dropped from the stack once recv_internal finishes execution, without the need to spend gas by explicitly executing a DROP instruction, which is an alias of s0 POP.
The FunC compiler does not check if the recv_internal arguments will actually match the values in the stack. For example, the following declaration will compile, but leads to errors during contract execution, because variable in_msg_body will not hold a slice, but the contract's balance, which is an integer!
() recv_internal(slice in_msg_body, int msg_value, cell in_msg_cell, int balance)Be careful of accidentally permuting the arguments in recv_internal. Only use the five possible declarations listed previously for recv_internal.
Main
main is an alias for recv_internal.
If the intention of the code is to handle inbound internal messages, it is preferable to use recv_internal over main, since recv_internal states more clearly the intention of the code.
Receive external
The recv_external function handles inbound external messages. It allows declarations similar to those for recv_internal:
() recv_external(int balance, int msg_value, cell in_msg_cell, slice in_msg_body)
() recv_external(int msg_value, cell in_msg_cell, slice in_msg_body)
() recv_external(cell in_msg_cell, slice in_msg_body)
() recv_external(slice in_msg_body)
() recv_external()The only difference is that msg_value is always 0, since external messages cannot carry coins, as they are created outside the blockchain.
The behavior of the stack is identical to the behavior described for recv_internal.
Run ticktock
The run_ticktock triggers at inbound tick and tock messages. It allows the following possible declarations:
() run_ticktock(int balance, int address, int is_tock)
() run_ticktock(int address, int is_tock)
() run_ticktock(int is_tock)
() run_ticktock()There:
balanceis the smart contract balance in nanotons. It is an integer.addressis the address of the current account inside the masterchain. It is an unsigned 256-bit integer.is_tocka flag that indicates if it is a tock message (-1) or a tick message (0).
The behavior of the stack is identical to the behavior described for recv_internal.
Split prepare
The split_prepare triggers for inbound split prepare messages. Even though the split_prepare name is currently reserved, split prepare messages are currently not in use.
Split install
The split_install triggers for inbound split install messages. Even though the split_install name is currently reserved, split install messages are currently unavailable.
Last updated on