Ethereum Contracts with Truffle Framework

Recently, I have been looking for tutorials on how to create a simple Ethereum Smart Contract.
As it turned out, most of blog posts and articles I found are quite outdated and have
mistakes or issues related to the newer versions of the Ethereum tooling. At some point,
I found myself constantly jumping between the stackexchange website,
GitHub Issues and random tutorials
to simply move forward and complete the originally picked up tutorial for voting.

This shows that the area of Blockchain is evolving very fast, so that existing
tooling is constantly getting broken by newer versions.

In this blog post, we will implement a simple Ethereum contract using Truffle framework and
Solidity. Then, we will deploy it to the test network Rinkeby. Hopefully,
this tutorial will be much cleaner and last longer.

From our goal perspective, the main subject of the smart contract does not really matter. However, let’s choose something
self-explanatory like a Bookmarks app. In our example contract, we will maintain a state with arrays of
URLs and their user-defined names.

We are going to use Truffle framework and its template to set up a project structure.
First, we need NPM installed on our local environment. It can be installed through a package manager.
For example, we can use brew on macOS:

brew install node

Now we need to install the Truffle framework:

npm install-g truffle

In my case, I installed Truffle version 5.0.3. Be aware that newer versions may have breaking changes, so that
this tutorial may not work in the future.

The two commands above are not necessary to be executed inside the Bookmarks directory.

Now, let’s use Truffle to create a bare project with all required folders included. Run this command:

truffle init

If the command is executed successfully, then we should have the following file structure in Bookmarks directory:

pragmasolidity>=0.5.0;contractBookmarks{addresspublicowner;Entry[100]publicentries;uintcount;structEntry{stringurl;stringname;}constructor()public{owner=msg.sender;}modifierrestricted(){require(msg.sender==owner,"Only owner can call this.");_;}functiongetBookmarksCount()publicviewrestrictedreturns(uint){returncount;}functiongetBookmarkAt(uintindex)publicviewrestrictedreturns(stringmemory,stringmemory){return(entries[index].url,entries[index].name);}functionaddBookmark(stringmemory_url,stringmemory_name)restrictedpublic{entries[count]=Entry(_url,_name);count++;}functionsetBookmark(uintindex,stringmemory_url,stringmemory_name)restrictedpublic{require(index<count,"index must exist");entries[index]=Entry(_url,_name);}functionremoveBookmark(uintindex)restrictedpublic{require(index<count,"index must exist");entries[index]=Entry("","");count--;}}

Save it to the contract folder with the name Bookmarks.sol.

We are going to use Truffle to compile above contract using the command:

The deployment process in Truffle is called migration. It consists of a folder
with scripted tasks in JavaScript. As we ran truffle init earlier, we got a folder, called migrations.
It contains a default script to deploy Migrations.sol, which is an auxiliary
contract to maintain the state of the latest migration number on the Blockchain. If you’ve ever been
working with a database, this might be familiar. Migration allows to
evolve existing applications and deploy new version of a contract.
It keeps track, which scripts are not yet applied. We will get back to it again later.

The Truffle init command has already prepared a script for a migration contract.
However, we need to add our own contract. This can be done as a separate script.

You might have noticed that we didn’t mention ‘where’ we are going to deploy the contract.
The Ethereum blockchain has several networks to choose from in order to deploy a smart contract. Truffle’s output above also gives a tip on what needs to be
specified to make the migration/deployment successful.

As part of this tutorial, we want to deploy our Bookmarks contract to
the Ethereum test network Rinkeby, using Truffle framework.
To make this happen, we have several options to choose from:

GanacheGanache is one more tool from the Truffle’s suite.
It is a personal blockchain for Ethereum development you can use to deploy contracts,
develop applications, and run tests. It comes with test accounts and fake Ether.
Since our goal is to deploy a contract to the real test network, we won’t go with this option.

Local Ethereum client: Geth or other
Geth (Go Ethereum) is one of the solutions to connect to the main and test Ethereum network.
Geth can be run as an Ethereum full node, which allows to mine new blocks.

InfuraInfura is an API platform, which exposes
JSON-RPC API to connect to the Ethereum network. Basically, Infura, or a similar
platform, is providing an infrastructure, so that one does not need to maintain a local node on its own.

We will go with Geth Local node to be connected to the Ethereum network directly.
However, this would require us to download the whole blockchain from the
very first block up to the current block.

Once it is started, you should see block synchronization messages.
Above command starts Geth in fast mode. This mode makes
synchronization much faster than running a full synchronization. However, this will still
take some time. In my case (2,2 GHz Intel Core i7, SSD disk),
it took less than an hour to sync with entire blockchain.

The property from needs to be set to your account address, which will be
used to make transaction in the Ethereum network.
That means this account needs to have some amount of Ether to deploy the contract
and later interact with it. In case you already have a test Rinkeby account,
just put it in truffle-config.jsnetworks.my_local.from instead of “…”.
Otherwise, follow the two sections below to create an account and request to test Ether.

Do not forget to put the correct account number, which was given by the first command.
Also, replace the pass phrase, which you have used to create an account.

600 is number of seconds for how long this account needs to be unlocked.
It means, that after 600 seconds an account will be locked again.
Make sure to run the next steps, which requires an unlocked account, within this duration.
Otherwise unlock it again, when needed.

Since we have created new account, we need to have some amount of Ether
to deploy a contract and interact with it. Ethereum network provides,
so called faucets to ask for fake Ether for testing purposes.
Go to https://faucet.rinkeby.io and request an Ether using the short
instruction given there. Fake Ether will be transferred to your account within
several seconds, once you post the required HTTP link to a social media account.

The last file index will be saved on the chain in the Migrations contract.
We can see its address in the Truffle logs above and then call a getter
function for the last_completed_migration property.
Right after the initial deployment, this function should reply 2,
because the last file in a sequence of the migrations folder is 2_deploy_contracts.js.
This approach prevents us to run the same scripts again,
if we launch the above migration command. In case we need to deploy
a new contract version, we need to create a new script with a file
prefix = last_completed_migration + 1.
For example, a file with name migrations/3_deploy_contracts.js
would be the next version of our application. Of course, we can copy paste
the previous file.
The Truffle migration API
has a lot of features to control the deployment process, so that we can
script our process in any way we need.

If you have trouble understanding which contract address is the Migrations contract,
and which one is the main application contract after running several
migration per day, you can decompile contract byte code, even online.

There are a couple of options we can choose from to call the deployed contract.
In this tutorial, we will do that programmatically using Truffle console.
One could also work with a contract via IDE like Remix.

Let’s run the Truffle console and call the deployed contract in the Rinkeby test network:

We have developed a new contract from scratch and deployed it to the test
network Rinkeby. Deployment to the main network will be similar,
but we will be using real Ether (i.e. real money) there to create
a contract and make transactions. Our example contract can be improved
a lot in terms of Gas usage efficiency, so that the contract creation and
state modification function call would be cheaper. One of the ideas is to
simply make our internal array a dynamic one, so that we do not need
to create a fixed size array in advance. We could also tackle struct types
to be more space efficient.

Using Truffle framework, we simplified our project creation process,
compilation and deployment. Hopefully, we will see more useful and stable
development tools for Ethereum blockchain in future.

TAGS

Until May 2019, Alexey was a senior consultant at INNOQ with more than ten years of experience in backend application development. His focus and passion is distributed systems, data engineering and functional programming.

I accept the storage and processing of my data in order to receive the monthly newsletter. This acceptance can be revoked via email to info@innoq.com or by clicking the corresponding links in the newsletter emails. I've read the privacy terms and accept them.

I accept the storage and processing of my data in order to receive the monthly newsletter from innoQ Schweiz GmbH. This acceptance can be revoked via email to info@innoq.com or by clicking the corresponding links in the newsletter emails. I've read the privacy terms and accept them.