Learn how to build a simple smart contract on Ethereum and how to test it using Truffle framework

*This tutorial is targeted to beginner audience and Do not use this code/pattern in a production setting. Also, look into more in Solidity’s common patterns*

Today, we will learn how to build a simple smart contract on Ethereum and how to test it using Truffle framework. Our smart contract will perform basic create, read, update, delete (CRUD) operations.

Table of Contents

  • Quick definitions
  • Building a smart contract with CRUD operations
  • Testing CRUD smart contract using Truffle (Part 2)

Quick Definitions

**What is Ethereum? — **Ethereum is an open source smart contract platform on which you can build decentralized applications (Dapps).

**What is Solidity? — **Solidity is one of the most famous language to code smart contract on ethereum. It is designed for smart contract programming. It’s syntactically similar to javascript.

**What is a smart contract? -**In simple words, A smart contract is a piece of code which controls some kind of digital asset. It defines rules for transferring asset and penalties like a traditional contract. The best thing is that it automatically perform these transfers and penalties based on pre-coded conditions without a need for a middleman.

Building a smart contract with CRUD operations

Our smart contract is very simple and basic in nature. It will store countries, their leaders and population.

Fun Fact— “According to the United Nations & the CIA World Fact Book, there are 195 Countries recognized by the World.”

It can be optimized but the mantra is 👇

        Addy is Eng. manager at Google and works on Google chrome project

So let’s dive in.

                                                      curdApp.sol

For convenience I have added our CRUD Smart contract above now we will go through the code and understand different aspect of our CrudApp and basic solidity language programming.

Think of a ‘contract’ as a ‘class’ in other programming languages.

Pragma — It specifies which compiler version should be used. This only works after solidity version 0.4.0.

Solidity Data Types

Struct — Using struct keyword you can define structures in Solidity. A structure is a user-defined data type that can be used to group items of possibly different types into a single type. Our structure will store country related properties.

  • name
  • country
  • population
struct country{string name;string leader;uint256 population;}

We are using strings to store country name and their leader’s name and uint256 datatype to store the population of the country. We are storing our countries in an Array. (Where we’ll perform all our CRUD operations)

uint256 public totalCountries;
function CurdApp() public{totalCountries = 0;}

We are using a variable to track the number of countries and then initializing it on the constructor with 0.

Events- With the help of events, we can utilize EVM’s logging facility. Use eventkeyword following the event name and parameter to define events. We have defined 3 events for the operations which modify our stored.

event CountryEvent(string countryName , string leader, uint256 population);
event LeaderUpdated(string countryName , string leader);
event CountryDelete(string countryName);

Create Operation -

Now let’s look at our insert function which is storing new countries.

function insert( string countryName,string leader,uint256 population)publicreturns (uint256 totalCountries){country memory newCountry = country(countryName , leader, population);countries.push(newCountry);totalCountries++;emit CountryEvent (countryName, leader, population);return totalCountries;}

This function taking 3 parameters and returning a number of total countries after completing the function.

We didn’t add basic checks, add them and comment your code on the response.

Operations and Storage are costly on ethereum. So we are declaring a temporary struct with the use of memory keyword then we will push it on countries array which we defined above. After that, we log our event using emit keyword. That’s it a simple straightforward creation of our first entry.

Read operation —

Now we want to read what we have stored. So let’s read countries data using country name. Our function simply iterates through entries and returns details if a positive match found.

function getCountry(string countryName)publicviewreturns(string name , string leader , uint256 population){for(uint256 i =0; i< totalCountries; i++){if(compareStrings(countries[i].name, countryName)){return (countries[i].name , countries[i].leader , countries[i].population);}}revert('country not found');}

Revert() — Ethereum operations take gas (ether) to run, so we need to optimize that. Revert function check condition and revert unused gas to the user. They should be used at the start so your function will use less gas.

revert(‘Something bad happened’);

Solidity provides two more functions assert() and require(). But discussing them is out of scope for this tutorial. You can find an awesome write us about it here.

View modifier- Above, we added in view modifier in function. By adding view, we simply mean that function is not modifying any state and just reading the current state. In other words, it’s a read-only function.

Solidity has a bunch of modifiers and you can also create your own modifiers. Here’s a list of conditions for a statement to be considered as “modifying the state”:

  1. State variables being written to.
  2. Events being emitted.
  3. Other contracts being created.
  4. Self-destruct being used.
  5. Ether being sent via calls.
  6. Calling functions that are not marked view or pure.
  7. Low-level calls being used.
  8. An inline assembly containing certain opcodes being used

Update operation -

Now let’s update our countries data. For example, we want to change Trump with Hilary 😜.

function updateLeader(string countryName, string newLeader) public returns (bool success){//This has a problem we need loopfor(uint256 i =0; i< totalCountries; i++){if(compareStrings(countries[i].name ,countryName)){countries[i].leader = newLeader;emit LeaderUpdated(countryName, newLeader);return true;}}return false;}

It’s taking 2 parameters and running a loop to find the country in our countries array. If there is a positive match, It replaces the leader with your input leader.

Same way, you can create an _updatePopulation_ function and comments on the response.

Delete Operation —

Now let’s look at delete operation. In our delete we are removing the country which user wants and replacing it with last entry in our countries array.

function deleteCountry(string countryName) public returns(bool success){require(totalCountries > 0);for(uint256 i =0; i< totalCountries; i++){if(compareStrings(countries[i].name , countryName)){countries[i] = countries[totalCountries-1];delete countries[totalCountries-1];totalCountries--;countries.length--;//emit eventemit CountryDelete(countryName);return true;}}return false;}

Other functions-

We have created some other functions too. One of comparing the string and other for giving the length of our array.

function compareStrings (string a, string b)  internal pure returns (bool){return keccak256(a) == keccak256(b);}
function getTotalCountries() public view returns (uint256 length){return countries.length;}

If you followed till now, let do some google search too. Respond in comments why we used keccak256() while comparing two strings?

In next part we will test out CRUD smart contract with help of truffle framework.

Notes & suggestions -

Smart contract controls assets, so they should be designed carefully and should follow a minimalistic approach. They should be properly audited in a production scenario for controlling assets. Smart contracts are the trust central of a decentralized app and the autonomous part of the system.

Blockchains are not just a database. Blockchain maintains a global state. Every change has to reflect on every node participating in the network, so changes are costly.

In the above tutorial, we used basic CRUD operation. Our crud design has few weak points, optimize it and let us know in the comment section. Operations are costly on Ethereum and you should minimize them while coding a smart contract.

On To Part 2…