Friday, May 5, 2023

Release: sc - 0.41.0, vm - 0.3.0

Fixed compatibility with rustc v1.71.0

The new Rust nightly compiler got rid of some feature flags, and changed allocator panic handlers. Our contracts were no longer compiling under the new version. This is now fixed.

Please note that the incompatibility goes both ways: you need to revert to an older compiler version to compile contracts pre-v.0.41.

The allocator system

MultiversX smart contracts are compiled to WebAssembly, which does not come with memory allocation out of the box. In general WebAssembly programs need special memory allocation functionality to work with the heap.

Using traditional memory allocation is highly discouraged on MultiversX. There are several reasons:

  • We have “managed types”, which are handled by the VM, and which offer a cheaper and more reliable alternative.
  • “Memory grow” operations can be expensive and unreliable. For the stability of the blockchain we have chosen to limit them drastically.
  • Memory allocators end up in smart contract code, bloating it with something that is not related in any way to its specifications. This contradicts out design philosophy.

Even so, it is unreasonable to forbid the use of allocators altogether, whether to use them or not ultimately needs to be the developers' choice. Before this release, the only allocator solution offered by us was wee_alloc. Unfortunately, it has not been maintained for a few years and has some known vulnerabilities. This was also causing Github’s Dependabot to produce critical warnings, not only to our framework, but to all contract projects, despite most of them not really using it.

First of all, we made the allocator configurable from multicontract.toml, currently the main source of contract build specifications. Developers currently have 4 allocators to choose from.

Then, we added the following allocators to our framework:

  1. FailAllocator (the default). It simply crashes whenever any memory allocation of deallocation is attempted. For the first time we have a tool that completely prevents accidental memory allocation. We already had an "alloc" feature in Cargo.toml, but it is only operating high-level and can easily (and sometimes accidentally) be circumvented.
  2. StaticAllocator64k. Pre-allocates a static 2-page buffer, where all memory is allocated. It can never call memory.grow . It never deallocates and crashes when the buffer is full. It can be suitable for small contracts with limited data being processed, who want to avoid the pitfalls of a memory.grow .
  3. LeakingAllocator . It uses memory.grow to get hold of memory pages. It also never deallocates. This is because contracts do not generally fill up so much memory and all memory is erased at the end of execution anyway. Suitable for contracts with a little more data.
  4. wee_alloc is still supported. It is, however, not included in the framework. Contracts need to import it explicitly. See the crypto-bubbles-legacy contract for an example. Note that this is considered legacy functionality.

Lastly, the “panic with message” feature was using a heap-allocated structure to format error messages. This was switched to a ManagedBuffer, making it independent from allocators. “Panic with message” is a feature very useful for debugging. It displays messages form panics in a contract, at the cost of ~1.5kB of additional contract size. It is disabled by default, we advise against using it in production.

We must reiterate: while these allocators are functional, they should be avoided by all contracts. Only consider this functionality when all else fails, in extremely niche situations, or for dealing very old code.

Fixed BigUint bitwise operations in the debugger

Bitwise operations were not usable in the debugger, due to a bug. This went unnoticed for a very long time because it seems that nobody had ever used this functionality before.

Packed smart contracts (the mxsc file)

A common problem when working with large systems and test contracts is that the contract metadata and ABI often get lost. The contract binary alone is enough to run it, but it gives no useful information about the contract’s interface, age, source or version.

To prevent this we have designed a “packed” contract file, that contains both the metadata and the binary. It gets created automatically when building. Support for this format with come to all products dealing with smart contract code, starting with scenario tests.

Refactor: reorganized the meta crate

The meta crate has grown quite a lot. It was in dire need of some systematization.

Deprecated some legacy methods in the API wrappers

We’ve discovered there were developers in the community still relying on some old legacy crypto functionality. We deprecated them to encourage people to move away from them. (Commit: deprecated legacy methods from API wrappers )

  • get_owner_address_legacy;
  • sha256_legacy_alloc;
  • ripemd160_legacy;
  • verify_bls_legacy;
  • etc.

Release Github Link:

As always, feel free to send us feedback or open a topic in our Github Discussions tab and share your thoughts so that the entire MultiversX community can hear you. If you have a great idea, share it with us and let's make it happen by implementing and integrating it in our ecosystem.

Stay Hungry! Stay Foolish!

Do you need more information?

Explore projects, tokens, and integrations built on MultiversX