Solidity Basics

Solidity Basics

A comprehensive guide to Variables, Datatypes, Functions, Conditional & Looping statements.

Variables in solidity

As we know, variables are temporary storage containers in any programming language. Similarly, in Solidity there are 3 types of variables:

  • local variables

  • global variables

  • state variables

  1. local variables: these are temporary variables used to perform operations as long as a function runs inside a program. Their scope of accessibility is within the function and they exist as long as the function is being executed.

  2. Global variables: these are universal variables in simple terms. they are of fixed values or keep changing with the global state of blockchain on which the contract is running. Some examples are the Block height, timestamp of a block etc..

  3. State variables: these are the variable stored in the blockchain that preserves the state of contract on the blockchain. they are declared outside a function and they are accessible in all of the functions in the contract.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Variables {
    // State variables are stored on the blockchain.
    string public text = "Hello";
    uint public num = 123;

    function doSomething() public {
        // Local variables are not saved to the blockchain.
        uint i = 456;

        // Here are some global variables
        uint timestamp = block.timestamp; // Current block timestamp
        address sender = msg.sender; // address of the caller
    }
}

Constants & Immutables in Solidity

Both of These values cannot be modified in the contract after they are assigned with a value. they are hard coded in the program.

Both of them have a key difference:

  • Constants are assigned a value during the declaration itself. i.e. its value is known in advance at the time of creation of contract.

  • Immutables are assigned with values during the deployment of contract. i.e. its values are uncertain during the contract creation for eg, the contract owners address.

๐Ÿ’ก
Usage of constants & immutables saves gas fees. However, immutables are more gas efficient.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Constants {
    // coding convention to uppercase constant variables
    address public constant MY_ADDRESS = 0x777788889999AaAAbBbbCcccddDdeeeEfFFfCcCc;
    uint public constant MY_UINT = 123;
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Immutable {
    // coding convention to uppercase constant variables
    address public immutable MY_ADDRESS;
    uint public immutable MY_UINT;

    constructor(uint _myUint) {
        MY_ADDRESS = msg.sender;
        MY_UINT = _myUint;
    }
}

Operators in Solidity

  • addition (+)

  • subtraction (-)

  • multiplication (*)

  • division (/)

  • modulus (%)

  • exponential (**)

  • unary +, -, *, /

  • ternary [?:]

Datatypes in solidity

Like any other programming language solidity also has various datatypes for numerical and string data. The primary datatypes of solidity are:

  • uint/ int(signed int)

  • string

  • bytes

  • bool

  • address

On the other hand, there are some complex datatypes in solidity which holds group of data of above datatypes. They may/ may not hold heterogeneous data. some of them are:

  • arrays

  • mapping

  • struct

  • enum

Fundamental/ primary data types

  1. uint: uint stands for unsigned int.

    1. it is used to store numerical data.

    2. holds only positive integers.

    3. also has subtypes like uint8, uint16, uint34, uint64, uint128, uint256. each of them have constraints on the size of data they hold.

    4. uint/ int without any specified size is equivalent to uint256.

    5. uint8 holds values from 0 to 2**8-1. Similarly, uint256 holds 0 to 2**256-1.

    6. in most of the cases in programming we use uint256 only.

    uint public myInt= 25;
  1. int holds -ve numbers also.

    1. int256 holds values from -2**255 to 2**255-1.
    int public myInt= -10;
  1. String: it is used to hold string data

    1. enclosed in single or double quotes

    2. solidity doesn't provide built-in operators or functions for concatenating 2 strings. they are converted into byte arrays and stored in a new byte array which is inturn converted into string. this will be discussed later.

    string wish= 'Hello world!';
  1. bytes: used to hold character data in the form of bytes

    1. bytes32 holds a max of 32 characters sequence
    bytes32 myBytes='hello';
  1. bool: is used to hold true/ false values.

     bool myBool= true;
    
  2. address: is used to hold wallet adresses, typically of the form '0x...'.

address myAddress= 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;
๐Ÿ’ก
solidity doesn't support float point numbers
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Primitives {
    bool public boo = true;

    /*
    uint stands for unsigned integer, meaning non negative integers
    different sizes are available
        uint8   ranges from 0 to 2 ** 8 - 1
        uint16  ranges from 0 to 2 ** 16 - 1
        ...
        uint256 ranges from 0 to 2 ** 256 - 1
    */
    uint8 public u8 = 1;
    uint public u256 = 456;
    uint public u = 123; // uint is an alias for uint256

    /*
    Negative numbers are allowed for int types.
    Like uint, different ranges are available from int8 to int256

    int256 ranges from -2 ** 255 to 2 ** 255 - 1
    int128 ranges from -2 ** 127 to 2 ** 127 - 1
    */
    int8 public i8 = -1;
    int public i256 = 456;
    int public i = -123; // int is same as int256

    // minimum and maximum of int
    int public minInt = type(int).min;
    int public maxInt = type(int).max;

    address public addr = 0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c;

    /*
    In Solidity, the data type byte represent a sequence of bytes. 
    Solidity presents two type of bytes types :

     - fixed-sized byte arrays
     - dynamically-sized byte arrays.

     The term bytes in Solidity represents a dynamic array of bytes. 
     Itโ€™s a shorthand for byte[] .
    */
    bytes1 a = 0xb5; //  [10110101]
    bytes1 b = 0x56; //  [01010110]

    // Default values
    // Unassigned variables have a default value
    bool public defaultBoo; // false
    uint public defaultUint; // 0
    int public defaultInt; // 0
    address public defaultAddr; // 0x0000000000000000000000000000000000000000
}

Derived datatypes

the data types that make use of primary datatypes for holding more complex data/ to perform complex operations are called derived datatypes.

  1. Arrays: container that holds homogenous data.
uint[2] ints= [1,2]; //fixed size array
uint[] integerarr= [1,2,3]; //dynamic size array
string[] strarray=['hello','hi'];
bool[] boolarr= [true, false, true];
address payable[] myAddresses= 
[payable(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4),
payable(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4),
payable(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4)];

uint[] numbers;
numbers.push(5);
numbers.push(10);
numbers.push(15);
  1. mappings: this is similar to a dictionary in python. it holds data in the form of key-value pairs.
mapping (uint => string) public myMap;
myMap[1]='ram';
myMap[2]='sam';
  1. struct: this is similar to struct in C programming. it holds/ encapsulates multiple attributes of different datatypes.
struct person{
uint id,
string name,
uint age,
bool hasLicense
};

person p1= person(1,'ram',25,true);
p1.name;    //ram
  1. enum: an enum (short for "enumeration") is a user-defined data type that consists of a set of named values, which are typically used to represent a finite set of closely related options or states. Enums are often used to improve code readability.
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract DaysOfWeek {
    enum Day { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }
    Day public currentDay;
    constructor() {
        currentDay = Day.Sunday;
    }
    function nextDay() public {        
        if (currentDay == Day.Saturday) {
            currentDay = Day.Sunday;
        } else {            
            currentDay = Day(uint(currentDay) + 1);
        }
    }
}

//uint(currentDay) returns the index in enum. for eg, Sunday returns 0

Conditional statements

Like any other programming language, solidity also has conditional flow statements like:

  • simple if

  • if-else if- else

  • nested if-else

  • switch case is not available in solidity

  1. simple if, if-else if- else, nested if-else:
if(condn1){
    if(condn2){
        //do somenthing
    }
    else if(condn3){
        // do something
    }
    else{
        //do something
    }
}
else{
    if(condn4){
        //do something
    }
    else{
        //do something
    }
}

Looping statements

solidity also has looping statements like all programming languages

  • for loop

  • while loop

  • do-while loop

  • continue

  • break

  1. for loop
for(uint i=0; i<=5;i++){
    //do somehting
if(i==3)
break;
}
  1. while loop
uint i=0;
while(i<5){
//do something
i++;
if(i==2)
continue;
}
  1. do-while loop
uint i=0;
do{
i++;
//do something
}while(condn1);

Functions

As we know functions are useful for modularity of code i.e. a single block of code can be used repeatedly without re writing it through simple function calls.

in solidity, a function may be a mutating function or a read-only function. If it is a read only function, we only fetch the existing value on the blockchain, we do not make any modifications to the state variables, hence it doesn't charge any gas fees.

a read-only function is specified by 'view' keyword.

In mutating functions, we will make changes to the state of blockchain, hence it is an expensive operation, it charges gas fees.

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract FunctionExample{
    uint myVar;
    constructor(uint value){
        myVar= value;
    }
    //read-only function
    function getValue() public view returns(uint){
        return myVar;
    }
    //mutating function
    function setValue(uint value) public{
        myVar= value;
    }
}

As all of these concepts are familiar in other programming languages like Java, C, I concluded each concept in the article precisely. In future individual concepts like string functions will be discussed if required.

๐Ÿ’ก
Solidity supports both pass by value and pass by reference in parameter passing.

pass by value creates a separate copy of the variable we are passing in the function call. This allows your function to modify the value without worrying that the value of the initial parameter gets changed.

we use memory key word for specifying pass by value parameter

function eatHamburgers(string memory _name, uint _amount) public {

}

In Solidity, functions are public by default. This means anyone (or any other contract) can call your contract's function and execute its code.

Obviously this isn't always desirable, and can make your contract vulnerable to attacks. Thus it's good practice to mark your functions as private by default, and then only make public the functions you want to expose to the world.

uint[] numbers;

function _addToArray(uint _number) private {
  numbers.push(_number);
}

This means only other functions within our contract will be able to call this function and add to the numbers array.


Keywords covered in the article

  • mapping

  • constant

  • struct

  • payable

  • address

  • function

  • for

  • while

  • do-while

  • enum

  • immutable


Follow & Connect ๐Ÿค—

๐Ÿ‘‰ Github

๐Ÿ‘‰ Linkedin

๐Ÿ‘‰ Website


Comments & Suggestions would be appreciable ๐Ÿค—

ย