Contracts Update: Solidity on PolkaVM

I’d like to share a brief update about 2 endeavors I’m currently working on.

A new Solidity compiler

As discussed previously here on the forum, we are exploring an alternative contracts runtime, based on PolkaVM. Since we want this new runtime to be highly compatible with Solidity, we started working on a new Solidity compiler.

Priorly, I was mainly working on Hyperledger Solang and we implemented an experimental PolkaVM target.

What is Solang

Hyperledger Solang is a Solidity compiler shipping a custom Solidity frontend, immediate representation and code generator. It emits LLVM IR and currently supports compiling contract to Polkadot pallet-contracts and Solana runtime targets.

You might ask yourself now, why starting something new? (1) Solidity is a moving target, (2) developing a complete Ethereum Solidity compatible compiler is a lot of work and (3) it comes with its own drawbacks (more detailed reasoning in spoiler below).

Tell me more
  1. A canonical Solidity language specification covering all version is yet to be published, the documentation is lacking, many half-baked Solidity features were shipped but never finished over the years. Today, solc as the reference implementation remains the single source of truth.
  2. It seemingly took the nomic foundation over a year and multiple engineers to build an accurate parser covering about 70 different Solidity versions (starting from Solidity 0.4.11). Note that this is not a complete compiler but just about the frontend!
  3. While Solang can produce a lot more optimized code for Wasm targets, this comes at the cost of loosing compatibility with some Solidity language features, most notably inline assembly. “Solang Solidity” contracts use SCALE ABI encoding, which integrates better with Polkadot overall, but is again loosing compatibility. The end result is effectively that we have a new Solidity dialect, which unfortunately isn’t highly compatible with “Ethereum Solidity” source code nor with existing tooling infrastructure. However, since any language targeting LLVM also runs in our contract runtime, we should value higher compatibility over higher performance for Solidity: Expensive workloads can for example be implement in ink!.

Instead, we leverage YUL (which wasn’t yet available when the work on Solang started initially), an intermediate representation (IR) used by solc: Instead of directly compiling Solidity to LLVM IR, we can let solc generate YUL IR, and compile that to LLVM IR. As an IR, YUL is a lot simpler and a much less moving target than Solidity; a lot less work is required to build a compiler that translates YUL IR to LLVM IR.

This is the exact same approach ZKSync is following with their zksolc Solidity compiler. By re-using some of their code base, we were able to hack together a working PoC to run a recompiled flipper contract on pallet contracts quickly.

TL;DR:

  • Using solc to process Solidity source code spares us a lot of work.
  • Recompiling YUL (and EVM byte code as a fallback if needed) dramatically improves Solidity compatibility on PolkaVM.
  • Getting tooling and wallets to support our runtime becomes simpler.

New RISC-V contracts runtime: Comprehensive benchmarks

Ideally, our RISC-V runtime achieves much better execution performance than Wasm and EVM runtimes while also retaining very competitive startup and compilation times.

Initial benchmarks showed that for computationally intensive code, RISC-V might outperform Wasm contracts by more than an order of magnitude - EVM performs even worse here anyways. Which enables exciting new applications so far not possible to realize directly inside a smart contract (for example, verifying STARK proofs without relying on any specific host functions - yes that’d still be slower than using a host functions but we gain a lot of flexibility).

However, traditional contract workloads aren’t computationally heavy; they execute little code per transaction. Here, fast startup and compilation times is king: A contract runtime exhibiting even native code execution performance but at the cost of doing a lot of work on compiling contract code still looses against in-place interpreters in the average case.

We want our contract runtime to exhibit excellent properties in both dimensions! To confidentially achieve this goal, we are setting up a comprehensive benchmark suite, comparing different Solidity compatible contract platforms like pallet-contracts and pallet-evm.

We’ll be measuring wall clock times for the runtime and setup parts. We aim to use a diverse set of contracts:

  • Synthetic ones (e.g. small code that does computational heavy work, large code that does only very little computational work and the like)
  • Classic contract use cases like ERC20 token transfers or ERC721 NFT mints
  • Some of the most popular contracts on ETH mainnet
  • New use cases for RISC-V (e.g. cryptographic computations currently infeasible on EVM or even Wasm).

Wasm based runtimes will be able to run ink! as well as Solidity cases; cross-validation against other Wasm and EVM interpreters or even eBPF is a possibility too.

If you feel like any specific contract or algorithm should be included into this benchmark suite, please let us know here!

Summary

This post covers new developments I’ve been actively working on at the derived Contracts Team at Parity. We hope to deliver a first working version of the compiler as well as a conclusive smart contracts benchmark report later this year. Stay tuned for future updates!

13 Likes

Do keep an eye on Mythical games, maybe you can speed up their code dramatically.

2 Likes

Wow great endeavor! Having this new contracts pallet based on PolkaVM and be highly compatible with Solidity is a totally awesome development!

As the Relay Chain is not suitable for smart contracts, I would like to see system chains (specifically AssetHub) incorporate the contracts pallet rather than depend solely on smart contract-oriented parachain developers. For ink! alone was quite challenging and only attempted seriously in a few cases (Astar, Aleph Zero).

Can we see contracts on AssetHub on Paseo / Kusama / Polkadot … and other system chains? What is the best vs worst case timing of inclusion for this?

I have closed RFC #66 in the expectation of resubmitting it as soon as contracts pallet is sufficiently mature – when could that be?

This specific PolkaVM-specific Solidity dialect should get its own name, like “P-Solidity”, with a versioned specification [of its own RISC-V assembly, cryptographic computations, whether feasible or not].

2 Likes

I’m not sure it even needs an RFC… In priniple, you could even link together contracts written partially in EVM and partially in Rust. It’s purely a matter of dev tooling, but the chain won’t care.

4 Likes

Thanks for the feedback!

This specific PolkaVM-specific Solidity dialect should get its own name, like “P-Solidity”, with a versioned specification [of its own RISC-V assembly, cryptographic computations, whether feasible or not].

By using solc as the compiler front-end we do hope to get away without introducing a Solidity dialect. We’d specify what either works differently (at runtime) or is not supported. The goal is that a vast majority of dApps shouldn’t notice and work fine without code changes.

The largest deviation will be how deployments work. However this only affects the developer side of it and can be worked around with tooling. For users (anyone just doing regular calls), existing tooling, wallets etc. will just work given we also add compatible RPC (which we could).

However, I expect a vast majority of features to just work. The relevant ZKSync doc section should give you a good taste as most of it applies to our case too.

I’m not sure it even needs an RFC… In priniple, you could even link together contracts written partially in EVM and partially in Rust. It’s purely a matter of dev tooling, but the chain won’t care.

Yeah for the runtime and chain, the contract Language is fully opaque. A Solidity contract can call anything as long as the callee respects the Solidity ABI encoding (hypothetical the same would apply for dynamic linking). We want to provide ETH precompiles though.

As the Relay Chain is not suitable for smart contracts, I would like to see system chains (specifically AssetHub) incorporate the contracts pallet

I do agree! I’ve collected and published ideas and thoughts around it here :slight_smile:

What is the best vs worst case timing of inclusion for this?

I think the sooner we push it to Kusama the better, starting with AssetHub first until other system chains are available. We just need to make sure to not introduce any new attack vectors.

I have closed RFC #66 in the expectation of resubmitting it as soon as contracts pallet is sufficiently mature – when could that be?

I don’t think we need to wait any longer as I don’t expect this final runtime to diverge much from contracts as it is today (after all, it is modeled after Ethereums contracts model and already highly compatible). Even if a couple things wind up differently in the end, shipping contracts as it is today paves the way and makes this a more incremental process overall :slightly_smiling_face:

2 Likes

This is an exciting endeavor, and looks like a pretty good match to the project introduced here.
I’m looking forward to porting an Ethereum dapp to a parachain. Please keep us updated!

1 Like