Building dapps on Ethereum – part 2: smart contracts

View this thread on: d.buzz | hive.blog | peakd.com | ecency.com
·@dickolsson·
0.000 HBD
Building dapps on Ethereum – part 2: smart contracts
![Ethereum-homestead-background-7.jpg](https://steemitimages.com/DQmUZWkUf5KeHkD5LaDhGhR8Xjoy3K6fMvWARPbd7df8fay/Ethereum-homestead-background-7.jpg)

This is the second post in [my series about building decentralised apps (dapps) on Ethereum][series]. 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.<!--more-->

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][chain], [what a smart contract is][contract] and the big picture of what makes a decentralised app. I described the latter in [the first post of this series][p1].

## 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:

- *Compilation* — the act of compiling Solidity code into byte code that can be stored on the blockchain for execution.
- *Call* vs *Transaction* — calls are functions in smart contracts that *read* data from the blockchain while transactions *write* or *update* the state of the blockchain. Calls cost nothing to execute, while transactions cost *gas*
- *Gas* — the cost of transactions on the blockchain which is paid with Ether (remember that [nothing is free][lunch]).
- *Migration* — a transaction that create (or update) a contract to the blockchain.
- *Mining* — the act of verifying transactions which is rewarded with Ether (that in turn can be used to pay for gas).

## 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][ide] for working with smart contracts:

<img class="alignnone size-large wp-image-518" src="https://dickolsson.com/wp-content/uploads/2017/06/Screen-Shot-2017-06-18-at-10.31.53-1024x341.png" alt="" width="1024" height="341">

We need a tool to help us with compilation, migration and testing of contracts. For this we use the [Truffle framework][truffle]. 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:

```bash
$ 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][doc] and [tutorials][tut] 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
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.

`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.

```
pragma solidity ^0.4.4;

contract Migrations {
  address public owner;
  uint public last_completed_migration;

  modifier restricted() {
    if (msg.sender == owner) _;
  }

  function Migrations() {
    owner = msg.sender;
  }

  function setCompleted(uint completed) restricted {
    last_completed_migration = completed;
  }

  function upgrade(address new_address) restricted {
    Migrations upgraded = Migrations(new_address);
    upgraded.setCompleted(last_completed_migration);
  }
}
```

`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][migration].

```js
var Migrations = artifacts.require("./Migrations.sol");

module.exports = function(deployer) {
  deployer.deploy(Migrations);
};
```

`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.

```json
{
  "config": {
    "chainId": 33,
    "homesteadBlock": 0,
    "eip155Block": 0,
    "eip158Block": 0
  },
  "nonce": "0x0000000000000033",
  "timestamp": "0x0",
  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "gasLimit": "0x8000000",
  "difficulty": "0x100",
  "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "coinbase": "0x3333333333333333333333333333333333333333",
  "alloc": {}
}
```


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.

```json
module.exports = {
  networks: {
    development: {
      host: "localhost",
      port: 8545,
      network_id: "*"
    }
  }
};
```

## 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][iron] which is a quite simple concept briefly described in a [practical example of using blockchains][practice] and [the project's whitepaper][wp].

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][sol]. Our first smart contract will be a simple organisation that can do four different things:

- Add doers (a transaction)
- Get the address of the trustee (a call)
- Get the number of doers (a call)
- Check if a given address is a doer (a call)

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:

```
pragma solidity ^0.4.0;

contract IronDoers {

	address public trustee;
	mapping(address => bool) public doers;
	uint public doerCount;

	modifier onlyTrustee {
  		if (msg.sender != trustee) throw;
  		_;
	}

	function IronDoers() {
		doerCount = 0;
		trustee = msg.sender;
		addDoer(trustee);
	}

	function addDoer(address addr) onlyTrustee {
		doers[addr] = true;
		doerCount++;
	}
  
	function getTrustee() constant returns (address) {
		return trustee;
	}

	function getDoerCount() constant returns (uint) {
		return doerCount;
	}
	
	function isDoer(address addr) constant returns (bool) {
		if (doers[addr]) return true;
		return false;
	}
}
```

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

- State variables (e.g. `uint public doerCount;`) hold the data stored on the blockchain
- The global variable `msg` hold metadata about the current message sent to the contract (such as the sender's address)
- The *constructor* (e.g. `function IronDoers()`) is only executed once when the contract is first deployed/created on the blockchain
- *Constant* functions promise to not change the state of the blockchain, i.e. you can *call* these for free without having to pay *gas*
- *Modifiers* are bits of code that are executed before the modified function. These are often used for access checks. The `_;` syntax is where the execution of the modified function continues.

## 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][mocha]. Here's what some basic tests look like for the above contract:

```js
var IronDoers = artifacts.require("./IronDoers.sol");

function assertThrow(err, test, msg) {
  if (err.toString().indexOf(test) != -1) {
    assert(true, msg);
  } else {
    assert(false, err.toString())
  }
}

contract("IronDoers", function(accounts) {
  it("should set the trustee", function() {
    var contract;
    return IronDoers.deployed().then(function(instance) {
      contract = instance;
      return contract.getTrustee.call();
    }).then(function(trustee) {
      assert.equal(trustee, accounts[0]);
    }).then(function() {
      return contract.getDoerCount.call();
    }).then(function(count) {
      assert.equal(count, 1);
    });
  });

  it("should validate doers", function() {
    var contract;
    return IronDoers.deployed().then(function(instance) {
      contract = instance;
      return contract.isDoer.call(accounts[0]);
    }).then(function(bool) {
      assert.equal(bool, true);
    }).then(function() {
      return contract.isDoer.call(accounts[1]);
    }).then(function(bool) {
      assert.equal(bool, false);
    });
  });

  it("should only let the trustee add doers", function() {
    var contract;
    return IronDoers.deployed().then(function(instance) {
      contract = instance;
      return contract.addDoer(accounts[1], {from: accounts[0]});
    }).then(function() {
      return contract.getDoerCount.call();
    }).then(function(count) {
      assert.equal(count, 2);
    }).then(function() {
      return contract.addDoer(accounts[2], {from: accounts[1]});
    }).catch(function(err) {
      assertThrow(err, "invalid opcode");
    }).then(function() {
      return contract.getDoerCount.call();
    }).then(function(count) {
      assert.equal(count, 2);
    });
  });
});
```

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:

```bash
$ testrpc
```

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

```bash
$ truffle compile --all
$ truffle migrate --reset
```

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

```bash
$ truffle test
```

Hopefully you will see something like this:

<img class="alignnone wp-image-555 size-large" src="https://dickolsson.com/wp-content/uploads/2017/06/Screen-Shot-2017-06-21-at-19.06.44-1024x524.png" alt="" width="1024" height="524">

## 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:

```bash
$ brew tap ethereum/ethereum
$ brew install ethereum
```

Install project dependencies:

```bash
$ npm install
```

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

```bash
$ 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:

```js
> personal.newAccount()
```

Second, to unlock the account copy the address that was created in the previous step and run:

```js
> personal.unlockAccount("the address")
```

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:

```js
> miner.start()
```

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.

```js
> miner.stop()
```

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

[series]: https://dickolsson.com/tag/how-to-build-dapps/
[chain]: https://dickolsson.com/whats-a-blockchain/
[contract]: https://dickolsson.com/practical-example-benefits-using-blockchain/
[p1]: https://dickolsson.com/building-dapps-on-ethereum-part-1-overview/
[lunch]: https://dickolsson.com/no-free-lunch/
[ide]: https://plugins.jetbrains.com/plugin/9475-intellij-solidity
[truffle]: http://truffleframework.com/
[doc]: https://truffle.readthedocs.io/en/develop/getting_started/project/
[tut]: http://truffleframework.com/tutorials/
[migration]: https://truffle.readthedocs.io/en/develop/getting_started/migrations/
[iron]: https://github.com/dickolsson/irondoers
[practice]: https://dickolsson.com/practical-example-benefits-using-blockchain/
[wp]: https://github.com/dickolsson/irondoers/blob/master/WHITEPAPER.md
[sol]: https://solidity.readthedocs.io/en/develop/
[mocha]: https://mochajs.org/
👍 , , , , , , , , , , , , , ,