Improving Smart Contract Development on Everscale: Overview of Year-Long Updates of the TVM Solidity Compiler

Improving Smart Contract Development on Everscale: Overview of Year-Long Updates of the TVM Solidity Compiler

One of the crucial tools for blockchain developers is the compiler, which acts as a bridge between the human-readable code that developers write and the machine-readable instructions executed by the blockchain's virtual machine. Everscale has TVM Solidity Compiler to fulfill that role. In this report, we will observe the most important changes to the Compiler, made by developers in the course of the last year.

What is the TVM Solidity Compiler?

The translation from a high-level programming language in a low-level code (bytecode) is vital for blockchain development, because it is required for the processing of human-made code of smart contracts by blockchain virtual machines that only understand bytecode. 

TVM Solidity Compiler is a modified version of the standard Solidity compiler, tailored for Threaded Virtual Machine (TVM) used in Everscale and other blockchains. In Everscale, smart contracts are written in TVM Solidity, a customized version of Ethereum’s Solidity language, and are compiled into TVM bytecode. This allows to create smart contracts using a familiar language but execute them on the TVM, benefitting from Everscale's protocol design, which provides better scalability and performance compared to Ethereum.

Everscale’s core development tools and technologies need constant maintenance and improvement to provide better experience for developers, particularly in everything related to smart contracts. In the last year, Everscale engineers have made several major releases, striving to make the TVM Solidity Compiler even better. Below is the overview of main changes.

Data Unpacking and Validation of Smart Contracts

Everscale’s virtual machine, TVM, uses various data structures, with the cell, witten in code as TvmCell, being the basic one. It stores up to 1023 bits of data, and up to 4 references to other cells. There is also another, compact data structure called slice, written in code as TvmSlice. It allows you to read the cell's data in a structured and efficient manner. Since slices are read-only, they are primarily used for deserializing or unpacking complex data structures stored across one or more cells.

In one of the releases, engineers added several functions for handling slices in TVM smart contracts, specifically focusing on unpacking and validating serialized data stored in cells. Specifically, these functions check whether a slice is empty, starts with a certain pattern, or begins with a specific bit, improving the process of working with complex data structures in a highly optimized, blockchain-specific environment.

Overall, new features ensure that smart contracts in Everscale can effectively manage and verify the integrity of data retrieved from cells, which is critical for the correct execution of decentralized applications on Everscale and other TVM-compatible blockchains.

Optimized Modular Arithmetic for Smart Contract Calculations

One more change introduced a function math.mulmod(). It performs an operation (a * b) / c, where a and b are multiplied together, and then the result is divided by c. Instead of returning both the quotient and remainder, this function returns only the remainder. This is common for modular arithmetic, cryptography, and random number generation. Thanks to the new function, developers can avoid unnecessary computations and memory usage related to calculating the quotient.

Enhanced Support for Advanced Cryptographic Curve Operations

As a result of one of the changes, the Compiler started supporting operations on a pairing-friendly BLS12-381 curve. This curve is used in cryptography, particularly for zero-knowledge proofs, digital signatures, and multi-party computation. Thus, this update has become an important step towards the support of ZK proofs in Everscale, essential for implementing secure and scalable cryptographic algorithms.

Error Handling with Quiet Arithmetic

One more update implemented the so-called quiet arithmetic for qintN and quintN data types, which allowed arithmetic operations to handle integer overflows and certain invalid operations more efficiently by returning a null value (NaN) instead of throwing exceptions.

It improved Compiler in several ways:

  • Quiet arithmetic ensures that smart contracts in Everscale don't abruptly fail due to integer overflows or invalid operations. Instead of terminating execution, they continue execution and return NaN, which the contract logic can handle appropriately.
  • By using null values as a signal for invalid operations, developers can add checks or fallback mechanisms to ensure handling of errors, reducing the chances of runtime exceptions.
  • Quiet arithmetic enabled safer and more flexible numerical operations, especially when dealing with variable-length integers or in scenarios requiring higher tolerance for computational uncertainties.

Efficient Dynamic String Construction

The introduction of StringBuilder has provided the TVM Solidity Compiler with a more gas-efficient way to build and manipulate strings in contracts.

In Solidity, string concatenation can be gas-intensive because strings are immutable. The usage of StringBuilder enabled building strings without constantly reallocating memory, which significantly reduces gas costs.

On the other hand, this feature simplifies the work with dynamic strings, making it easier to handle string formatting, concatenation, and construction in smart contracts, particularly in scenarios where you need to manipulate strings efficiently, such as in logging, messaging, or token data formatting.

Greater Precision and Range for Integer Operations

Previously, the integer type in TVM Solidity was a 256-bit integer by default. It has been transferred to a 257-bit one, changing the alias for int from int256 to int257. This update improved the TVM Solidity Compiler by providing better precision and range in numerical operations. Functions that deal with loading and storing integers have been also refined to accommodate the new standard.

Improved Retrieval of Last Element in Optimized Data Containers

A support for the .last() function has become an important enhancement to the TVM Solidity Compiler: it enabled retrieval of the last element from a vector(T), a template container akin to a dynamic-sized array (with some difference) that stores elements of the same type (T).

This container is optimized for performance and is limited to 255 elements due to its implementation based on the TVM Tuple type. Unlike regular dynamic arrays, vectors can only exist during the smart contract's execution, and cannot be passed, returned, or stored in state variables.

The new function returns the last value from the vector without removing it. It is important for a  better data retrieval process, making it easier and faster for developers to work with vectors in smart contracts. And the addition of .last() brings more convenience when working with vectors, especially in use cases where the most recent data is frequently required.

Last-In-First-Out (LIFO) Data Management

With the added support for stack(T), Compiler received a versatile last-in-first-out (LIFO) data structure that improves data handling within smart contracts in Everscale. Stack is a simple LIFO structure where the most recently added item is accessed or removed first. With several functions and additional operations within this type, developers became able to effectively manage and manipulate stack-based data during contract execution.

For example, after pushing two integers 100 and 200 onto the stack, the top() function will return 200 without removing it, while pop() will remove 200 and return it, leaving 100 as the top of the stack.

Free Function Calls via Objects

TVM Solidity Compiler has become equipped with free functions, treated as methods of specific object types through the “using A for B” directive. This feature allows developers to reuse free functions across different contracts or object types without having to rewrite them as methods for each type. And attaching free functions to specific types improves the readability and maintainability of contracts, as the code can be more intuitive and object-oriented. Last but not least, it simplifies the syntax of calling functions on objects, making the code cleaner.

Implementation of Standard Unary Operators

Compiler now supports unary operators (++, --, -, delete, ~) for varint and varuint, integer types with specific serialization and deserialization schemes according to TLB (Typed Lambda-Based) formats.

By supporting unary operators, the update made varint and varuint types behave more like standard integer types in Solidity. This has allowed developers of contracts in Everscale to perform common operations like incrementing, decrementing, and negating these types without the need for custom logic. 

Because these types are designed to be space-efficient, it ensured more optimized storage costs for smart contracts.

Safe and Flexible Integer Type Casting

The new function .cast() improved the TVM Solidity Compiler by allowing for safer and more flexible integer type conversions without the risk of exceptions. This change differentiates the cast() method from standard type conversion, offering a more predictable and resilient way to handle integer type casting in smart contracts.

This update introduces support for the nostorage keyword in the TVM Solidity Compiler, which allows developers to declare state variables that are not stored in the contract's persistent storage. Instead, these variables are reset to their default values at the start of each transaction.

Temporary State Variables for Enhanced Transaction Efficiency

TVM Solidity Compiler got updated with the nostorage keyword, allowing engineers to define state variables that are reset to their default values at the beginning of each transaction. 

Using nostorage variables avoids high gas costs associated with storing and retrieving data from persistent blockchain storage. It is also useful for variables that are limited to a transaction, such as counters, flags, or temporary values used within a single transaction.

Conclusion

As technical superiority is one of Everscale's main strengths, its developer community has been tirelessly working to improve the blockchain protocol along with its vital components, and TVM Solidity Compiler is no exception. Even though this work may not be seen to ordinary users at a first glance, better technical infrastructure inevitably translates into more stable, potent and faster dapps, enriching the ecosystem.

Read More