Hands-on practicals


If you have installed truffle on your laptop, the files for these practicals can be downloaded from this repo. If you prefer to try using the docker image, see the Appendix. If you are using the provided virtual machine, the project files are in the home directory.

Practical 0: warm-up

As noted above, you can download the project files from:


  1. Download Ganache. This gives a nice graphical view of the local blockchain.

  2. Configure the truffle configuration to set the development network to port 7545 (used by Ganache).

  3. Open a terminal in the workshop_project directory
  4. Compile the smart contract with the truffle command.

$ truffle compile
  1. Launch Ganache.

  2. Migrate the contract. In Ganache, notice how the state of the blockchain changes after the migration.

$ truffle migrate
  1. In the app directory, we build and run our frontend. Smart contract changes must be manually recompiled and migrated. Run the following in another terminal i.e. not in the truffle develop prompt.
$ cd app
$ npm run dev
  1. Truffle can run tests written in Solidity or JavaScript against your smart contracts. Back in the development console, run the following.
$ truffle test
  1. Optional. To build the application for production, use the build script in the app folder. A production build will be in the app/dist folder.
$ npm run build

Now move on to Practical 1.

Practical 1

Let us customise the token contract a little.

ERC-20 provides a standard interface for the implementation of token smart contracts. It allows client applications (such as wallets and exchanges) to work with different token implementations via a common API.

For example, the interface allows token implementations to (optionally) have a descriptive name and “ticker”-like symbol. We need not implement a fully ERC-20 compliant token here, but let us nevertheless customise the token name.

Naming the token

We will give a name to the token, via a little test-driven development (TDD) to illustrate a typical process for testing the contract.

  1. Identify the two ERC-20 functions that return the name and symbol of the token, and add these to the contract (but do not set these yet!).

  2. In test/metacoin.js, add test cases to check the name of your token (e.g. "JoeBloggs", "JBX"). Check that these new tests run (but fail), following a similar workflow to Practical 1A.

  3. Now “fix” these failing tests by setting your token name appropriately in the contract. Check the tests pass as a result of your change.

Checking transfers

Next we will check that the given sendCoin is implemented sensibly.

  1. Add further test cases to exhibit the property “one cannot spend what he does not have”. In other words, it should not be possible to transfer an amount of tokens (via the sendCoin function) if the sender does not have at least that amount in his balance. Note that this task should be achievable with little to no modification to the contract itself.

  2. Optional. Add further tests similar to properties expressed like that in 4.

Transaction charge

We will now modify the behaviour of the contract further so that every transfer of tokens pays a so-called “non-Sterling transaction charge” (common with some rip-off banks). At least this charge just goes back to the instructor, so that the course is continually improved ;P

  1. As with TDD-style, first add a test case checking that 1 unit of the token in a transfer is deposited to the instructor (assume this is the 2nd account of your local blockchain).

  2. Now fix the test by modifying the sendCoin function of the contract.

Event handling

In this next task, we will make a change that requires work both in the contract and at the interface between contract and front-end.

Take a look at app/src/index.js. In the sendCoin function, a call to refreshBalance is made after the (asynchronous) call to the contract function. But a more robust solution would instead use a contract event. Indeed, ERC-20 contracts require such an event Transfer to be published whenever a token transfer succeeds:

event Transfer(address indexed from, address indexed to, uint256 value);
  1. Add a Transfer event to the token contract that signals whenever a sendCoin transfer succeeds.

  2. Modify index.js to respond to the event. The response should be a call to refreshBalance. You may find the Web3 documentation helpful.

Practical 2A

In this practical we will go about setting up and connecting to a private Ethereum network. In more detail, we will:


In the past, setting up a private network was rather involved. Recent tools bundled with Geth e.g. puppeth and bootnode make this process a little easier. If you are interested in setting one up, see steps 1 and 2. Note: close Ganache as we will not use it here.

  1. Download Geth & Tools from the Geth Downloads page. Also see this guide.

  2. Use the tools to generate a genesis file, network id and boot node (For more information, see e.g. the relevant parts of this guide). For this example config.

geth --datadir data init xyz.json
  1. Connect to network by starting geth, setting the --networkid option
geth --datadir data --networkid 20190409 --bootnodes "enode://bd0accfbd571f3caee0459fbe941274b6d71c507413a382fc7abbbabe2004f8a6099c37ac7eecbc454f34c04395e649a474ced41633a0912e466003306362708@" console
  1. In the Geth console, create an account.
  1. Start mining - at the Geth console:

Note: to stop mining

  1. To open your node to RPC calls, restart the Geth node adding the following flags,
--rpc --rpccorsdomain "*" --unlock 0

You should then be able to connect via port 8545.

  1. Migrate the token contract using Truffle (the RPC port you opened with Geth allows Truffle or other external programs to connect to it).

  2. For the purposes of the next step, it is useful to install BlockScout - a kind of “block explorer”.

  3. Send a transaction (e.g. send some tokens) through our private network by reconfiguring your web3 (or Metamask, if you prefer), and trace this with BlockScout.

Practical 2B

Goal: To integrate IPFS with Ethereum investigate the ipfs-http-client libraries.

In this practical we will work with IPFS, which you should have installed. The task is to create a simple application that allows you to input some feedback for the course (or perhaps just a to leave a “guestbook”-style message), and have this stored in IPFS. Also leave a tip for your instructor!

  1. Go through the basic IPFS guide.

  2. Install the JS client library.

  3. Check out the README of the library to see how to connect to IPFS, and how to write a text file to it. Some example code in your web / server javascript to get you started:

var ipfsClient = require('ipfs-http-client')

// connect to ipfs daemon API server
var ipfs = ipfsClient('localhost', '5001', { protocol: 'http' }) // leaving out the arguments will default to these values

function writeToIPFS(fileContent) {
  return ipfs.files.add(Buffer.from(fileContent)).then((res) => {
    let ipfsHash = res[0].hash;
    logger.log('ipfs', `Saved IPFS file`);
    return ipfsHash;
  1. When a file is stored on IPFS, take the IPFS hash (e.g. the output of writeToIPFS above) and store this in the contract.

  2. Add a front-end with a text box for the feedback / guest message.

  3. Optional. Charge for storage, using the token functionality of your contract.


Docker Image

If you are unable to install truffle, follow these steps to load and run the docker image

docker run -it --mount type=bind,source=<your local file system>/workshop_local,target=/work_data truffle_image

You can then edit the work_data files on your local file system.

In the docker image copy the files from /initial_data to work_data

cp -R initial_data/* /work_data

In the image, you should find a workshop_project directory.