Solidity Smart Contract Tutorial With Code Examples

This is the only Solidity smart contract complete tutorial with code examples that you would ever want to see and practice without any help. We have explained all the concepts of building smart contracts in Solidity with defining each use-case. By the end of this post you will be able to write any smart contract on Solidity and deploy it immediately on IPFS or Swarm or check and check it.
Before writing on the blockchain or pushing it on IPFS make sure it’s compiled and errorless.

This Solidity programming tutorial has been divided into 2 parts. This is the first part where we have tried our best to explain every small detail that is used for coding Ethereum based smart contracts to be used publicly and verified on the blockchain when an event or a function has been called.

In the next post we will explain other Solidity code examples with real-time functionality and real-time use of receiving and sending cryptocurrency or talking to other smart contracts etc.

What is Solidity?

Here is how our basic Solidity smart contract goes. We need to understand some basics about the Solidity programming language before digging deep. So the first thing is Solidity is a Turing complete programming language. We can use Solidity literally however we want for dApps. Some of the use-cases include using it for writing smart contracts about DeX, NFTs and different other tools including trading bots etc.

Please note we have used only Remix IDE and the code examples are 100% accurate with zero errors. We have not used hardhat, ganache or truffle at this point to test the transactions. This Solidity smart contract post is just to give enough information to the beginners that it’s the easiest programming langauge on the planet and literally this is all you need to know.

There are few important things that we need to add in our smart contracts written in Solidity. First of all let’s move to remix.ethereum.org – a publicly available IDE to write our smart contract. The next comes the structure of our smart contracts. All the codes examples in this tutorial to write you beginner-to-professional Solidity smart contract are verifable at Solidity Docs.

#1 Basics of A Solidity Smart Contract

The first thing that we need to do is to assign our smart contract a name– let’s call it MyContract. We must mention in our Solidity Smart Contract the GPL – or public license at the top of every contract.

// SPDX-License-Identifier: GPL-3.0

Now we have to mention the version of Solidity we are using. Like I have shown here:

pragma solidity >=0.8.2 <0.9.0;

Now we have to mention our smart contract name. Like we have chosen the name MyContract for that which we would mention in our new smart contract with the arbitrator.

 contract MyContract {
//write code here
}

Now we would put all of our smart contracts code in these curly brackets here. Everything would go in these curly brackets. So that’s all about the initial important aspects of a smart contract.

#2 Data Types in Solidity Smart Contract

Now we have to understand the data types we will use in our smart contract. We have to add strings, variables, state-variables and functions. We would add all the necessary functionality in the later part of this post. Here is how our smart contract looks now:

// SPDX-License-Identifier: GPL-3.0


pragma solidity >=0.8.2 <0.9.0;


contract MyContract {
//we will write code about our smart contract here  
}

As far as the Solidity data-types go, we need to understand that Solidity is statically typed language so we are bound to declare the data-type for our smart contract when we are to add strings, variables and functions, we have to declare them and the type should not change at all as we will use state-variable.

Now We Have to Declare The Data-type

Now we are declaring the datatype “string” and “myString” as the state variable (it also means we have added this value into the blockchain). Here is how our smart contract looks now:

// SPDX-License-Identifier: GPL-3.0


pragma solidity >=0.8.2 <0.9.0;


contract MyContract {
   string public myString = "My string"
  
}

You notice we have also added “public” to make this smart contract public and anyone can see it on the blockchain and view different values added in it. It’s more like open-source technically.

There are also other variable-types that we can add such as Boolean, UnsignedIntegers, Integers and Addresses. (They are all types of State Variables) Like this:

// SPDX-License-Identifier: GPL-3.0


pragma solidity >=0.8.2 <0.9.0;


contract MyContract {
   string public myString = "my string"
   bool public boolean1 = true,
   uint public myUint = 1;
   int public myInt = 1;
   address public myAddres = here goes ethereum wallet/metamask address;


}

#3 Functions in Solidity Smart Contract With Code Example

“There are two types of functions used in the blockchain– Write Function and Read Function. So when we have to write a function we have to pay a gas fee to write it to the blockchain while we can use the read function completely free. “

Next we will learn how to add functions in our Solidity Smart Contract. Without adding some functionality there’s no point writing a smart contract. There must be some function.
In our smart contract we would use functions such as “setName” “getName” or “resetName”. So we declare them “public” ; anyone can see these functions if we use “internal” , which means it’s supposed to be seen only in our smart contract. I have shown the example below:

pragma solidity >=0.8.2 <0.9.0;


contract MyContract {
   string name = " Example 1";


   function setName(string memory _name) public {
       name = _name;
   }
   function getName() public view returns(string memory) {
       return _name;
   }
   function resetName() internal {
       name "Example 1"
   }


}

One thing you noticed: we have used our functions visibility internal at one place. There are three ways to use visibility of function in Solidity smart contract:

string name1 = “Name 1”; = No visibility
string private name2 = “Name 2”; = Can be seen inside a smart contract
string public name3 = “Name 3”; = Can be seen inside outside a smart contract
string internal name4= “Name4”; = Visibility is internal but it can be inherited

So these are the code examples:

contract MyContract {
   uint public count;


    function increment1() public {
        count = count + 1;


    }
    function increment2() public {
        increment1();
    }
    function increment3() private {
        count = count + 1;
    }
    function increment4() public {
        increment3();
    }
    function increment5() external {
        count = count + 1;
    }
    function increment6() public {
        increment4();
    }

}

#4 Function Modifiers

Solidity has a set of built-in modifiers within functions that we can use to customize our smart contract and set the rules. See the example below:

contract MyContract {
   string public name = "Example 2"
   uint public balance;


   function getName() public view returns(string memory){
       returns name;
   }


   function (add uint a, uint b) public pure returns(uint){
       returns (a + b);
   }


   function pay() public payable {
       balance = msg.value;
   }

For instance in the function getName() public view returns(string memory). Its state is public with a view which means someone can view the name (state variable) but cannot modify it.

In the next function (add uint a, uint b) public pure returns. Its state is set to public pure which means no one can read or modify the state such as state variable (name).

In the 3rd function pay() public payable – It means anyone is allowed to pay publicly. The message and value will be generated about the amount and address.

The functions can also be customized and the owner is allowed to do that in order to receive amounts in crypto-currency. They are called custom modifiers. We can add the specifics about it in the smart contract. The best example is trading bots where the owner is allowed to customize them accordingly.

#5 Constructors

So the constructors are also special functions which can be used once in the smart contract where the smart contract goes live on the blockchain they are represented by the keyword constructor. Here is the code example in our smart contract for that:

pragma solidity >=0.8.2 <0.9.0;


contract MyContract {
   string public name;


   constructor(string memory _name){
       name = _name;
   }


}

You can see we also add other arguments like other functions such as payable any other way we want to. There is only one thing to remember about constructor function— it can only be called once.

#6 Global Variables

There are also some global variables that we must take into notice in order to make our smart contract workable professionally. Here is the code example for that:

pragma solidity >=0.8.2 <0.9.0;


contract MyContract {
   address public contractAddress;
   address public payer;
   address public origin;
   address public amount;


   constructor() {
       contractAddress = address(this);
   }
   function pay() public {
       payer = msg.sender;
       origin = tx.origin;
       amount = msg.value;
   }
}

You can see here we have mentioned contractAddress = address(this); so when we say (this) then the smart contract uses the address of the smart contract to receive crypto currency. We have also added additional functionality to it:

Function pay has msg.sender (It’s the person who’s make the call for this function)
Origin = tx.origin (Means where the transaction has taken place or originated)
Amount = msg.value (it shows the amount of cryptocurrency added in the transaction by the person who has called the function.
In the below we will show more functionality detailed about this transaction:

contract MyContract {
   address public contractAddress;
   address public payer;
   address public origin;
   address public amount;


   constructor() {
       contractAddress = address(this);
   }
   function pay() public {
       payer = msg.sender;
       origin = tx.origin;
       amount = msg.value;
   }
   function getBlockInfo() public view returns (uint, uint, uint) {
       return(
       block.number
       block.timestamp
       block.chainid
       )


   }
}

You can see in the next function we have shown how block info is generated and made public with other details such as:
block.number(it tells the block number on the blockchain which has generated this transaction)
block.timestamp( the time when the transaction was generated)
block.chainid( the id of the blockchain)

#7 Operators in the Solidity Smart Contract – The type of math used in the Solidity Smart Contracts

So many people ask how much math is involved to code smart contracts in Solidity. Let’s review operators or mathematical operations involved in Solidity. These operators have “+, -, x, /, exponents, modules, increment, decrement and so on so forth. We have shown the Solidity code example to see how operators (maths is used in Solidity):

contract MyContract {
   function add(uint a, uint b) external pure returns(uint) {
       return a + b;
   }
   function sub( uint a, uint b) external pure returns(uint) {
       return a - b;
   }
   function div(uint a, uint b) external pure returns(uint) {
       return a / b;
   }
   function mul(uint a, uint b) external pure returns(uint) {
       return a * b;
   }
   function exp(uint a, uint b) external pure returns(uint) {
       return a ** b;
   }
   function mod(uint a, uint b) external pure returns(uint) {
       return a % b;
   }
   function decrement(uint a) external pure returns(uint) {
        a--;
        return a;
   }
   function increment(uint a) external pure returns(uint) {
        a++;
        return a;
   }


   }


}

In the above example you can see we have shown how simple mathematical operations are added and called upon. We are adding more operators below but these are the basic “+, -, \, *, increment and decrement etc. use-cases. All the possible operators have been shown. We are showing their pure functionality here so you could understand how they actually function if you are exceptionally new to basic mathematics.

function mathExample(uint a) external pure returns(uint) {
       uint a;
       a = a + 1; //1
       a++; //2
       a = a * 2 //4
       a = a** 2 //16
       a = a / 2 //8
       a = a - 2 //6
       a--; 2 //2
       return a;
   }

You can see how each of these mathematical operations works in the Solidity smart contracts.
Here are some more examples of mathematical operations:
When the value is equal == which could be return as true/false

contract MyContract {
   function eq(uint a, uint b) external pure returns(bool) {
       return a == b;
   }

When the value is not equal !=

 function notEq( uint a, uint b) external pure returns(bool) {
       return a != b;
   }

When the value is greater than

contract MyContract {
   function gt(uint a, uint b) external pure returns(bool) {
       return a > b;
   }

When the value is less than “

contract MyContract {
   function lt(uint a, uint b) external pure returns(bool) {
       return a < b;
   }

When the value is greater than or equal to “>=”

   function gtorEq( uint a, uint b) external pure returns(bool) {
       return a >= b;
   }

Less than or equal to “<=”

   function ltOrEq( uint a, uint b) external pure returns(bool) {
       return a <= b;
   }

And when the both things are true “&&”

   function and( bool a, bool b) external pure returns(bool) {
       return a && b;
   }

When one of the two is true “||”

   function or(bool a, bool b) external pure returns(bool) {
       return a || b;
   }

When something is not true “!=”

   function not(bool a, bool b) external pure returns(bool) {
       return a!=;
   }

Some operations which do not contain integers such as:

contract MyContract {
   function checkAddress() external pure returns(bool) {
       address address1 = 0X00000sender;
       address address2 = 0x00000receiver;
       return(address1 == address2);
   }

#8 Conditionals

We can always use operators with conditionals for “If Else” conditions. See the code example:

contract MyContract {
   function evenOrOdd1(uint x) external pure returns (string memory){
       if (x % 2 == 0) {
           return "even";
       } else {
           return "odd";
           }
   }
   function evenOrOdd2(uint x) external pure returns (string memory){
       if (x % 2 == 0) {
           return "even";
       }
       return "odd";
   }
   function evenOrOdd3(uint x) external pure returns (string memory){
       return x % 2 == 0 ? "even": "odd";
   }

So you can see different uses of if else statements and how they are used. In the last function evenOrOdd3 it’s further exemplified how we can use both.

#9 Arrays

Arrays are also used in Solidity. They are basically lists of data used in coding. We have shown examples of Arrays below and how they are used in Solidity smart contracts. They are denoted by using “[]”

contract MyContract {
    uint[] public array1 = [1, 2, 3];
    uint[] public array2;
    uint[10] public array3;
    string[] public array4 = ["cow", "camel", "ox"];
    string[] public array5;
    string[10] public array6;

}

These are the examples of using Arrays with initializing the data type and also with or without values.
We can demonstrate arrays by various methods depending on the type we are using. Here are few more examples:

We can read from Arrays if they are public to see the value out of “i” index:

contract MyContract {
   uint[] public array;


   function get(uint i) public view returns (uint) {
       return array[i];
   }

We can make the length public and everyone can see it like:

   function length() public view returns (uint) {
       return array.length;
   }

We can add the new element using push as shown here:

   function push(uint i) public {
       array.push(i);
   }

We can use array.pop to remove the last element. As shown below:

function pop() public {
       array.pop();
   }

We can also delete an element from an specific index as shown here:

function remove(uint index) public {
       delete array[index];


   }

#10 Mapping in Solidity Smart Contracts

One of the easiest ways to store information in smart contracts is by the method of mapping. These value pairs work like associated arrays or hash-tables in other languages.

Like other programming language in Solidity we use keys with associated value pair. Such as:

mapping (uint => string) public names;

In the above example you can see we declared mapping “uint =>string” as key and value to save names.
There are other related examples for saving other informations that we have shown here:

contract MyContract {
   mapping (uint => string) public names;
   mapping (uint => address) public addresses;
//saving blockchain addresses
   mapping (address => uint) public balances;
// balances by mapping address corresponding to number uint
   mapping (address => bool) public hasVoted;
//voting etc. in bool which can be true/false
   mapping (address => bool) (uint => bool) public myMapping;
//nested mapping of addresses
}

Here are some examples of manipulation values inside or outside the smart contract to add, remove values or set to default.

contract MyContract {
   mapping (uint => string) public myMapping;


   function get(uint _id) public view returns (string memory) {
       return myMapping [_id];
   }
   function set(uint_id, string memory _value) {
       myMapping [_id] = _value;
   }
  function remove(uint _id) public {
      //default value is restored
      delete myMapping(_id);
  }

#11 Struct

We can also construct our own types with Struct by passing value pairs. We can easily use our own data for that to declare and define them. See the code example for struct we are creating the record items on the store:

contract MyContract {
   struct Store {
       string item;
       string buyer;
       bool completed;
  
   }

Now we will add the value which defines the details of items on the store with necessary details.

 /array of items on store
   Store[] public stores;


   function add(string memory _item, string memory _buyer) public {
       stores.push(Store(_item, _buyer, false));
   }

Now we will call the function to see if the data is stored and check it:

function get(uint _index)
   public
   view
   returns (string memory item, string memory buyer, bool completed)
   {   
   Store storage store = stores[_index];
   return (store.item, store.buyer, store.completed);
   }

We will mark the store update complete by adding the function and making it public:

//finalizing the details about store
   function complete(uint _index) public {
       Store storage store = stores[_index];
       store.completed = true;


   }

#12 Solidity Events

Solidity allows users to subscribe to the events and know about them any time any function has been called. It’s more of a push notification where once we allow them we get updated regarding the changes made or the event is emitted.

contract MyContract {
   string public message = "Hello World";


   event MessageUpdated(
       address indexed _user,
       string _message
   );


   function updateMessage(string memory _message) public {
       message = _message;
       emit MessageUpdated(msg.sender, _message);
   }


}

There are particular events that we can subscribe to or code them and emit them for others. So whenever that event has been called the subscriber gets the notification. You can see there could be address indexed _user, these are the details. These events are viewable on blockchain.

#13 Native Cryptocurrency (ETHER)

Solidity has native cryptocurrency Ether which is divisible by 18 decimal places. Its smallest unit is Wei which is divided ether by 18 decimal places. However, Gwei is the unit which is used most commonly to pay for the gas on Ethereum blockchain. You can see more about it on Eth-Converter.

We can send or receive Ether by using its payable function with other values such as msg.sender and the amount of Ether sent.

We can code that into our smart contract if the send/receive needs to be invoked when the transaction is conceded and the sender/receiver gets notified.

This is the first part of creating solidity smart contracts within less than an hour. In the next post we will talk about how we can handle errors, interface, adding transaction values and communicate with smart contracts by creating our own smart contract and adding required functionality to it.

Please let’s us know in the comments for feedbacks on this Solidity tutorial which is the only solidity programming tutorial for coding your beginner-to-pro smart contract in a single go.

 

Part 2 COMING SOON!