KrypC builds award-winning taXchain for EU tax forms new case study >

Skip to main content
Hyperledger Foundation
search
Menu
  • Learn
    • Case Studies
    • White Papers
    • Training & Certification
    • Training Partners
    • Webinars
    • Research
    • Blockchain Showcase
    • Wiki
  • Use
    • Distributed Ledgers
    • Domain-Specific
    • Libraries
    • Tools
    • Tutorials
    • Hyperledger Certified Service Providers
    • Vendor Directory
  • Participate
    • Collaboration Tools
    • Contribute to Coding
    • Academic Collaboration
    • Find a Meetup
    • Regional Communities
    • Speakers Bureau
    • Join a Community Group
    • Labs
  • Events
  • News
    • Blog
    • Announcements
    • Newsletter
  • About
    • Join Hyperledger
    • Members
    • Leadership
    • Charter
    • Job Board
    • Contact Us
  • Join
  • English
    • 简体中文
    • Português
    • Français
    • Malayalam
    • 日本語
    • Español
  • search
Close Search
Tag

substrate

Jan 25
Love0

Hyperledger Mentorship Spotlight: Solang Solidity Compiler optimizations and error handling

By Salaheldin Soliman Blog, Hyperledger Mentorship Program, Hyperledger Solang

What did you work on?

Project name: Solang Solidity Compiler optimizations and error handling

Introduction: What is Hyperledger Solang?

Hyperledger Solang is a Solidity compiler for Solana and Substrate written in Rust that utilizes LLVM as the backend. It can be considered the first solid initiative towards making Solidity available for non-EVM chains, while maintaining compatibility with Ethereum’s Solidity compiler: Solc.

Chapter 1: Applying for the Hyperledger mentorship

I found out through a friend that Hyperledger Foundation hosts mentorships for open-source projects related to blockchain infrastructure, which has been my main interest since it covers a whole lot of different Computer Science topics (Distributed systems, cryptography, networking, etc.). As I scrolled through the presented projects, I found a Hyperledger Solang mentorship project addressing three issues:

  1. Make multiplication overflow detection during runtime work above a certain bit-width.
  2. Improve the efficiency (gas cost or compute units) of array bounds checks.
  3. Improve Solang’s parser resilience. 

The first issue intrigued me personally. I was working on a De-fi app, using Remix Solc compiler version 0.7.6 that didn’t have runtime overflow checking. The lack thereof was causing a function to misbehave and consumed me a few valuable days to dig into the issue I was facing. The debugging process was captivating and motivated me to go further in understanding how overflow checking works. Although the problem was fixed on later versions of Solc, I saw in the mentorship an opportunity to improve my knowledge about the topic.

I contacted Sean Young and Lucas Steuernagel, the mentors, and discussed some questions I had about the compiler. They were really helpful along the way.

Chapter 2: Getting warmed up

I was new to contributing to open source, didn’t have any experience with Rust and didn’t use Git quite often 🙂 I spent the first three weeks of my mentorship exploring the source code and deciding on what issue to start working on. Since it would give me a broader idea of the code base, I started with the array bounds optimization, whose goal was to decrease the number of instructions when checking if an array indexation is done within its length limits. More details about my work are available both in Solang’s documentation and in the pull request that addresses this.

In my first pull request, my mentors pointed out issues on how I was solving the task and raised many problems with my Rust programming style. I was clearly struggling with it.  If you are learning Rust, do not take my approach of “learn by doing.” Please go to the Rust Book, read it, and try out the examples there. It will take some time in the beginning, but the examples will teach you the correct programming concepts. This is the only thing I regret not doing at the beginning of the mentorship. 

After that PR was merged, I took some time to read Understanding Ownership and Smart Pointers chapters in the Rust book. That improved my code over the following PRs.

Chapter 3: Multiplication Overflow Detection

The issue at the core of this project was that there was no multiplication overflow detection for integers wider than 64 bits. There are some facts to consider before solving such a problem:

  1. LLVM introduces a set of intrinsics for arithmetic operations. The catch here is that there are no intrinsics for multiplication with overflow for integers wider than 64 bits, so we have to implement our own.
  2. Solidity was designed for the EVM, which supports bit widths up to 256, and bit sizes of multiples of 8 (int128, int136, etc…). On the other hand, Solang compiles for BPF/WASM, and there is no inherent support for types bigger than 64 bits. 

Given these two facts, Solang handled multiplication of larger bit widths by first rounding the value to the nearest 32 bits, then splitting the operands bits into chunks of 32 bits and performing long multiplication.

The multiplication of N bit values will result in at most 2N bit values. So overflow checking was done by assessing whether the uppermost N bits contain any set bits, and raising a runtime error if there are any. Signed multiplication overflow was done first by doing unsigned multiplication, then checking the result for an unexpected change in the sign.

Solang interfaces with LLVM using Inkwell crate. Basically, all of the above was written as Rust code that generates LLVM-IR with the desired logic.

What did you learn or accomplish?

  1. If one is in a mainly learning position, a mentorship, do not pinpoint your vision on completing the task. Instead, take some time and do some background readings in order to tie stuff together. For instance, the aforementioned issue needs some background readings on LLVM, and why Solang used Inkwell instead of LLVM’s C API.
  2. One cannot develop resilient code without random testing.

Chapter 4: Improving Solang’s parser resilience.

Solang utilizes LALRPOP, a parser generator, for its parser. The problem was that once a parser or lexical error was found, the parser would throw an error and stop. If there are multiple errors in a Solidity file, the programmer will only see the first one.

I have utilized LALRPOP’s error recovery documentation to add new grammar rules to account for errors, in such a way that the parser returns multiple errors which makes coding easier.

Some messages for future mentees:

  1. When in daily/weekly meetings with your mentors, do not focus on reporting what you have done. Try to focus more on what they have done, even if you do not understand immediately or have nothing to add to the conversation. This will give you a broader vision of the project and its future plans, in addition to benefiting from their knowledge in the field.
  2. Do not take code comments personally. Remember that the goal is to learn from a more experienced person. They are criticizing your code, not you 🙂 It is also useful to review your own code multiple times before asking for reviews.
  3. You will grow muscles, as in becoming a better software engineer. You will know  how the open source community works and gain a new set of technical and communication skills.

What comes next? 

For the next six months, I will continue working on Hyperledger Solang through a Web3 Foundation grant with a focus on improving the Solang developer experience. Also, my team and I will continue our thesis project (a cross chain wallet), making sure it is production ready by the end of the next Spring semester. For the long term, I will continue working on blockchain infrastructure-related projects.

Dec 13
Love0

Hyperledger Solang Release v0.2.0 and what’s to come

By Cyrill Leutwiler, Lucas Steuernagel, Sean Young Blog, Hyperledger Solang

With great pleasure we announce our most recent Hyperledger Solang Release: v0.2.0 “Berlin.” This release marks an important milestone towards maturing and stabilizing our Substrate compilation target: we are leaving ink! version 3 behind us in favor of introducing compatibility with the recent ink! 4 beta release! 

Status update for our Substrate target

With the “Berlin” release, Hyperledger Solang substantially improved its compatibility with many existing Ethereum Dapps and concepts within the Polkadot and Kusama ecosystem. Porting from Ethereum to a Substrate Parachain is now easier since the compiler supports almost all language constructs as Ethereum Solidity 0.8. This release represents just the beginning of a series of upcoming achievements yet to unlock for the Substrate compilation target.

Getting started with Hyperledger Solang on Substrate

Running your first Solidity contract on Substrate Parachains should be a matter of minutes. In this section we walk you through the few steps, showcasing how to use a classic Solidity example on Substrate. Namely, we are going to deploy an unmodified version of the “Voting” example contract, directly out of the Solidity documentation itself. According to Solidity documentation, the “Voting” contract example showcases a lot of Solidity’s features.

Prerequisites

To follow along, you’ll need to install Solang version “0.2.0” on your system. We offer plenty of quick installation options, including Homebrew as well as pre-built binaries for all common platforms. Please consult our documentation for instructions specific to your platform. Impatient readers may as well just use our docker option, which doesn’t require installing anything, instead.

If you want to test contracts on a local node, you’ll need to run version “0.22.1” of “substrate-contracts-node” on your local machine. Installation instructions can be found here. Again, our impatient readers may use the “paritytech/contracts-ci-linux” Docker image instead as this image contains a compatible substrate node as well (at the time of writing).

Compiling the “Voting” Solidity contract to WASM

We start with saving the source code of the “Voting” example contract into a file called “ballot.sol.”. There is no need to make any modification to the code, unless you want to tinker around a bit on your own. Now we use “solang” to compile the contract as follows:

solang compile --target substrate ballot.sol

The contract should compile without any warnings. If you prefer docker, you can use the following command instead:

docker run --rm -it -v $(pwd):/sources ghcr.io/hyperledger/solang:v0.2.0 compile -o /sources --target substrate /sources/ballot.sol

Now, inside your current working directory, a new file called “Ballot.contract” should appear, containing the web assembly BLOB together with the metadata of the contract.

Testing on a local development node

Before deploying the compiled contract to a testnet, let’s try it out on a local node. If you are in a hurry, you may as well skip this section and proceed directly with a deployment to a testnet. Start a local node on your machine using the following command:

substrate-contracts-node --tmp --ws-external -lerror,runtime::contracts=debug

Alternatively, the equivalent command for our docker users is as follows:

docker run --rm -it -p9944:9944 paritytech/contracts-ci-linux substrate-contracts-node --tmp --ws-external -lerror,runtime::contracts=debug

The odd looking “-lerror,runtime::contracts=debug” CLI option will instruct the node to use the debugging log level for the “contracts” pallet. This might come in handy as it effectively enables using the debug buffer, which allows the contract to communicate with the developer at runtime.

Deploy the contract using the contracts UI

Now head over to the contracts-UI and make sure to select ”Local Node” in the top-left corner. Then click on “Add New Contract” just below, and choose “Upload New Contract Code.” As the Contract Bundle, choose the ”Ballot.contract” file from the previous section. The node we are using comes with some special built-in accounts, which come in very handy for development purposes. The “alice” account is one of them and it is fine to use that for contract instantiation.

Image 1: Choosing the compiled contract bundle in contracts-UI

In the next section, you’ll be presented with some options for contract instantiation. Primarily, you might want to add some more “proposalName”s to our voting Ballot by clicking the big “+” button on the right side, so that we can actually choose between different voting options later. The actual values for the ”proposalName” won’t matter at this point.

Image 2: Configuring constructor arguments for contract instantiation in contracts UI

When you are satisfied with your deployment options, scroll to the bottom of the page to click on “Next” and then “Upload and Instantiate.” Under the hood, this will call the intrinsic to instantiate the contract. As the node we are using is configured to have instant block finality, the operation should succeed immediately. You’ll find your freshly deployed contract on the left side and it will look like this:

Image 3: The solidity contract deployed to a local node

Interacting with the contract

Now we can start playing with the contract by calling some of its functions. For example, try calling the “giveRightToVote()” function using the “alice” account, to entitle “bob,” “dave” and “eve” with the rights to submit a vote. You’ll notice that, if you are trying to call the ”vote()” function using an account that was not given voting rights priorly, the contract will trap and the transaction reverts as a consequence. If you did set the log level for the contracts runtime to “debug” in the previous step, you will be able to observe failed “require” statements in your local nodes terminal output. You will find a message like this when trying to submit a “vote()” using a non-entitled account as the caller:

2022-12-07 18:45:46.496 DEBUG tokio-runtime-worker runtime::contracts: Execution finished with debug buffer: Has no right to vote

Deploying to a testnet

Finally, let’s see how we can deploy our ballot contract to the “Rococo” live testnet, turning it into a usable Dapp. For this we are going to use the polkadot JS browser extension to create some accounts. So make sure to install that in your browser if you don’t already have it.

Creating test accounts

While our local node conveniently provided us with accounts charged up with balance out of the box, this won’t be the case on any “real” network. Instead we will create dedicated accounts. Even though you could reuse any pre-existing value-bearing Accounts from polkadot.js for this experiment, it is considered best practice to always use dedicated throw-away accounts for any development purposes. In your browser, open the polkadot JS extensions and use “Create new Account,” accessible by clicking on the big  “+” button on the top right side.

Once you successfully created a new account, in the polkadot JS extension, click on the ”gear” sign on the top-right corner and choose “Substrate” under “DISPLAY ADDRESS FORMAT FOR.” This will make polkadot JS to represent your Account ID in the correct address format used on “Rococo.” Naturally, deploying and calling any contract on-chain will cost some value, which is “ROC” tokens in the case of Rococo specifically. You can get some “ROC” tokens for free as follows:

1. Visit the Rococo faucet channel on matrix here.
2. Copy your Account ID in the “Substrate” address format and send the following command inside the Rococo faucet channel: “!drip YOUR_WALLET_ADDRESS:1002” (the “:1002” appended to your address is important).
3. A bot will respond to you shortly, confirming your balance. After a short while, you should also be able to confirm your balance by visiting the polkadot JS apps using this link.

If something does not work out, you can find more detailed instructions related to the Rococo faucet here.

Deploying the contract to rococo

We are almost there! Back inside the contracts UI, you can switch to the “Contracts (Rococo)” network using the dropdown menu in the top left corner. Once connected, you are good to use your freshly created account, loaded up with some “ROC” tokens, to deploy the contract. From now on, instantiating your contract and interacting with it works in exactly the same way as on the local node.

Image Image 4: The solidity contract deployed to the contracts parachain on Rococo

Many congratulations! You have just successfully deployed your first Solidity Dapp to a substrate parachain ✨

What’s next for Substrate

Primarily, we aim to fully support cross-call support between contracts written in ink! and Solidity. At the time of writing, it is only possible to call Solidity contracts from the ink! side in a rather bare-bones way. By implementing all missing primitives and supporting interfaces for bidirectional calls between ink! and Solidity, interacting with both worlds eventually will become a natural thing to do for smart contract authors targeting Substrate-based parachains.

A future goal will be to provide Solidity contracts direct access to chain extensions. This will open up a variety of immense benefits. For example, it is the building block for accessing randomness through verifiable random functions without calling into an oracle contract. Ultimately, support for chain extensions will enable using XCM within Solidity contracts. So stay tuned for the future!

Hyperledger Solang brings Solidity to many blockchains

Hyperledger Solang is designed to bring Solidity support to many blockchains. In addition to introducing compatibility with ink! v4, this release contains many small fixes and improvements.

A brief Solana update

On the Solana side, we are focusing on Anchor integration. Our goal is to have this finished by the next Solana Foundation hackathon so that participants can build their projects using Solidity. We still need to generate Anchor IDLs from Solidity contracts and integrate Anchor discriminators with Solang so that Rust contracts can call Solidity and vice versa. Recent breaking changes made the compiler incompatible with previous versions, but we are progressively updating the existing tooling until we switch to Anchor client side libraries.

We are looking forward to hearing from you!

If any blockchain would like to add Solidity to its list of supported smart contract languages, please do not hesitate to get in touch with us. We are excited to help anyone interested in integrating with Hyperledger Solang. As we mature our existing compilation targets, any form of feedback is highly appreciated. Try out Solang now and let us know how you get on!

Copyright © 2022 The Linux Foundation®. All rights reserved. Hyperledger Foundation, Hyperledger, and the other Hyperledger Foundation trademarks are trademarks of The Linux Foundation. For a list of Hyperledger Foundation trademarks, please see our Trademark Usage page. Linux is a registered trademark of Linus Torvalds. Privacy Policy and Terms of Use.

Close Menu
  • Learn
    • Case Studies
    • White Papers
    • Training & Certification
    • Training Partners
    • Webinars
    • Research
    • Blockchain Showcase
    • Wiki
  • Use
    • Distributed Ledgers
    • Domain-Specific
    • Libraries
    • Tools
    • Tutorials
    • Hyperledger Certified Service Providers
    • Vendor Directory
  • Participate
    • Collaboration Tools
    • Contribute to Coding
    • Academic Collaboration
    • Find a Meetup
    • Regional Communities
    • Speakers Bureau
    • Join a Community Group
    • Labs
  • Events
  • News
    • Blog
    • Announcements
    • Newsletter
  • About
    • Join Hyperledger
    • Members
    • Leadership
    • Charter
    • Job Board
    • Contact Us
  • Join
  • English
    • 简体中文
    • Português
    • Français
    • Malayalam
    • 日本語
    • Español