31/10/2018 Innovation
Industrializing smart contracts with Truffle
This piece is the first of a serie on BlockChain networks. It is aimed for an audience already educated in BlockChain networks and Ethereum Smart Contracts.
Vous pouvez aussi lire cet article en version française.
Ever since the DAO Hack, smart contracts security has become a critical issue in decentralized applications development, especially on the Ethereum blockchain. Industrializing smart contracts is a key step to this security as it allows running unit, functional or integration tests automatically. Once we have an industrialized process, we can implement security testing. We’ll see how we can industrialize our smart contracts using Truffle. We will then be able to systematically validate the edits made to our code, and comply to our quality standards.
Truffle is a project initiated by ConsenSys (Vitalik Buterin’s company). It allows us to interface smart contracts with JavaScript code, and the NodeJS ecosystem. This provides us industrialization tooling coming from the JavaScript world, that we can apply to Ethereum smart contracts.
Truffle provides the following features:
- Dependency management (through NPM or EthPM – Ethereum’s smart contracts package manager)
- Smart contracts compilation
- Migrations
- Testing (2 available modes)
<li style="font-weight: 400;">
With JavaScript, to validate your contracts outside of the BlockChain network
</li>
<br />
<li style="font-weight: 400;">
With Solidity, to validate them from within
</li>
<br />
- Interact with contracts in JavaScript
<li style="font-weight: 400;">
There is a console as well
</li>
<br />
- Manage multiple environments (named networks)
This tooling allows us to setup a classic industrialization process, such as: Build > Test > Deploy
Let’s see how to build this with Truffle.
Setup
First of all, we’ll need a project. Let’s use the one provided by Truffle:
npm install -g truffle ethereumjs-testrpc && truffle init
You should now have a project containing a contracts directory, a migrations directory, a test directory and a truffle.js file.
Build
In order to declare your smart contracts on the Ethereum network, it will need to know of your contracts capabilities. We need to generate a JSON file for each smart contract containing among other things the list of available functions. This file is similar to a header file (.h) in C/C++.
Truffle provides a way to generate this file through the following command:
truffle build
Dependency management
Your contracts or JavaScript code will most likely depend on other packages. Truffle allows us to handle those dependencies easily: once declared in the correct file, you can install them through the truffle install command (for smart contracts dependencies) or npm install (for JavaScript).
To sum up, those are the needed commands to build our app:
npm install
truffle install
truffle build
Note: it might be easier in the long run to handle your dependencies by customizing Truffle’s build process. This will depend on your project, and overrides the truffle build command.
Test
Things get interesting here: indeed, we don’t want to test our code directly on the Ethereum BlockChain, but we’d like to be able to see what’s going on under the hood. That’s why we installed the ethereumjs-testrpc package during the setup: it will allow us to have a local Ethereum network, and check what’s happening in it.
To run it, open a console, and enter the testrpc command. Your network will be locally available (by default through port 8545).
Once launched, you can run your smart contracts tests with the command: truffle test .
Our tests are running, and we can check the testrpc console to see what’s happening.
To summarize: in order to test our application we needed the following commands:
testrpc & (run as a background task)
truffle test
Note: if you need to switch testrpc’s port, it’s quite easy. Run the testrpc commandwith the -p option: testrpc -p 8242 ; then, whithin the truffle.js file, update the port parameter for the development network:
module.exports = {
networks: {
development: {
host: "localhost",
port: 8242,
network_id: "*" // Match any network id
}
}
};
Our application tests being green, we can go to the next step.
Deploy
In a Continuous Integration process, once our tests are green, we can deploy our application to an integration platform (where QA can try it for instance). To do so, we need to declare this environment within the truffle.js file:
module.exports = {
networks: {
development: {
host: "localhost",
port: 8242,
network_id: "*" // Match any network id
},
integration: {
host: "integration.my-dapp.com",
port: 80,
network_id: "*"
}
}
};
Here, my “integration” environment is hosted on a remote server, that we can reach through the “integration.my-dapp.com” address. To deploy our contracts on the environment, we’ll use the following command:
truffle migrate --network integration
This command updates the JSON files for our contracts into this environment, and then executes the migrations (declared within the migrations directory). Here’s what happens on this environment with those migrations:
Gitlab CI integration
If you wish to integrate Truffle within Gitlab CI, here’s a sample .gitlab-ci.yml file which should work with the starting example of Truffle. Ideally, we would have a testrpc service declared within the Gitlab CI configuration, as well as a dedicated docker image to run the tests with Truffle. The process as indicated below is a bit slow otherwise, as we need to install everything each time we run it.
image: alpine:latest # Ideally, a dedicated docker image with Truffle on it
before_script:
- apk add --no-cache nodejs nodejs-npm git python g++ make
- npm install -g truffle ethereumjs-testrpc
stages:
- build
- test
- deploy
build:
stage: build
tags: [ek-docker]
script:
- truffle compile
test:
stage: test
tags: [ek-docker]
script:
- testrpc -p 8242 & # We could also have a service
- truffle test
deploy:
stage: deploy
tags: [ek-docker]
script:
- testrpc -p 8242 &
- truffle migrate --network integration
Here’s the result within Gitlab CI:
So here’s how to industrialize your Smart Contracts projects with Truffle in a few steps. You will now have a systematic validation of your code, and can even deploy it automatically.
Next steps
We can add checks to our process, noticeably in the testing step, such as integrating the static analysis tool Oyente (still in beta). This analysis will increase our confidence in the developed code, by telling us whether we respect coding standards, or have introduced a potential bug within our Smart Contract. It will also check for known security breaches.
Ethereum Smart Contracts and Solidity programming language are still quite fresh. However, having industrialization tooling within the ecosystem indicates that the technology is growing more mature.