Ethereum Smart Contract & Test Driven Development

Matthew Minseok Kim
HAECHI AUDIT
Published in
8 min readJun 25, 2018

This article is written to summarize various tools HAECHI LABS has used for smart contract development. And, anyone can access the code through HAECHI LABS’ github. It would be awesome if HAECHI LABS’ small contribution can help the smart contract development world.

Smart contract is the development tool to show new potential for blockchain industry since it can be used in many ways. For instance, smart contract can be used to create ERC20 tokens or make a game like CryptoKitties where you can buy and sell cute cats. In addition, it can be also utilized for making multisig wallet and decentralized exchange (DEX). Above all, smart contract is mostly used for Initial Coin Offering(ICO).

Even if smart contract sounds like magic word to solve many problems, we need to be careful for developing secure smart contract. Because smart contract executes on top of decentralized network environment, there are many different features compared to other software program. In particular, we cannot modify a code if you deploy the smart contract to main-net. Although we are able to update business logic by using proxy patterns for update, we still cannot adjust the code we deployed. It cannot be reversed even if a bad transaction occurs due to a fatal flaw in the code or wrong implementation.

For example, a blockchain team can suffer from massive economic losses if there is a security flaw in the smart contract for ERC20 tokens and hackers steal an enormous amount of ERC20 tokens. The parity multisig wallet freeze and the SmartMesh(ERC20) hacking were also examples of damage caused by security flaws in the smart contract.

To create a secure smart contract, you need to be aware of known attack patterns and have enough tests to write code. There are mainly two types of tests; one is to execute the deployed smart contract on main-net or test-net and another is to execute a test before deployment. Of course, the latter method is suitable for more efficient test. I am going to write how we can make a test code and build development environment to help make a test code conveniently.

Test driven development, TDD

Before jumping into how to make a test code, I would like to explain what test driven development (TDD) is. TDD is one of the software development methods and it literally says test leads code development. TDD is not to write any production code but make a failing unit test pass and then make the code work. TDD has the benefits even if it seems like wasting time or ineffective development method.

First, TDD simplifies to write a code. Without a test code which define each role and functionality of a function, one function can include many logic. In this case, one function becomes a universal function, making it difficult to write a test code later.

Second, TDD increases the readability of the code. Test code helps programmers to know which input a function receive and which output the function return. Additionally, it helps to understand the code because a test code includes which value should be prepared in order to call a function.

Lastly, it is likely to ensure the completeness and correctness of the code. We can easily check the completeness of the code throughout simple execution of a test after modifying the code. Without a test code, it is difficult to tell whether the function works well right after the code modification.

Source: http://lewandowski.io/2017/02/thre-levels-of-tdd-1/

The mantra of Test-Driven-Development is called ‘red, green, refactor’ a framework that programmers use to build a test code, write production code, and eliminate redundancy.

RED: Before writing business logic, write a test and watch it fail.

GREEN: Write enough code to pass the test.

REFACTOR: Eliminate redundancy and improve the code without changing its behavior.

TDD is an usual development methodology used in app, web, and server. However, there are many difficulties to build a test code in a traditional software. For instance, in order to build test code for android application, we use MVP and MVVM patterns separating layers which is used to implement view layers depending on framework, data model layers, and business logics (Pure Java). In this pattern, to develop a test code, we use Mock objection by using Dependency Injection for network and storage. There are architectures to help write a test code simply and clarify each role of layer.

However, it is much simpler to write a smart contract on top of Ethereum rather than traditional test code for software program. There is no view layer dependent on the framework and there is no complicated network communication and Mock objection which enables storage access for simple test. However, smart contract development environment is not mature yet which makes developers inconvenient.

Pain points of smart contract development environment & Solution

Many programmers use Truffle framework to develop smart contract. However, there are some pain points to proceed TDD by using only Truffle. Additionally, it is quite inconvenient to deploy smart contract to test net or main net. Even if there are many open sources to solve those problems, it is uncomfortable since it is not integrated into one development environment. Let’s take a look at what is required and what should be provided when developing smart contracts using TDD. I explain development environment HAECHI LABS used for developing smart contracts and refer openzepplin-solidtyproject.

#1. I would like to write a code quickly and execute a test code simply and easily.

TDD code, HAECHI LABS published, helps to write a test code easily by using test library, chai-as-promised, and chai-bignumber. It also helps to import and use test libraries of openzeppelin-solidity. And it does not need to run TestRPC separately, but we can run TestRPC through test.sh shell script using ganache-cli in order to execute a test code and TestRPC will be finished if test is finished. In other words, you can easily execute the code you wrote above with only one npm run test line. The process for executing a test should be simple in TDD, therefore we can do develop a code easily.

The result of test code execution

#2. We want to know how much coverage the test code has for Solidity code.

While writing a test code, we might wonder whether a test code can testify all Solidity code. However, if you write many lines of code, developers might have a problem checking if each solidity function has its own test code. In this case, you can easily know it if you use a test code coverage tool. In other words, you can use solidity-coverage to see how much percent of your Solidity code is testified by your test code. If you type the command,npm run coverage, it executes the test code and shows how much percent of the Solidity code the test code can cover.

The result of test coverage execution

#2. We want to write a clean and same style code when you cooperate with other team mebers.

It is better to follow the company’s code style when you develop a software with other team members. If you include linter into a project, you can easily check if code style follows a fule. There is a good linter, eslint, in Javascript. And there is also a linter,solium, in Solidity even if it is not mature. If you use HAECHI LABS’s TDD, you can use both linters and easily execute those throughout npm run lint:all command. If you only execute eslint, you can use npm run lint. If you only execute solium , you can use npm run lint:sol.

The execution result of eslint
The execution result of solium

#4. We want to know how much gas each function and transaction will consume in Solidity

It is significant to predict precisely how much gas smart contract function and transaction will consume in order to deploy into test-net or main-net. If you do not consider gas limit enough, the smart contract might not work due to out of gas. In particular, ICO team should notify investors how much gas limit the team recommend for successful transaction. To find the suitable gas amount, we use eth-gas-reporter. If you use this plug-in, npm run test해will execute a test code and show how much gas each Solidity function consume throughout the table below.

Gas consumption of each function measured by eth-gas-reporter

#5. We want to deploy a code into test-net.

It is very important to generate a transaction on top of test-net before deploying into main-net after developing smart contract throughout Test-Driven-Development(TDD). However, many blockchain teams do not testify their code because this work requires time and cost. HAECHI LABS TDD published a way to help blockchain teams deploy test-net easily. At first, it connect individual wallet by using truffle-hdwallet-providerand help deploy a code easily by a command line. If you use Infura, you can deploy smart contract by connecting to Ethereum node without running Geth on top of local computer. HAECHI LABS help programmers setup development environment by adding code below into truffle-config.json.

rovider = require('truffle-hdwallet-provider');
const providerWithMnemonic = (mnemonic, providerUrl) => new HDWalletProvider(mnemonic, providerUrl);
const infuraProvider = network => providerWithMnemonic(
process.env.MNEMONIC || '',
`https://${network}.infura.io/${process.env.INFURA_API_KEY}`
);

Developers, building the development environment, just need to make .env file and register Mnemonic 12 digits of their HD wallet and INFURA_API_KEY given from Infura. And then the environment variables set by dotenv are loaded.

Open Source

It is not possible to modify smart contract if you deploy it once and it can cause a colossal amount of economic damage if there is a bug; therefore, it is significant to have enough tests before deployment. I uploaded development environment described above, boilerplate project code, at github. When you develop smart contract, feel free to use this. And I would love to get your feedback.

HAECHI LABS is a smart contract security lab and provides smart contract development and audit service. You can contact us to hello@haechi.io.

--

--

Matthew Minseok Kim
HAECHI AUDIT

HAECHI LABS COO, Smart Contract Security, Blockchain researcher at Decipher