DEV Community

Cover image for Introduction to Solidity
Ranjith jupaka
Ranjith jupaka

Posted on

Introduction to Solidity

If you are a cocoon to establishing yourself in the web3 garden and have yet to begin to write blockchain smart contracts in Solidity, this is the article for you.

You will understand how to create a basic Solidity program by the end of this article.

Image description

What is Solidity?

Solidity is an object-oriented, high-level, compiled, and statically typed programming language for implementing smart contracts.

That is the basic definition of it.

Now, let us see the meaning of each keyword :

Object-oriented: Object-oriented language is a language that joins various data and functions into an object and encourages the reuse of these objects within the same and other programs. Java and C++ are two examples of object-oriented languages.

High-level: A high-level programming language is a language for writing computer instructions that are easy to understand and similar to human language. Some examples of High-level languages are Java, C, C++, and Python.

Compiled: A compiled language is a programming language where the source code is translated into machine code, and the machine code is stored in a separate file. C and C++ are two examples of object-oriented languages.

Statically typed: Statically typed language is a programming language where the variable types are explicitly declared and determined at compile time. Statically typed nature lets the compiler decide whether a given variable can perform the actions requested from it or not. Some examples of compiled languages are Java, C, and C++.

Smart contracts: A Smart Contract is a piece of code on the Ethereum blockchain. It is a set of functions and state-related data stored at a particular address on the Ethereum blockchain.

Image description

What does it run on?

Solidity code runs on Ethereum Virtual Machine(EVM). Ethereum Virtual Machine (EVM is the runtime environment for Solidity code, just like your browser is a runtime environment for JavaScript code. So, after writing Smart Contract code in Solidity, the compiler converts it into bytecode. The bytecode is then deployed and stored on Ethereum (and other EVM-compatible blockchains).

Image description

The solidity file that stores the solidity code will have a .sol extension.

The Layout of the Basic Solidity file:

The Layout of a basic solidity file is as follows:

  • License Identifier
  • Pragma directives
  • Import directives
  • Contract definitions

A solidity file can contain any number of pragma directives, import directives, and contract definitions.

Let us understand more from the following Solidity smart contract:

/* 1. License Identifier */
// SPDX-License-Identifier: MIT

/* 2. Pragma directive */
pragma solidity ^ 0.8.17;

/* 3. Import directive */
import "./owned.sol";

/* 4. Contract definition */
contract HelloWorld_Contract {
   // 5. State variable 
   string public myString;

   // 6. Constructor
   constructor() {
     myString = "Hello World";
   }

   // 7. Function
   function showMyString() public view returns (string) {
     return myString;
   }
}
Enter fullscreen mode Exit fullscreen mode

License Identifier

A license identifier is a single-line comment that specifies the machine-readable license that covers the solidity code. Machine-readable SPDX(Software Package Data Exchange) license identifiers are used In Solidity. You can declare the SPDX license identifier as follows:

// SPDX-License-Identifier: <License Name>

The license name should be from one of the following in the SPDX license list.

If you do not want to specify a license or if the solidity source file is not open-source, you can use the exceptional value UNLICENSED.

E.g.:

// SPDX-License-Identifier: MIT
Enter fullscreen mode Exit fullscreen mode

The license identifier can be declared anywhere in the file at the file level, but it is best to place it at the top.

Image description

The solidity compiler shows a warning for a solidity file without a license identifier, and the solidity compiler shows an error with multiple license identifiers.

Pragma directive

The pragma directive is used to configure compiler features and checks. The pragma directive is not global and always local to the current file. Pragma from one file does not automatically apply when importing it to another. As a result, you must include a pragma directive in each file for it to work and be applicable across the entire Solidity project.

The pragma directive follows Semantic Versioning (SemVer) - a system where each number signifies the type and extent of changes contained in that version.

In Solidity, there are three types of Pragma as shown below –

  1. Version Pragma
  2. ABI Coder Pragma
  3. Experimental Pragma

Now, not wasting time, let’s get into the details of each section:

Image description

1. Version Pragma

Version pragma directive instructs the compiler on the solidity code version to ensure that the code complies only with the given version or version range of Solidity. Otherwise, the compilation should be rejected.

You can declare the version pragma as follows:

pragma solidity <version>;

E.g.,

pragma solidity ^0.8.7;
// Anything above 0.8.7 is accepted

pragma solidity >=0.8.0 <0.9.0;
// Anything between 0.8.0 to 0.9.0 where 0.9.0 is not included is accepted

pragma solidity 0.8.7;
// Only Version 0.8.7 is accepted
Enter fullscreen mode Exit fullscreen mode

You should note that using the version pragma does not affect the compiler's version. It does not even enable or disable compiler features. It simply tells the compiler to compare its version to the one specified by the Pragma. The compiler throws an error if it doesn't match.

2.ABI Coder Pragma

First, let's understand what ABI is and what ABI encoder and ABI decoder are.

ABI is a shorthand for an Application Binary Interface, which is "an interface between two binary program modules." An ABI allows our smart contracts to access another smart contract's data structures and functions, which run as machine code, i.e., bytecode on an EVM.

Bytecode is a product of the final phase of the solidity compilation process, and it runs very low, directly on the underlying hardware.

Hence ABI definition must provide us with instructions or mapping on how to transform our high-level language access to data structures and functions to communicate with an EVM running the bytecode and reinterpret the EVM's response in bytes back to a high-level language data structure. Translating high-level language calls to bytes and from bytes is called ABI encoding and ABI decoding. ABI encoding and decoding are mostly done automatically by the compilers or wallets, which interact with the blockchain.

ABI coder pragma is a directive that allows you to choose between the ABI encoder and decoder's v1 and v2 implementations. The v2 ABI coder includes nested array and struct types unavailable in v1.

You can declare the ABI coder pragma as follows:

pragma abicoder <abi encoder version (v1 or v2)>

V2 ABI coder is default from solidity 0.8.0; hence pragma abicoder v1 has to be used to work with the old version of the ABI coder.

Example: if you try to create the contract in the solidity version 0.7.0 with struct types which is not supported by default, it throws a compilation error. There are two solutions to this issue:

  • To begin, use the pragma abicoder v2; directive to make the code compatible with ABI Coder v2, which supports struct.
  • Another option is to use Solidity 0.8.0, which by default, implements the v2 ABI coder.

Image description

3. Experimental Pragma

Experimental Pragma allows us to enable previously disabled features of a compiler or the Solidity language. A notable, still experimental pragma in this regard is the SMTChecker component. More information is available here.

You can enable it as follows:

pragma experimental SMTChecker;

Import directives

Solidity provides import directives to help you modularise the source code. In Solidity, the import directives are very similar to javascript (from ES6 on), Except Solidity does not support the concept of a default export.

You can import other files into your solidity file using the below syntax:

Import <file name>;

Where is an import path of a file containing some helpful code, e.g., a library.

An import statement of this type would import all global symbols defined in the imported file into the global scope. The same effect can also be achieved with the following syntax:

import * as symbolName from "filename";

and

import "filename" as symbolName;

Image description

There are two ways to import:

1. Local Imports

You can import local files in the same folder or from external folders in Solidity, as shown below.

For files in the same folder

Image description

You can import file2.sol in file1.sol in this case as follows:

import './file2.sol';

For files in the different folders

Image description

You can import file2.sol in file1.sol in this case as follows:

import "./folder/file2.sol";

2. Import Through Github

For importing solidity contracts from GitHub.You need to copy the GitHub URL pointing to the contract and paste it after import as follows:

// https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/mocks/ MockAggregator.sol

import "https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/mocks/ MockAggregator.sol";
Enter fullscreen mode Exit fullscreen mode

Contracts definitions

Contracts are a collection of states and functions deployed on the blockchain at a specified address. Contracts in Solidity are equivalent to classes in object-oriented programming languages.

Image description

Contracts can even inherit from other contracts. There are also particular kinds of contracts called libraries and interfaces (These will be covered detailedly in upcoming blogs).

You can declare a contract as follows:

contract <contract name> {}

E.g.,

contract HelloWorld_Contract { }
Enter fullscreen mode Exit fullscreen mode

Each Solidity Contract has declarations of

  • State Variables
  • Functions
  • Function Modifiers
  • Events
  • Errors
  • Struct Types
  • Enum Types

State Variables

The state variables are declared outside a solidity function, inside a contract, and permanently stored on the blockchain.

Here is an example of a State variable declaration:

string public myString;
Enter fullscreen mode Exit fullscreen mode

Let us break down the state variable declaration:

  • String: specifies solidity datatype, which stores a set of characters.
  • Public: Indicates variable is accessible by other contracts
  • myString: specifies the variable name

The above state variable initialization is as follows:

myString = "Hello World";
Enter fullscreen mode Exit fullscreen mode

Constructor

A constructor is a special function. In Solidity, a constructor is an optional function that initializes state variables in a contract and is executed only once upon contract creation.

Here is an example of a contract declaration that initializes the above state variable:

constructor() {
     myString = "Hello World";
   }
Enter fullscreen mode Exit fullscreen mode

Image description

A contract can only have a single constructor. If there is no constructor, the contract will use the default constructor, which is equal to

constructor() {}
Enter fullscreen mode Exit fullscreen mode

Function

In programming, a function is a piece of code that performs a specific task. Functions are code components encapsulated within a single object.

In Solidity, the “function” keyword is used to define a function.
The following is an example of a function declaration:

function showMyString() public view returns (string) {
     return myString;
   }
Enter fullscreen mode Exit fullscreen mode

Let us break down the function declaration.

  • showMyString: specifies the function name
  • public: which signifies that other contracts can access the function.
  • view: indicates that the function does not change data on the blockchain.
  • returns: indicates the data types returned by the function.
  • string: specifies the data type of the returned value.

Comments in Solidity

Comments are notes added to the program to provide explanatory information about the source code. The compiler ignores comments. Solidity accepts C and C++-style comments.

Without comments, your code will be like this:

Image description

Comments types in Solidity are as follows:

  1. Single-line or inline comments
  2. Multi-line or block-line comments

You can declare a single-line comment as follows.

// This is a Single Line Comment
Enter fullscreen mode Exit fullscreen mode

You can declare a Multi-line comment as follows.

/*
This is A Multi-Line Comment 
*/
Enter fullscreen mode Exit fullscreen mode

NatSpec or Documentation comments

Solidity contracts can use a unique form of comments to provide rich documentation for functions, return variables, and more. This unique form is named the Ethereum Natural Language Specification Format (NatSpec).NatSpec comments can be single-line or multi-line.

Single-line comments start with /// and can contain tags such as @title,@author, and @dev as shown below:

/// This is NatSpec Single Line Comment
/// @title: Title of the contract
/// @author: Author Name of the contract
/// @dev: Developer notes about contract code and what it does
Enter fullscreen mode Exit fullscreen mode

Multi-line comments begin with /** and end with */ and can contain tags.

/** This is NatSpec Single Line Comment
line 2
line 3*/
Enter fullscreen mode Exit fullscreen mode

That's all for today, folks! Did I miss any topic in this article? Make sure to leave a comment below and let me know!
I hope you learned something new today, and don't forget to connect with me on social media.

See you in the next Solidity article in this series!!

Follow me on LinkedIn if this content added any value to you. 💙

Image description

Top comments (0)