Embarking on the FunC Adventure
Introduction to FunC Development: A Step-by-Step Guide
To help you navigate this journey effectively, I’ll provide you with a roadmap and practical tips, guiding you through the lessons so you can gain a solid understanding of FunC and potentially create your own applications on the TON blockchain.
Embarking on the TON Ecosystem
As we set our sights on the TON ecosystem, our journey begins…
Smart Contracts on the TON Blockchain
The TON network is powered by TVMs (TON Virtual Machines), where smart contracts—programs stored on the blockchain—execute when specific conditions are met. The high-level language FunC is used to develop these smart contracts on the TON blockchain. FunC code is compiled into Fift assembler code, which in turn generates the bytecode that runs on the TVM.
Any developer can create a smart contract and deploy it to the TON network by paying a network fee. Users can then interact with the smart contract by executing its code, again for a fee paid to the network.
Through smart contracts, developers have the ability to create and deploy complex user applications and services.
It’s also worth noting that once published, smart contracts are assigned a unique address on the network.
As we venture into the TON ecosystem, the first thing we encounter is a “forest” of cells. To make sense of this and move forward, we need to understand data types, exceptions, and functions in FunC.
Understanding Data Types, Functions, and Exceptions in TON
In the TON Blockchain, all persistent data is stored within trees of cells. Each cell can contain up to 1023 bits of arbitrary data and can reference up to 4 other cells. These cells serve as the memory for the stack-based TON Virtual Machine (TVM).
A FunC program is essentially a collection of function declarations/definitions and global variable declarations. Each function declaration or definition follows a common pattern:
[<forall declarator>] <return_type> <function_name>(<comma_separated_function_args>) <specifiers>
Here, [ … ] denotes an optional component.
Special Functions in TON Smart Contracts
Smart contracts on the TON network have two key reserved methods that can be accessed:
- recv_internal(): This method is triggered when an action occurs within the TON network itself, such as when another contract interacts with yours.
- recv_external(): This method is executed when a request is made to the contract from an external source, outside of the TON network.
Handling Exceptions in Smart Contracts
An essential aspect of any smart contract is the ability to handle errors through exceptions. Exceptions can be triggered by using conditional primitives such as throw_if and throw_unless, or by the unconditional throw primitive.
To help you grasp these concepts, I’ve prepared a lesson where you’ll write your first smart contract and apply the information you’ve just learned in practice. [Link to the first lesson].
Congratulations! You’ve navigated through the “forest” of cells. However, to ensure others can follow the path you’ve created, we’ll need to test it.
Testing a Smart Contract
As you ponder the importance of testing, a wise figure approaches and informs you that there are currently two types of tests in TON.
V1 Tests
In the older V1 testing framework, each test requires the creation of two functions:
- Data Function (or more accurately, a state function)
- Test Function
For each test, you first establish the data or state using the data function. Then, within the test function, you outline the test logic, triggering exceptions whenever the logic is violated.
Although this is the older testing method, the sage encourages you to explore it to gain a deeper understanding of how testing works in TON. You can learn how to test the smart contract you created in the first lesson using V1 tests by following the instructions in the second lesson.
V2 Tests
As the sage departs, he gestures toward the horizon and mentions that TON now has a new testing framework that you should explore if you want to create tests more efficiently.
V2 Testing Framework
In the updated V2 tests, testing is streamlined through two key functions that allow you to invoke smart contract methods:
- invoke_method: Assumes that no exception will be thrown.
- invoke_method_expect_fail: Assumes that an exception will be thrown.
These functions are called within your test functions, which can return multiple values—all of which will be displayed in the test report when the tests are executed.
To distinguish test functions from helper functions, ensure that the name of each test function begins with __test. This naming convention helps identify which functions are tests and which serve as utilities.
Understanding the Stack and Registers in TON
As you delve deeper into the TON ecosystem, it becomes clear that mastering the concepts of registers and the stack is essential. Without this understanding, creating anything meaningful within TON is nearly impossible, making this knowledge a crucial part of your journey through the network.
Stack and Registers in TON
The TON Virtual Machine (TVM) operates as a stack machine, where the last element added to the stack is the first to be removed—following the Last In, First Out (LIFO) principle. As a result, when working with smart contracts, you often need to access data sequentially, even if some of it is not immediately relevant. For example, in the function below, we aim to retrieve the address, but must first read the flags, even though they are not used:
slice parse_sender_address (cell in_msg_full) inline {
var cs = in_msg_full.begin_parse();
var flags = cs~load_uint(4);
slice sender_address = cs~load_msg_addr();
return sender_address;
}
Additionally, the TVM’s state is managed by control registers, with c4 being the most commonly used register in TON smart contracts. The c4 register holds the root of the persistent data, essentially representing the contract’s data section, and this value is stored in a Cell.
As your journey through the TON ecosystem continues, you may establish several “smart contract base camps.” But the question remains: how do you effectively organize communication between them?
Sending Messages in TON
TON employs an actor model for communication between smart contracts. Each smart contract can receive a single message, modify its state, and send one or more messages within a given time frame. This model allows both the entire blockchain and individual contracts to scale, accommodating an unlimited number of users and transactions.
In addition, the TON blockchain and its hosted contracts can receive external messages from other blockchains or the broader web. This capability means that you can send a message to a TON smart contract without needing an on-chain account, enabling smart contracts to process and integrate external data for on-chain operations.
Testing Messages
As we venture further into the ecosystem, we encounter enigmatic stones inscribed with ancient runes….
To test smart contracts that interact with messages, we must first generate the necessary addresses. In TON, objects are described by TL-B schemes, so to determine what a test address should look like, we need to examine the block scheme.
It becomes apparent that the runes on these stones hold valuable information that will guide us on our journey.
To gain a deeper understanding of TL-B, I recommend studying the following resource: TL Language.
The Road Ahead
In this article, we embarked on our journey through the TON ecosystem, starting with the FunC programming language. I hope these initial steps have ignited your enthusiasm to continue exploring and learning more.