Data model
- TVM has no random-access memory. Instead it uses a stack of values as a scratchpad.
- There are no memory addresses. Most instructions either store their parameters directly in the code, or take them from the top of the stack.
- All values are immutable. Most of the data is stored as immutable tree of cells.
- Reading and writing of cells is done with slices and builders.
- There are no function addresses or function pointers. Code is executed from bitcode inside continuations.
TVM state
On incoming messages or get method call, a new instance of TVM is started, with a new state. Derivation of the initial state from the message is described in its own article. The total state of TVM consists of the following components:- Stack. A regular stack data structure. The vast majority of instructions
pop()operands from the top andpush()results back. - Control registers. A small fixed set of special registers, denoted as
c0,c1, …,c5, andc7(c6does not exist). - Gas counter. Tracks remaining computation budget. Each instruction decrements gas. When counter hits zero/negative value, an exception is raised, and the run aborts.
- Current continuation (
cc). A special register that stores a list of the next instructions to execute. Similar to the instruction pointer in traditional architectures. - Current codepage (
cp). Determines how to decode the next instruction incc. Different codepages may implement different instruction sets, allowing for adding new features to TVM without affecting old smart contracts. Currently, only codepage0(cp0) is implemented. Smart contract runsSETCP0instruction to explicitly use codepage0.
TVM data types
Values on the stack and inside of registers are of one of the following seven types:| Type | Description |
|---|---|
| Integer | 257-bit signed integer. Has the special NaN value representing arithmetic faults. |
| Cell | Node of a tree with bit string on it (<= 1023 bits), and up to 4 arrows (refs). |
| Slice | Read cursor over a Cell. |
| Builder | Write cursor to construct a new Cell. |
| Tuple | List of 0..255 elements of any of seven types. Types of elements can be distinct. |
| Continuation | Executable Slice with TVM bitcode. Continuations are callable like functions. |
| Null | Empty value. |
Example of a smart contract: counter
Here is a sample contract, written in Fift. It implements the following logic:- If an event is not an internal message, stop execution.
- Read 32-bit number (
msg_counter) from internal message’s body. - Check that it is equal to the 32-bit number stored in
c4(persistent account storage). - Increment it.
- Save it back to
c4.
s0(top of the stack), function selector, is0. For other events, e.g., external messages or get method calls, selector will be non-zero.s1, message body. The example contract expects exactly 32 bits here.- Three more values
s2,s3,s4are pushed by TVM onto a stack. They won’t be used in the example. After execution finishes, they’ll still be on the stack, and will be silently ignored.
Current stack comments, we represent stack at that moment of execution, keeping its top to the right (e.g., s2 s1 s0, where s0 is the top of the stack).
Fift