Unlock the Power of Solidity: Exploring the Essential Keywords for Smart Contract Development

Solidity is a smart contract programming language built solely to develop smart contracts that can be deployed on blockchains. C++ and JavaScript inspired it, an Object Oriented and High-Level language (HLL), that helps developers define the behaviour and rules for a Decentralized Application (Dapp). Smart contract facilitates autonomous, secure, and efficient transaction execution on the blockchain without needing any intermediary (self-executable) and solidity provides the base framework for achieving the same.

It is essential to understand the common keywords used in solidity to solidify your core understanding of the language so in this article, we’ll pin down some prominent keywords that help us develop these smart contracts by embracing the true power of solidity language.

Table of Content

  • Contract
  • Constructor
  • Data Types
  • Delete
  • Enum
  • Function
  • Interface
  • Import
  • Struct
  • Visiblity Specifiers
  • Exception Handling
  • Pragma Directive
  • License Defintion
  • Modifier
  • Data Location
  • Global Variables
  • Fallback Function
  • SelfDestruct
  • ‘assembly’ and ‘inline assembly’

Contract

The keyword ‘contract’ as indicated by its name is used to define a smart contract.

  1. A smart contract is a self-executing code that consists of the data members to store data, and functions that can be used to interact with it from the outside world of blockchain.
  2. It is similar to declaring a class in any other high-level programming language.
  3. There are two ways to create a contract: From solidity, and from JavaScript Api web3.js.

Example:

The below code creates a contract named ‘GeekContract’, that has a single storage variable named : “sayHello()”

Solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^8.25.0;

contract GeekContract {
    string public message = "Hello Geek";
}

Output:

Contract

Constructor

Constructor keyword is used to create a constructor which is a special type of function that will be executed as soon as the smart contract is Deployed to the chain, and is used to set the initial state variables in the contract and do some initilial startup work.

Note:

Constructor can only be declared using the ‘constructor’ keyword starting from solidity version ^0.6.0. And the old method to do so was using the Contract name which is DEPRECATED now.

Example:

The below contract code will have a public function for the state variable ‘message’ which will contain the string : “This is my first Contract!” and this string will be set on the deployment of this contract on chain.

Solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.25;

contract GeekContract {
    string public message;
    
    constructor(){
        message = "This is my first Contract!";
    }
}

Output:


Constructor


Data Types

  1. address: Stores ethereum address, either a contract address or account’s address.
  2. bool: Stores a true or false binary value.
  3. int or unit: int is a positive or negative value, uint (unsigned integer) is a positive whole number storage type.
  4. bytes: Represnts a dynamic array used for storing arbitrary binary data.
  5. string: It is a data type defined for storing the long sequence of alphanumeric and special characters. Mainly used for storing UTF-8 encoded characters – text data.

Delete

The ‘delete’ keyword is used along with the state variables or structs for resetting their values. It helps in managing the contract state and resources by clearing the data structures values, resetting states etc.

Example:

Solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.25;

contract GeekContract {
    uint256 public myNumber = 10;
    address public myAddress = "Input Valid Ethereum Address here";

    function resetVariables() public {
        delete myNumber; // Sets myNumber to 0
        delete myAddress; // Sets myAddress to address(0)
    }
}

Explanation:

  1. This code declares two public variables : myNumber = 10, and myAddress which will contain a valid ethereum address.
  2. Once the resetVariables() function is called, it will reset the values of these storage variables value to their default values.

Enum

The keyword ‘enum’ is used to declare an enumeration type consisting of only some of the selected pre-defined values that are called ‘enumerators’.

  1. It restricts a variable type to have only certain set of pre-defined values.
  2. It can be defined inside a contract itself.

Example:

Solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.25;

contract TransactionState {
    // * Defined enum type with 3 enumerators : active, pending, failed
    enum State {active, pending, failed}
}

Explanation:

  1. The above code simply defines an enum type ‘State‘ inside a ‘TranscationState‘ contract. It has 3 enumerators : active, pending and failed.
  2. You can assign these values to variables of type State.

Function

A function is a set of code statements that are executed when a function is called from the inside (from another function) or outside of the smart contract.

1. The keyword function is used to declare a function followed by the function name, parameters it takes (wrapped in a parenthesis), visibility specifier like public, private, external or internal, type of function, return type (if any). Below is an example of function signature:

function functionName(parameter1 ….. parameterN) visibilitySpecifier modifier returns(datatype) () { // Code Logic Here }

2. Function Modifier:pure’ is to prevent modification or state access, ‘view’ is for reading the state but preventing any modification, and ‘payable’ is so that functions can receive ethers when called. We’ll learn more about these later in the article.

Example:

Solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.25;

contract GeekContract {
    string public message;
    
    constructor(){
        message = "This is my first Contract!";
    }

  // Reset message variable
 function sayHello ()  public {
    message = "Hello Geek";
 }
}

Explanation:

The above code is an extension of previous code, we’ve just added a new function named ‘sayHello’ which resets the value of message variable to “Hello Geek” when called.

Output:


Function


Interface

The ‘interface’ keyword is used to declare an interface in solidity for providing a declaring for functions that will be implemented by smart contracts.

  1. Interfaces increase code reusability, readability and also promotes interoperability as they can be used in any contract.
  2. Interfaces are a collection of function declarations (without the function definition) that will be given its implementation in the implementing classes and cannot contain anything else (like variables or modifiers)
  3. They cannot inherit from other contracts but other interfaces.
  4. All declarations functions MUST be external in the interface even if they’re public
  5. Unlike contracts, they don’t have a constructor.

Example:

Solidity
interface MyToken {
    // Function Declarations
    function transfer(address _from, address _to) external returns (bool);
   function balanceOf(address account) external view returns (uint256);
}

Explanation:

Above is an interface declared named ‘MyToken’ this interface can be implemented by any contract using inheritance’s ‘is‘ keyword.

Inheritance – ‘is’ keyword

In the context of Solidity, Inheritance refers to the property of once smart contract to acquire properties of another smart contract. The ‘is’ keyword is used for two purposes:

  1. For inheriting smart contract.
  2. For implementing interfaces.
  3. Below is an example for implementing interface (Same can be done for another contract).

Example:

Solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.25;

interface GeekToken {
    // Function Declarations
    function transfer(address _from, address _to) external returns (bool);
   function balanceOf(address account) external returns (uint256);
}

// GeekContract implements the GeekToken interface
contract GeekContract is GeekToken {
    uint256 public balance;

    function transfer(address _from, address _to) external override  returns (bool) {
       // * Transfer logic
       return true;
    }

    function balanceOf(address _account) external override returns (uint256) {
        // BalanceOf Logic
        balance = _account.balance;
        return balance;
    }
}

Explanation:

  1. You might encounter some warning as for simplicity we haven’t implemented the logic
  2. ‘GeekToken’ is an interface, implemented by ‘GeekContract’ named contract and its overriding the functions present in the interface, by utilising function type keywords such as – ‘override’

Output:

Inheritance

Import

Import statements are nothing but extracting and accessing a piece of code that exists somewhere outside the current file. In solitidy, we can import from two places:

  1. External Solidity Library
  2. Another file in our same project

Example for External Solidity Library:

import “@openzeppelin/contracts/token/ERC20/ERC20.sol”;

Example for Importing from another file:

import “./MyOtherContract.sol”;

Explanation:

This imports the File named “MyOtherContract”.

Struct

‘struct’ keyword is used to declare a structure that consists of various different data types. It is used to declare a new ‘type’ in itself like a custom data type.

Example:

Solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.25;

struct Geek{
      string name;
    uint16 age;
      address addr;
}

Explanation:

  1. The above code declares a new type called ‘Geek’ which has 3 fields : name, age and addr.
  2. This type can be used to create variables of type Geek, and organized Geek’s Data.
  3. Note that this code will not generate any output because its a structure not a contract.

Visiblity Specifiers

Visibility specifiers are analogous to the access specifiers or modifiers in object oriented languages, they define the visibility and accessibility of the function or variables.

  1. public variables and functions are accessible from everywhere.
  2. external functions are only callable from external world outside the contract.
  3. internal functions and variables are accessible in current and inherited contracts.
  4. private variables and functions are accessible only in the current contract.

Example:

Solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.25;

contract GeekContract {
    
    function externalFunction() external  {
        // can only be called from the outside
    }

    function internalFunction() internal {
        // Only accessible in this contract and child contracts
    }

    function privateFunction() private  {
        // Accessible only in this contract
    }

    function publicFunction() public   {
        // Accessible Everywhere!
    }

}

Output:

Visibility Specifier

Explanation:

As you can see, only the public and the external functions are visible in the output. Because private & internal functions are accessible on the contract, and the sub-contracts respectively.

Exception Handling

The exception handling mechanism in solidity is defined for handling cases when the error is made on the user’s end like invalid inputs, or even validate a condition.

  1. revert: Used when we want to revert the state of smart contract back to how it was, in case exception conditions arise.
  2. required: It enforces a condition satisfying mechanism to ensure a certain condition is met before a piece of code is executed. (Input validation mechanism)
  3. assert: unlike revert and required, assert is used to pre-enforce conditions. Suitable for conditions that should NEVER Occur.

Pragma Directive

Solidity and Blockchain is an ever evolving space, that’s why many updates and breaking changes are made very often compared to any other technologies that’s why it offers this feature to avoid compatibility issues.

  1. Pragma is a directive that is followed by the version selection operator ‘^‘ and the version number. It defines the solidity compiler’s version that this code will be compiled on.
  2. It helps avoid compatibility issues as updates are made frequently.

Example:

pragma solidity ^0.8.25;

This defines that the smart contract will use solidity version >= (greater than equal to) 0.8.25.

License Defintion

It is used to specify the license version under which the code will be distributed (made available to everyone). Every license has their own set of protocols for right to use, code modification, copy writing guidelines etc. Solidity has some of the popular license under : SPDX (Software Package Data Exchange), Apache License, MIT License, GPL & LGPL etc.

Example:

Solidity
// SPDX-License-Identifier: GPL-3.0

Explanation:

The above code defines that the given source code will be licensed upon the GPL (General Public License) version 3.0 which gives the user the right to use, modify, study and distribute as well.

Modifier

In Solidity, modifiers are special type of functions that helps us add some extra functionality to the existing functions. You can define a modifier by using keyword ‘modifier’ followed by its name, and parameters it may take.

  1. Modifiers helps restrict access, add additional conditions to the existing functions without rewriting the entire function, saving extra lines of code.
  2. You can apply multiple modifiers to a function and pass parameters to the modifiers.

Example:

Solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

contract Counter {
    uint256 public count = 0;
    address public owner;

      //  Modifier definition
    modifier onlyOwner {
        require(msg.sender == owner, "Only owner allowed");
        _;
    }
    //  Modifier definition
    modifier valueGreaterThanZero(uint number) {
        require(number > 0);
        _;
    }

    constructor() {
        owner = msg.sender;
    }

    function increment() public onlyOwner {
        count++;
    }


    function customIncrement(uint256 digit) external onlyOwner valueGreaterThanZero(digit)   {
        count += digit;
    }
}

Output:

Initially, before calling the customIncrement method:

Before calling

After calling the customIncrement method:

After Calling

Data Location

In solidity, for effective memory management we can decide where to store the variables based on their nature or existence duration.

  1. There are mainly two types of data location : ‘storage’ and ‘memory’.
  2. Storage : Storage variables are persistent and are stored permanently on the blockchain, and also require more gas fee. These are similar to class data members in OOPs.
  3. Memory variables are temporary and are stored temporarily, they are destroyed as soon as the function execution finishes. Mainly used in the function parameters.

Example:

Solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.25;

contract GeekContract {
    // Storage Variable - message
    string message;
    
    constructor(){
        message = "This is my first contract";
    }
  
    // return type is a memory variable, not stored permanently
    function sayHello ()  public pure returns  (string memory) {
     return 'Hello Beginner!';
     }    
}

Explanation

  1. The above code has one storage variable : ‘message’ which is stored permanently on the blockchain
  2. And the return type is of memory type data location, indicating that it is there temporarily.

Output:


Data Location


Global Variables

Some variables are facilitated for accessing the global state of the blockchain :-

  1. msg: for accessing the sender address, amount of ethereums received etc.
  2. block: for accessing meta data like timestamp, hash, difficulty, number of the block etc.
  3. tx: Represents the current transaction and can be used to access the initial sender, and the gasprice cost.

Fallback Function

Fallback function is a special type of function in solidity that is called when either condition is met :-

  1. A non-existing function is called. Example : function fun() is called from within the contract, which was never defined inside the contract’s code.
  2. It doesn’t take any parameters but must be marked as external and payable
  3. If ethers are sent without any function data (information regarding which function to invoke)

SelfDestruct

  1. It helps clearly define the contract’s exact purpose and can be used to introduce a loophole or honeypot in the contract, indicating its vulnerability.
  2. Example: After certain amount of ethers are collected, then it will first call a transfer function to transfer all the ether to another address and then self-destruct like it never existed.

Note:

This function is DEPRECATED starting from Cancun Hardfork, but we can still use it but it will NOT Destroy the underlying opcode in the blockchain but only transfer the ethers to the owner.

Example:

Solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.25;

contract SelfDestructExample {
    address public owner;

     // Set the contract deployer as the owner
    constructor() {
        owner = msg.sender;
    }

    // Function to destroy the contract and transfer remaining ether to the owner
    function destroy() public {
        require(msg.sender == owner, "Only the contract owner can destroy the contract");
        selfdestruct(payable(owner)); // Self Destroy the contract and transfer remaining ether to the owner
    }
}

Explanation:

  1. The given code is just an example and it would be required to implement the functionality to collect ether, so that they can be transferred to the owner upon calling selfdestruct function
  2. The above code will transfer the remaining ether in the contract to the owner and will self destroy and remove itself from the blockchain.

Output:


SelfDestruct


‘assembly’ and ‘inline assembly’

Both the keywords are typically used when we’re trying to define assembly level bytecode for the EVM (Ethereum Virtual Machine) directly.

  1. Used for code optimization.
  2. It requires technical expertise and advanced solidity EVM knowledge.
  3. Assembly language code can be written in the assembly block inside a function like below:

Example:

Solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.25;

contract AssemblyContract {
  // Function defining the assembly block
    function assemblyFunction() public pure {
        assembly {
            // Assembly code here
        }
    }
}

Explanation:

The function defines an assembly block where you can directly write assembly code.