Building dapps on Ethereum - part 2: smart contracts

This is the second post in my series about building decentralised apps (dapps) on Ethereum. In this post we will cover installation and configuration of the development environment for coding, compiling and testing smart contracts. You’ll also learn how to set up two different Ethereum blockchains on your local computer, firstly with testrpc for automated testing and secondly with geth which is a full-spec client for more advanced needs.

Before we begin

If you haven’t already, I would recommend you to read the previous post in this series:

Here is what we’ll cover:

  1. Important concepts
  2. Development tools
  3. Basic project structure
  4. Writing your first smart contract
  5. Writing tests for smart contracts
  6. Running tests

In the third and next post in this series we will learn how to write a user interface for our smart contract.

The setup described below assumes macOS v10.12 and NodeJS (v7 or v8). Further, it’s helpful to have a basic understanding of what a blockchain is, what a smart contract is and the big picture of what makes a decentralised app. I described the latter in the first post of this series.

1. Important concepts

So far on this blog we’ve covered the very basic concepts of what dapps are. But to actually develop dapps there are some further concepts that are important to understand. Pay extra attention to the following things throughout this post:

2. Development tools

In order to be productive I would recommend a decent IDE. I’m used to JetBrains’ PhpStorm, so I used the ItelliJ-Solidity plugin for working with smart contracts:

We need a tool to help us with compilation, migration and testing of contracts. For this we use the Truffle framework. We also need a client in order to run a blockchain locally for testing. [TestRPC] is the standard choice which works well for automated testing, so we’ll use this. Install both tools globally so that you use them across your different projects:

$ npm install -g truffle ethereumjs-testrpc

As a bonus at the very end of this post we’ll cover how to install and run geth for more advanced needs.

3. Basic project structure

The Truffle framework project has some decent resources for creating and developing smart contracts. For example, you can read their documentation and tutorials and learn how to use the truffle init command to scaffold an example project. But for the purpose of this post we are going to manually create a minimum viable project in order to truly learn what everything means.

We will start by creating the following files and directory structure for our dapp:

build/
chain/
contracts/
- Migrations.sol
migrations/
- 1_initial_migration.js
scripts/
src/
test/
genesis.json
truffle.json

We have not yet created any project-specific files. The above structure, and the source code of these files are project-agnostic and can be re-used for almost any project. Here’s a brief description of each directory and the source code for each file so far:

build/ is where Truffle will put our compiled contracts.

chain/ is where the data directory and all the blockchain files will live. This is only required when using geth as the blockchain client.

scripts/ is where we later will put various utility scripts.

src/ is where we later will put the Javascript source files for our dapp front-end.

test/ is where we will keep our files for automated testing.

contracts/ is where the Solidity source code will live for all our contracts. The only contract so far is the required but project-agnostic Migrations.sol that Truffle is using to store the migration state for your project-specific contracts (we have not yet created these). Don’t worry about understanding the source code of this contract yet.

migrations/ is where we need to put deployment scripts for all contracts. Naming of these scripts are important, they are executed in numerical order and the first script must be the required but project-agnostic 1_initial_migration.js which migrates Migrations.sol to the blockchain for the purpose we described earlier. Your project-specific deployment scripts must be named 2_example.js, 3_example.js etc. The format of deployment script is easy to understand and is described in the Truffle framework documentation. You will need both of these scripts:

genesis.json contain information required to create the very first block in the blockchain (called the coinbase). This is only required when using geth as the blockchain client. The file contains information such as the initial mining difficulty, gas limit for transactions etc.

Interesting fact: Bitcoin’s coinbase block famously contains this piece of extra data:

The Times 03/Jan/2009 Chancellor on brink of second bailout for banks

truffle.js contain basic configuration neededs for the Truffle framework in order to connect to the blockchain which we will start later in this guide.

4. Writing your first smart contract

Alright, we’re done with the basic project structure and we have everything we need to actually write our own contracts. Throughout this blog post series we will use sample code from the Iron Doers project which is a quite simple concept briefly described in a practical example of using blockchains and the project’s whitepaper.

Smart contracts are written in Solidity and I’ll cover some basics of how it works, but for more details I recommend you reading the Solidity documentation. Our first smart contract will be a simple organisation that can do four different things:

The source code for this organisation is very straight forward. Solidity is a strictly typed language which makes it quite easy and convenient to read:

I won’t go into all the linguistic details of how Solidity works, but there are a few key things going on here:

5. Writing tests for smart contracts

Tests are extremely important when dealing with systems of trust and financial data. Tests can be written in either Solidity or with Javascript (using Truffle’s abstractions that call out to the bytecode on the blockchain). I’ve chosen Javascript because our front-end will later be written in Javascript, which means we can have all our tests in a single language — that’s handy!

The Truffle framework embeds support for the popular Mocha test framework for Javascript. Here’s what some basic tests look like for the above contract:

Notice the syntax difference between a call vs transaction, i.e. contract.getDoerCount.call() vs contract.addDoer().

6. Running tests

Now we’ve got our tools, the project structure, the first contract and some tests in place. Let’s run it all! First we need to start the blockchain we will use to run our tests on:

$ testrpc

Then, in a new terminal window you must compile and migrate all contracts to the blockchain you just started:

$ truffle compile --all
$ truffle migrate --reset

Then finally we can run the automated tests with one simple command:

$ truffle test

Hopefully you will see something like this:

Bonus: Installing and running geth

This setup will use the geth client to run a local blockchain. This is good for advanced testing and debugging, but can be a little bit complicated to set up. If you want to run the test suite against a blockchain on geth instead of testrpc then you need to manually create all required accounts and fill them with Ether accordingly (this is what testrpc does automatically for you).

Install global dependencies:

$ brew tap ethereum/ethereum
$ brew install ethereum

To begin operating the blockchain you first need to initiate the genesis block and then jump into the console:

$ geth --datadir ./chain init ./genesis.json
$ geth --datadir ./chain --rpc --rpcapi="db,eth,net,web3,personal" console

Note that this blockchain isn’t very useful yet — there are no accounts and no one is mining, so no transactions would be verified. To fix this we need to:

  1. Create the first user account
  2. Unlock said account
  3. Start mining Ether

First, while inside the geth console, create a new account and give it a password by running:

> personal.newAccount()

Second, to unlock the account for 9999 seconds by copying the address that was created in the previous step and run:

> personal.unlockAccount("the address", "the password", 9999)

Third, in order to be able to do transactions you need to (a) have some Ether to pay the gas fees and (b) validate said transactions. Both are achieved via mining, which you start in the console by running (using 1 CPU thread):

> miner.start(1)

At any point you can stop mining by running the below function. But remember, no transactions will be processed while mining is stopped! Mining is what keeps the system running.

> miner.stop()

Continue reading

Featured image: Creative Commons Attribution 3 - https://www.ethereum.org/assets