How to Test Smart Contracts on Ethereum, Code Included

Jonathan Levison
The Orbs Blog
Published in
5 min readJun 19, 2018
Image by Marina Rudinsky

The Orbs blockchain relies today on Ethereum in more than one way. At Orbs, we have a ERC20 token (ORBS) which among other things, can be used to purchase our consumer apps oriented blockchain. Another application we have running is our subscription validation, which checks if a customer has a valid subscription to use the Orbs blockchain service.

As we were developing our blockchain solution, to check the subscription we found ourselves in need of a sidechain connector to Ethereum, and as we were writing the tests, we saw that connecting to Ethereum and more importantly testing the connection logic is not that simple today.

So Ethereum has a testnet of course (we use Ropsten) but although there is no actual cost, you still need to deploy a contract there and the process is not a simple as running an automated test — the testnet still has some notion of resource limit. In more common terms, the testnet can be seen as a staging environment, but what about a development environment? This is where we could not find exactly what we were looking for and had to create our own solution.

The first version of our blockchain was built using TypeScript, and we were looking to see if there is something that would make it simple for us to test our contracts and side-chain connector logic.

We are not alone of course, and Consensys made available the truffle suit, as they describe it: ‘your Ethereum swiss army knife’. Truffle feature set is very broad, and it is easy to get lost there. Our requirements were very specific in regards of what we needed to do:

  • Ensure the smart contract compiles
  • Ensure we can call the smart contract function
  • Make sure that the entire logic around the connection and object parsing is stable.

So to perform that, we found out that the following toolset is required:

  • Ganache-core — part of the truffle suit, it is the Ethereum blockchain emulator
  • Solc-js — based on the solc C++ project, it is a Javascript solidity compiler
  • Web3.js — the Ethereum Javascript API

But wait! Don’t we also have remix to help us test our solidity code, why go through all this trouble? And indeed we also use remix to test the contract itself but eventually, although remix can run its own Javascript VM, we want to be able to test the code from our Javascript implementation.

Exploring the web and looking on how people are using Typescript with the above libraries did not net us the solution we were looking for, of doing the above in a simple way. To be more specific, the truffle suit enables the features we were looking for, but it feels over engineered to our needs. There are several wrappings of web3 for typescript, but that alone did not get us any closer to our goal as well.

So we decided to build something that fits our needs and open it up for the community, in case it can help someone else. Our package which we also use internally is called ethereum-simulator, and is based on Ganache core for blockchain simulation, solc to compile the contract and web3 to access the blockchain.

The main two use cases for this component can be:

  • Testing a contract call from within Javascript/Typescript
  • Testing your own web3-based rpc implementation vs. a Ganache instance

Using it to test a contract is as simple as:

The contract that fits this test is:

Breaking down the above, we first define a new EthereamSimulator instance

When calling listen(port) we will open the ganache core instance with an account that has more than enough ‘ether’ to do any operation we may need.

We then ‘add’ the contract and arguments to initialize it:

These are synchronous operations which just load data into our object, could have been a builder pattern if this was not so short, will perhaps change that if we add more functionality in the future.

The contract variable is the solidity contract as a string value.

Next we compile and deploy the contract to the ganache instance, this will use solc to compile the contract and return the contract address after it was deployed.

It can take a couple of seconds for this line to execute, especially at the first time this contract is used (cold execution).

At this point the ganache has the contract ready and you may call and execute functions on this contract. The code below does that exactly using web3 behind the scenes:

What returns from the callDataFormSimulator() call as ‘data’ in the example above is using the DataFromEthereum interface:

In our case, according to the function interface we passed it will have a ‘intValue’ and ‘stringValue’ keys. At this example we then output the string value stored in our contract and then close the simulator using

In cases where you want to test with external code, you should defer calling the close() until your test code is done. For examples on how to use it with mocha and chai, you can refer to the package testing code that can be found in the github repo at test/ethereum-driver.spec.ts

For us, this package made it much simpler to setup and run the ganache-core code as well as test our contracts from within our system.

In the EthereumSimulator you will also see the function call callDataFromEthereum(), which accepts an endpoint. This endpoint will be used in web3 to access the Ethereum node at that address. This was left open as a simple wrapper for accessing Ethereum and call a smart contract according to the interfaces we built.

The library is available as an npm package at:https://www.npmjs.com/package/ethereum-simulator

Its code is available in Orbs’ GitHub repository at:

What may be missing here:

  • It is worth noting that the 0x project has an interesting project around web3 typescript wrapping and we can probably benefit working with the ABI and function calls should this package (ethereum-simulator) become larger and more complex.
  • No way to send() over Ethereum — we did not need that for our use case and thus did not implement it. As sending a transaction over Ethereum is an asynchronous operation, implementing such a feature for synchronous testing of a smart contract makes little sense, but still that does not mean this feature is redundant (and this is true for most of the other blockchains publicly available today).

The future releases of Orbs network will include a much wider support for cross-chain execution, especially from Ethereum. The ability to have both polyglot contracts and giving them the ability to access data on other blockchains is extremely important to enable applications to choose the right blockchain for the right data and use case. Our testing frameworks enable us to move fast and achieve a quick feedback on how our code is behaving, and thus enable our blockchain customers better cross-chain abilities.

--

--