How to write and deploy first smart contract in Solidity 0.5.x and Truffle 5.x.x
If you want to start your adventure with the Solidity language, first you need to set up an essential development environment for creating smart contracts. We will use Truffle version 5.0.6 and Solidity 0.5.0.
1. Setting up smart contracts environment
1.1 Node.js and npm installation
Node.js is installed in a package with npm and can be downloaded from https://nodejs.org/en/.
If you do not remember whether you already have Node.js and npm, you want to check the version or make sure that the installation has been carried out correctly — run the console command:
node -v
npm -v
1.2 Truffle installation
Truffle is the most popular framework for Ethereum. To install Truffle globally on your computer run the command in the console
npm install -g truffle
or
sudo npm install -g truffle
Now we can check our Truffle version by running in the console:
truffle version
I’m using right now:
- Truffle v5.0.6 (core: 5.0.6)
- Solidity v0.5.0 (solc-js)
- Node v11.6.0
The latest Truffle version you can check at https://www.npmjs.com/package/truffle.
1.3. Ganache installation
Ganache is a local blockchain network for development purposes. It is convenient to use and it has a friendly interface. You can download it from ganache page.
1.4 Code editor for smart contracts in Solidity
To start coding, you need an editor with an extension for Solidity language, so that you can use syntax highlighting or snippets. Personally, I recommend:
- Visual Studio Code — with the solidity extension (currently I use it),
- Atom — with language-ethereum extension
Of course, you can simply choose your favorite code editor — the most popular have available packages for Solidity, for example:
- Sublime text — with Ethereum extension
More examples of integration you can find in the Solidity documentation.
2. Creating a first smart contract
Our environment for creating smart contracts is prepared, so it’s time to go to the most interesting part and write the first smart contract in Solidity.
We will create a very simple contract “Hello”. Our main assumptions:
- we have three state variables — the name, the age and the Ethereum address of the owner,
- the owner can add/change the name and the age,
- everyone can get the value of state variables.
2.1 Project initiation
First, we create a folder and initiate Truffle there.
mkdir hello-soliditycd hello-soliditytruffle init
If everything goes well, we receive information: Unbox successful. Sweet!
In the folder of our project, we can find now files and folders generated during the initiation. Truffle project structure looks as follows:
Folders:
- contracts — in this folder we place our smart contract files. Currently, there is a contract named Migrations.sol. It was created automatically and is responsible for the migration process in Truffle. Usually, there is no need to modify it.
- migrations — this folder contains the file 1_initial_migartion.js, which is responsible for deploying the Migrations.sol contract. We will add here a file with configuration for our smart contract.
- test — according to the name we place test files here (information on how to write tests will be in one of the next entries)
Files:
- truffle.config.js — Truffle configuration file, where we place settings regarding, among others, blockchain networks that we use, the selected version of the solc compiler, etc. An example configuration is below.
2.2. Truffle configuration — truffle.config.js file
This file contains basic configuration settings allowing for the creation and implementation of smart contracts. It may require minor modification depending on the settings in Ganache. The default network used by Truffle is development. We should check if the port is compatible with the one indicated by Ganache. If not — you should change the port in truffle.config.js to the correct one (or you can change the port in the Ganache settings).
In the truffle.config.js file, you can also choose the version of the compiler (solc) you want to use. In our case, we will set it to 0.5.0.
Due to a Medium issue — the github code is not displayed in Safari. Use a different browser to view all content
2.4 Choosing the compiler version — pragma solidity
In the Contracts folder, we create a new file and call it Hello.sol (extension .sol applies to smart contracts in Solidity). At the very top, we start by specifying the version of the compiler that should be used to compile our file. We use pragma solidity expression.
pragma solidity ^0.5.0;
In our case, this means that the minimum version of the compiler needed to compile our smart contract is 0.5.0. “^” means we can’t use the version higher 0.5.X. If we use the compiler in version 0.6.X (or higher), it through an error. Why? When upgrading to version 0.5.1 or 0.5.7, the changes shouldn’t disrupt our contract running, but in the upgrade to 0.6.X changes can be breaking.
Important! The specific version of the compiler in smart contract inform us what version of the compiler is needed to compile our code. It does not change the version used by Truffle compiler — to do this you need to change the settings for Truffle in the file truffle.config.js
2.5 Smart contract — name and state variables declaration
Now we can finally write our Hello contract. We start with the word “contract” and then indicate its name. In our case, smart contract name coincides with the file name.
In the beginning, inside a smart contract, we start with state variables declarations. Solidity is a statically typed language. First, we define the type of the variable and then its name. In our case, it will be a state variable owner holding the Ethereum address of the contract owner and string name with our name.
pragma solidity ^0.5.0;contract Hello { address private owner;
string private name;
}
In the smart contract we can also define other types of variables:
- bool — logical type,
- int or uint — numeric types,
- contract,
- array,
- struct,
- enum,
- mapping.
More information about data types, you can find in the Solidity documentation.
2.6 Constructor
Below the variables, we define a constructor — function called when deploying a smart contract in a blockchain network. In our constructor, we assign to the “owner” the Ethereum address which called deploy. This is “msg.sender” that determine the sender of the current message. The constructor is optional. We do not need to use it in our smart contract if we do not want our contract to perform any activities immediately after creation.
constructor () public {
owner = msg.sender;
}
2.7 Types of visibility (public, private, external, internal)
There are four visibility types: public, private, external and internal. We have to specify the type for all variables and functions. For simplicity, assume that in our smart contract all variables are private (it does not mean that they are invisible to other users of the blockchain), and all functions are public. The Solidity documentation precisely explains all types.
2.8 Smart contract functions
In our contract, we will create the following functions:
- setName — sets a new value to the variable name
function setName (string memory _name) public {
require (msg.sender == owner, “You are not the owner!”);
name = _name;
}
- getName — gets the value of the variable name
function getName() public view returns (string memory) {
return name;
}
- sayHello — gets your greeting text
function sayHello()
public
view
returns (string memory, string memory)
{
return (“Hello Solidity! My name is:”, name);
}
For functions that do not modify any states — in our case, they will be getName() and sayHello() — we add the “view” type after the visibility type.
In addition, we specify a data location for the function parameters (passed or returned by the function):
- memory — its lifetime is limited to a function call,
- storage — the place where the state variables are stored,
- calldata — the location of special data.
Our first smart contract is ready and looks like this:
Due to a Medium issue — the github code is not displayed in Safari. Use a different browser to view all content
3. Compiling and deploying smart contract. Implementation on the local Ganache blockchain
3.1 Adding a smart contract migration file
In the migrations folder, we create a new file named 2_deploy_contracts.js where we define the smart contract that we want to deploy during migrations. In our case, where we have one smart contract, the content of this file will look like this:
var Hello = artifacts.require (“Hello.sol”);module.exports = function (deployer) {
deployer.deploy (Hello);
};
3.2 Smart contract deployment
First of all, we need to make sure that our local blockchain network — Ganache is running. Then we go to the console and run the command:
truffle compile
In this way, we check whether our smart contract compiles correctly. If everything is correct, we see will such a message:
We can check now that in the location of our project, build folder was created, during compilation. We can find there also contracts folder, containing compiled versions of our smart contracts in .json format.
If everything compiles correctly, we can deploy our smart contract to our Ganache blockchain using:
truffle migrate
This command starts migrations to run the deployment process. As a result, we receive information about the correct migration. We can find there, among others address of our smart contract.
During the work on a smart contract in a local network, I often use the command:
truffle migrate --reset --compile-all
It causes that after smart contracts modifications, we force to recompile and migrate all of the contracts (not only those with changes) — this command sometimes helps to avoid emerging errors.
3.3 Interactions with the smart contract
To communicate with our smart contract, we will use the Truffle console. We run it with the command:
truffle console
Now the truffle (development) mode should appear in our console (to exit we use ctrl+c).
In the beginning, we save the instance of Hello contract in the app variable:
Hello.deployed().then((instance)=>{app = instance;})
Now, by entering the app in truffle console, we can display our smart contract instance.
Then we add our name to the state variable name:
app.setName(“Paulina”)
We check the result of this operation by calling our next function getName ()
app.getName()
We got the value of our name, so now we can say hello to Solidity:
app.sayHello()
and we receive
Great job! We have just created and deployed to the blockchain simple smart contract. If you have any question, feel free to leave a comment.