In TON, smart contracts are executed inside TVM (TON Virtual Machine). TVM expects instructions in a specific binary format, available here:
https://ton.org/docs/learn/tvm-instructions/instructions
These binary instructions are like assembly code, and writing them by hand is very hard. At the beginning Fift was created as a scripting language to make it easier to write smart contract codes. It has a special syntax and working with it is easier than TVM instructions, but it's still very low level and hard to use, but it's doable.
After a while, FunC was developed which is like the C language. A lot easier than assembly and very powerful, yet still considered a low level language.
There are higher level languages being developed like Tact (https://tact-lang.org/) or Rift (https://rift.skyring.io/), which will ultimately produce those TVM instructions.
You can interact with smart contracts by sending them messages encoded in the binary format expected by those smart contracts.
recv_internal
is the main entry function in FunC, which expects to receive internal messages generated inside the blockchain. It expects four arguments, as TVM puts those 4 args on the stack. In FunC, you may omit any of the previous args if you are not using them.
For the short answer, yes. Smart contracts are written in FunC, then compiled into Fift, and deployed on the blockchain. They can later be interacted with using either Fift or a wrapper SDK.
On the other hand, there are always 4 arguments on stack when recv_internal
is called.
By declaring recv_internal with less than 4 arguments you force FunC to ignore most deep variables (they still will be there, but your code will be unaware for the whole TVM execution).
here are the example for recv_internal
in the latest tutorial built by community:
() recv_internal(int msg_value, cell in_msg, slice in_msg_body) impure { ;; well known function signature
if (in_msg_body.slice_empty?()) { ;; check if incoming message is empty (with no body)
return (); ;; return successfully and accept an empty message
}
int op = in_msg_body~load_uint(32); ;; parse the operation type encoded in the beginning of msg body
var (counter) = load_data(); ;; call our read utility function to load values from storage
if (op == 1) { ;; handle op #1 = increment
save_data(counter + 1); ;; call our write utility function to persist values to storage
}
}
You can catch more in here: https://ton.org/docs/learn/tvm-instructions/tvm-overview#initialization-of-tvm
For the deeper understanding, you can check Ch4.4 in Whitepaper
https://ton.org/tblkch.pdf