In our previous post we tried compiling, disassembling and comparing Ethereum smart contracts using solc, the Solidity compiler, and evmdis, a Solidity disassembler that works on the principle of abstract interpretation.

We encountered a number of issues when trying to compile more older Solidity smart contracts (such as The DAO) with current solc versions, and vice versa. In this post we look at the Solidity compiler versions, and how one might go about building different versions.

Solidity compilers: solc and solcjs

There are actually two Solidity compilers: solc, written in C++, and solc-js, which uses Emscripten to cross-compile from the solc C++ source code to JavaScript. Technically they’re built from the same source code, but in practice they appear to produce slightly different results. They also have different command line interfaces, and solcjs is (as expected) quite a bit slower than solc.

$ time solc --optimize --bin -o . Test1.sol
Warning: This is a pre-release compiler version, please do not use it in production.

real	0m0.075s
user	0m0.007s
sys	0m0.009s

$ time solcjs --optimize --bin Test1.sol

real	0m3.950s
user	0m3.524s
sys	0m0.337s

A JavaScript build of the Solidity compiler allows for some cool applications though, like the web based Remix Solidity IDE.

The Solidity smart contract language and its versions

Solidity is the smart contract language of the Ethereum blockchain. It is a high-level C-family language and compiles down into Ethereum bytecode, which runs on the Ethereum Virtual Machine (EVM). The EVM is a distributed virtual machine running across all the nodes participating in the Ethereum blockchain, and is integrated into an Ethereum client. The most popular Ethereum clients are cpp-ethereum, go-ethereum and [Parity][evm-parity] (written in Rust). The bytecode and EVM operation is described in detail in the so-called Ethereum yellow paper by Gavin Wood.

Since the Ethereum blockchain is immutable, one can reasonably expect smart contract (bytecode) deployed on the blockchain will always be valid. That is, if breaking changes are made to the Solidity bytecode speicifcations, the EVMs will always need to support already-deployed bytecode. However, changes to the high-level Solidity language might be backwards incompatible with older versions of the solc compiler, and vice versa.

This is exactly what we encountered when experimenting with evmdis, where we were unable to compile The DAO source code (circa Mar 2016) with the latest version of solc (circa May 2017).

Version Pragma

Since the 0.4.0 release of Solidity, it has been a requirement to have a version pragma statement such as pragma solidity ^x.y.z at the top of every Solidity file. As the documentation notes, more complex rules are possible and this allows for a compiler to gracefully reject incompatible source files rather than compiling with (possibly) undefined or undesirable results.

Versions of Solidity: Ethereum Improvement Proposals

It’s not clear if there’s a comprehensive list of Solidity language changes, or the mirror of this, changes in solc output for the same Solidity input. Aside from blog or reddit posts, the most notable source we were able to locate is the list of Ethereum Improvement Proposals (EIPs), which is the process by which standards changes are discussed, formalized and agreed upon for Ethereum.

Installing solc

Solidity and solc are under very active development, and have changed substantially over time. We generally followed the Solidity documentation on building and installing solc, but for the 0.4.11 version (May 2017), noted a few quirks:

  • There’s currently no downloadable binary package available for Mac OS due to some build pipeline issues. Linux and Windows users can install from binary.

  • Installing via Homebrew pegged our CPUs for 10s of minutes recompiling Boost. We aborted.

  • We ended up cloning and building from the source on Github. It took about 30 minutes and we didn’t have any issues with Boost.

Installing earlier versions of solc

Part of the active development process of Solidity has meant that documentation and source code, and their dependencies, have moved around. In order to recompile The DAO as part of our previous post, we needed to obtain a version of solc circa May 2016, about a year ago. In fact, we had wanted to use the exact solc version that was used to compile the deployed version of The DAO, [solc version v0.3.1-2016-04-12-3ad5e82][the-dao-contract]. After much searching on Github, we were unable to locate this particular revision (3ad5e82), so gave up and went with solc 0.3.2 (28b30ec13).

The build process has changed too. The documentation refers to repos that have moved or been deprecated, so we basically used the new repos (cpp-ethereum) with the old commands, and just hacked around until we got it working.

Conclusion

It would be an interesting project to build a solc-meta-builder that could build an arbitrary version of solc, and then compile Solidity source code with it.