Truffle Suite – Ethereum developer toolbox: Truffle.

Truffle Suite is the tool pack dedicated to Ethereum developers (focusing on smart contracts). That very actively developed project is currently one of the most popular frameworks for implementing, testing and running Ethereum based decentralized applications.

In this article:

  • I will describe the Truffle Suite tools;
  • I will describe and use the main tool of the suite – Truffle (name of the tool is the same as suite name);
  • I will initialize example project Pet Shop – implementing first features and corresponding tests;

Truffle Suite

Truffle Suite currently consist of 3 components dedicated for Ethereum developers. These are:

  • Truffle – the tool dedicated to creation Ethereum based project structure. It creates the basic folders structure, it manages the dependencies, allows to implement automated tests and finally to run the the code.
  • Ganache – personal, local Ethereum blockchain (the simulator). It allows to run implemented contracts (and tests).
  • Drizzle – the collection of frontend libraries which makes dapps UI development easier.

These tools are collectively the suite because all together they improve and help development of all the layers of decentralized application (the smart contract layer which is backend, and UI – the frontend). These tools must be installed in operating system what makes the impossible to use in web code editors. Truffle Suite (except Drizzle) is similar to Remix IDE, or newer Ethereum Studio which also allow to edit, compile and run smart contracts. The benefits of using Truffle Suite is simply the possibility of using own choice IDE and possibilities in the space of automation and scripting (for example automated testing or compilation).

Truffle Suite currently consists of 3 components for developers: Truffle tool, Ethereum blockchain simulator – Ganache and frontend libraries for dapps development – Drizzle.

Truffle tool – what’s the purpose?

truffle

Truffle is the main tool of the Truffle Suite. Its functionalities allow for extensive Ethereum based project development. It structures the project improving the maintainability. It also allows testing and running the contracts, including complex deployment scenarios. So far it’s experimental but you can even debug smart contracts using Truffle. This tool is the framework of smart contracts development – the model of using the tool and maintaining the project is set and fixed. The project initialized with that tool consists of:

  1. contracts catalog – where the smart contracts source code files are stored.
  2. migrations catalog – it contains the migrations files. Migrations are the instructions of compiling and running (to the blockchain) smart contracts. They makes the compilation easy, especially when we talk about large projects which consist of multiple files and dependencies (for example other contracts which are already loaded in the blockchain network).
  3. tests catalog – where the automated test files are stored. Truffle allows to implement tests using Javascript or Solidity.

This tool is based on Node.js which is why dependencies management is based on npm. Project configuration files and the migration definitions are based on Javascript.

Installation

The installation uses npm. In order to install the tool in the Linux system, simply run:

npm install truffle -g

It’s possible that it must be run with sudo (it depends of OS configuration).

Part of the Truffle tool package is also the Solidity compiler this is why there is no need to additionally install it. After the successful installation truffle command should be available.

How it works? Let’s initialize the Pet Shop project

Truffle has kind of library of already prepared projects (called boxes), which can be used by developers. These already prepared and setup projects can be useful when we develop the dapp having similar functionality to the example project or when we have similar technology stack. This box will have all dependencies set what makes less work for developer. The boxes list has already over a dozen of projects. 

Example Truffle boxes projects can be used as a base for own project.

Having Truffle installed it’s possible to download and extract box project. Installation is simply based on invoking the command:

truffle unbox pet-shop

This particular command downloads the example Pet Shop project. The structure of this project opened in the IDE is given (Intellij used with Intellij-Solidity plugin):

petshop-project-structure
Pet Shop project structure which is the example box project available in Truffle.

Project has the described previously folders structure. By default Truffle is dedicated to Solidity smart contracts however it’s possible to download Vyper programming language based project.

Currently there is only 1 contract Migrations.sol and 1 migration Javascript file 1_initial_migration.js. These 2 files together create the mechanism of compilation and deployment of the project so should not be deleted.

Smart contract

The smart contract being the logic of developed Pet Shop is in the single file (I created the file contracts/Adoption.sol). Its code is given:

pragma solidity ^0.5.0;

contract Adoption {
    address[16] public adopters;

    function adopt(uint petId) public returns (uint) {
        require(petId >= 0 && petId <=15);
        adopters[petId] = msg.sender;
        return petId;
    }

    function getAdopters() public view returns (address[16] memory) {
        return adopters;
    }
}

Contract defines the array which can store 16 address type elements. Has 2 public functions: adopt and getAdopters.

The function adoptchanges the inner state of the contract by doing the logic of ‘adopting’ – assigning the address of function caller to the array under the given index petId. The second line of this function restricts the possibility of assigning the value to the array index beyond the correct index (array has 16 elements so it can store values under index 0-15). The lack of this secure mechanism would be really serious flaw and bug. The function returns the value of parameter which also accepts (petId). It uses 8 bit unsigned integer type – because we store quite small value it’s appropriate type to use.

The function getAdoptershas the keyword view in its declaration. The viewfunctions indicate that the logic of the function doesn’t change the inner state of the smart contract. It means it’s impossible to assign the value to any contract fields. Trying for example to move logic from adoptfunction to this function returns given compilation error: TypeError: Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable.

Compilation of the contract is simply invoking the command:

truffle compile

Invoking the command causes the contract compilation – the build catalog will be generated. The folder includes .json files, the file per contract. These files contains among the others: compiled contract bytecode, ABI (Application Binary Interface) and some other data which enable Truffle to run tests and interact with contract from test environment.

Migration

The Adoption contract migration code is in the file I’ve created migrations/2_deploy_contracts.js. The code is given:

const Adoption = artifacts.require('Adoption');

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

Truffle is based on Node.js this is why we can use requirekeyword in order to “import” the contracts/Adoption.solcontract and assign it to Adoptionconstant variable. The migration is quite simple because Adoption contract has no dependencies.

Defined migration can be now invoked (what will cause loading contract to the blockchain). It’s done by invoking the command:

truffle migrate

The result of the command is printed on the console and contains the information about the successful migration, in particular: the hash of contract deployment transaction or the gas cost. The Truffle network configuration by default recognizes the Ganachesimulator running. Configuring the Ethereum testnet is defined in truffle-config.js.

Tests

The implementation of automated tests using Truffle is based on 2 options:

  • tests using Javascript (or Typescript) – in that scenario the test engine is Mocha, assertion library is Chai;
  • tests using Solidity – the mechanism of Truffle allows to implement which are smart contracts running in the same blockchain environment where the contract being tested. This implies the direction communication between test contract and tested contract;

Javascript tests based on popular technology stack will be probably good choice for developer who is already familiar with that language and the stack (JS/Mocha/Chai). I also think that JS tests are beneficial in the sense of testing correct conversion of types between Solidity and Javascript, having in mind that implementing true dapp with web interface is based on Javascript (web3.js).

The benefits of using Solidity based contracts is the minimalistic approach of these tests (very few dependencies) and complexity of the project. Everything what needed is already provided by Truffle – the tests initialization mechanism and assertion libraries. Also what I believe is that writing Solidity more is always good way to learn the language and the technology overall.

Testing the contracts in Truffle, no matter of the testing technology of choice is always the interaction directly with smart contract (running in blockchain). Before starting tests the contract is loaded to the network (e.g. testnet network or Ganache). Because of that, these are not unit tests for whose the result of invocation is the code processing in isolated local environment. What’s worth to mention that every test invocation causes reloading the tested contract to the network (it’s also truth for Solidity based contracts tests). In fact this makes tests running in “isoloated” environment however only because this integration with blockchain – these tests cannot be described as unit tests. And once again: because tests run in the blockchain, you should better be careful testing on e.g. Ethereum testnet (where the deployment is simply “gas” cost).

Truffle gives possibility to implement automated tests using Javascript (Mocha/Chai) and Solidity. The tests interact directly with smart contract running in blockchain (for example in testnet or Ganache).

The following code is the example simple test contract (implemented in Solidity) for the Adoptioncontract features. It tests 2 functions from Adoption:

pragma solidity ^0.5.0;

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/Adoption.sol";

contract TestAdoption {

    Adoption adoption = Adoption(DeployedAddresses.Adoption());
    uint expectedPetId = 8;
    address adopterId = address(this);

    function testShouldAdoptCorrectlyAndReturnExpectedAdoptionId() public {
        //when
        uint returnedId = adoption.adopt(expectedPetId);

        //then
        Assert.equal(returnedId, expectedPetId, "Returned adoption ID should match expected id!");
    }

    function testShouldReturnCorrectAdopters() public {
        //when
        address[16] memory adopters = adoption.getAdopters();

        //then
        for (uint i = 0; i< adopters.length; i++) {
            if (i == expectedPetId) {
                Assert.equal(adopters[i], adopterId, "Expected adopter address under adopted pet id!");
            } else {
                Assert.equal(uint(adopters[i]), uint(0), "Expected no adopter!");
            }
        }
    }
}

The code is quite hermetic, and 2 imports and the beginning initialize the test and deliver all required assertions. The test contracts names in Truffle must start with the Testprefix and test functions must start with testprefix. Running the test (what requires configured blockchain network running) is simply:

truffle test

Summary

Growing Ethereum ecosystem continuously delivers more and more tools dedicated for developers. Truffle, the main tool of Truffle Suite is the framework for implementation, testing and running Ethereum smart contracts. Open source, price (Truffle is a free tool), community support, a lot of features and stability – these are at least few of attributes which will be taken under consideration by potential users. It’s worth to have these attributes in mind, especially when developing blockchain solutions. There are of course known software development problems like technical overhead, risk and costs of choosing particular technology but except that, we deal with much more strict approach of immutability of blockchain where the cost of unexpected behavior (or bug) can be really huge.

Do you use Truffle in your projects? Do you know some alternative tools? Have some opinion or you know some fancy feature of Truffle?
Let me know in the comments! Przemek