Rust is a programming language that is well known to Web3 developers.While it has a reputation for being a somewhat complicated and difficult to learn language, it’s still heavily used in the world of Web3 and for a good reason.
At our recent Web3 Happy Hour meetup, LimeChain’ senior developer Maksim Dimitrov held an insightful presentation about Rust, highlighting some of the key features of the language. In this article we’re sharing some of those key takeaways. So join us in this high-level overview of Rust, as we try to understand what makes it such a powerful tool for Web3 development.
Rust – unique characteristics
There’s a reason why Rust has been voted as the most loved programming language in the world for the last seven years. It does certain things in its own way, pioneering novel concepts that help it stand out in a crowded field. And while this makes it less accessible for newcomers, its distinct approach brings some unique advantages. Let’s take a look at some of Rust’s defining characteristics.
Perhaps the most distinctive thing about Rust is its unique approach to memory management. Unlike many high-level languages, Rust does not use a garbage collector to clear up memory. Instead it leverages novel concepts like variables immutability and ‘ownership and borrowing’ to ensure memory safety. Here’s the gist of it.
Every value in Rust is assigned to a single variable known as its owner. When that variable falls out of scope, Rust automatically frees up the memory allocated to it. However, if that were all there was to it, that would be a very limited and inefficient way of doing things. This is because functions often have to reference values declared locally in other parts of the code.
Rust solves this problem by allowing functions to temporarily borrow a value without assuming ownership of it. When a value is borrowed, the resources bound to it are not deallocated after falling out of scope. This concept is taken even further with ‘lifetimes’, which can be described as an advanced form of borrowing.
There are strict rules for borrowing and adherence to those rules is tracked by the ‘borrow checker’. Most importantly, every part of the ‘ownership and borrowing’ process happens at compile time, which is how Rust remains memory-safe without a garbage collector or other memory-safety systems. If the rules aren’t followed, the program cannot be compiled.
In addition to memory-safety, Rust also targets speed and high performance. We already hinted at one of the ways it achieves that – because checks happen at compile time, there is little, if any, runtime overhead.
Variables immutability also plays a significant role. In Rust, every variable is immutable by default and is automatically stored in stack memory, which is very fast.
In addition, Rust code compiles to native machine code and because of that is able to match the performance of comparable code written in C and C++.
Another advantage of Rust is that it works very well with other languages. For example, Rust code can be easily invoked in programs written in other languages. At the same time, invoking Rust in other languages is just as easy. This property of Rust comes in very handy when it comes to Web3 development.
All that sounds well and good, but as we know, there is no such thing as a perfect programming language and Rust is no exception. Its unique traits give the language clear advantages in certain areas, but those come with tradeoffs. Here are some of the challenges you’ll face as a Rust developer.
Steep learning curve
A logical consequence of having your own way of doing things is that you do not conform to conventions. This is why Rust is often described as difficult to learn. Concepts such as immutability and ownership and borrowing can be quite intimidating to the uninitiated. It is quite common for rookie developers to spend their first few months learning Rust wrestling with the borrow checker.
Contributing to the steep learning curve is also the fact that Rust syntax is very complicated and requires some getting used to.
Long compile time
Because so much in a Rust program happens at compile time, you can have very little runtime overhead. However, this means that the compile time is much longer. So you can often spend a considerable amount of time waiting before you can have a functional build. Goes with the territory.
Poor third-party support
Rust supports libraries, which are called crates and are loaded through the ‘Cargo’ module. The problem is that when it comes to third-party crates, the situation is far from exemplary. Many third-party crates are half-finished, abandoned or lack proper documentation.
Rust in Web3
While Rust may be lacking in some areas, its unique features and capabilities more than make up for its deficiencies. For that reason, the language is a powerful tool that can be used for building a wide range of applications, from web browsers through cybersecurity services to entire operating systems. Of course, to us, of particular interest is how the language is used in the Web3 world. We can pinpoint three main areas where Rust has so far had a significant impact.
Some of the most prominent Web3 protocols are written in Rust. The go-to example is the multi-chain protocol Polkadot and its development framework Substrate. The team behind Polkadot, Parity Technologies, has praised Rust for its memory safety and performance.
Solana is another major Web3 protocol written in Rust. The language was chosen by the Solana team for its high performance, support for parallelized transaction processing, easy debugging and scalability.
Another oft-cited plus of Rust is its support for compiling to Web Assembly (WASM). This comes in handy in blockchain development, but it is also a major advantage when it comes to writing smart contracts. This is because a number of popular smart contract execution layers including 3em and Ethereum Wasm can execute Web Assembly.
Other characteristics that make Rust great for writing smart contracts include that it is memory-safe, features compact data structures and produces small binaries.
Many of the popular tools used for Web3 development today are also written in Rust. Notable examples include: Ethers.rs – a Rust implementation of the popular JS library Ethers.js; Foundry – a modular toolkit for Ethereum dApp development; Solang, which is a Solidity compiler for Solana and Substrate; and the open-source Ethereum consensus client Lighthouse.
The aforementioned examples clearly demonstrate that the Web3 community is embracing Rust and recognising its immense capabilities. The growing demand for skilled Rust developers also points to the same conclusion. We have little doubt that these trends will continue to grow and that Rust will become an even bigger part of the expanding Web3 space.