The Basic Solidity Guide
Tags: web3, solidity, blockchain, guide
Published: 2022-06-25 02:06:21

## Introduction 
As a web developer venturing into learning new languages is only a necessity, and one of the key features that make up a developer.
deeming the rise of the new iteration of the internet (web 3), solidity has proven to be one of the primary and essential tools for developers transitioning into the space of web3.
In this tutorial You'll learn all the fundamentals to get you started with understanding the basics of solidity, You'll be able to read smart contracts and make reasonable analyses of what's going on 🤔?

## Solidity and Smart Contract 

When transitioning into a new language, it is only logical to assume that you must have made all necessary research as to what and how a language scales in the real world, and also the kind of problem they solve.
This tutorial is not aimed to make you an expert, but rather to give you a clearer picture of the basics of Solidity and get you started with the real-world practice... A quick recap
## What is Solidity
Solidity is an object-oriented programming language used to build smart contracts that run on the Ethereum blockchain.

For a better recommendation for mastery, check out the Solidity Documentation that stands as a sure guide over your course of learning.

## What is a Smart Contracts
The smart contract is a set of computational instructions executing transaction protocols that are deployed on a decentralized blockchain like (Ethereum)...
they are immutable or incredibly hard to change once deployed due to consensus and 
they are automatically executed

 
## Getting Started
Unlike other languages, you can always specify the version of solidity you want to use with a line of code, which you'll see often beginning with every smart contract

```solidity
pragma solidity <version number>;
```

Where the version number is the specific version of solidity you want to compile your code.

Note: If you don't want to use a specific version, you can specify a minimum version number by adding the caret (^).

For example, the code below means the smart contract can compile with the solidity version 0.8.0 and above,

```solidity
pragma solidity ^0.8.0;
```
but without the caret (^) sign, it uses the 0.8.0 specifically. 
```solidity
pragma solidity 0.8.0;
```


## Initializing the smart contract
Every smart contract begins by defining the contract with the keyword `contract` or `library` followed by the name of the contract which can be anything.
```solidity
contract  <ContractName> {
}
```
For Example:
```solidity
contract  FirstContract {
}
```
Any code written in the brackets above will be the context of the contract `FirstContract`.

**Libraries** `library`: are similar to contracts, but only you cannot declare any state or send ether transactions. Libraries are embedded into the contracts, only if all the library functions are internal. They help to add more functionalities to different values.
They are created just like contracts but with the keyword `library`.
```solidity
library  <ContractName> {
}
```
For Example:
```solidity
library  AnotherContract {
}
```


## Types and Variable Declaration
Just like every other programming language, Solidity also supports primitive data types as such:
`uint` `int` `address` `booleans` `bytes`,
just like other languages, they are used to define variables.
The format of which variables are declared in solidity is
```solidity
<type> <variable name> = <value>;
```
when you initialize a variable without adding a value the, its value is automatically assigned as 0;

**Unsigned integer**`uint`: Similarly to the unsigned data types in `SQL` they carry only positive numbers.
```solidity
uint linesOfCodeWritten = <positive numbers>
```
this means that the variable `linesOfCodeWritten` can only be assigned a positive value.
For example: 
```solidity
uint256 linesOfCodeWritten = 150
```
when using the `uint` type, you can also declare a specific byte range if you're certain about its value size, an example: `uint8` for 8 bytes or uint32 for 32 bytes, 
but without specification, it'll automatically be declared as `uint256`.
 
**Integers** `int`: They are the opposite of `uint` because they carry signed integers which include positive and negative numbers, but similarly to the `uint` they are be prespecified in size, `int16` for 16 bytes or `int64` for 64 bytes  
```solidity
int codeLineAdded  = 10
// unsigned integer
```
and will also be automatically declared as int256 when size is not specified.
```solidity
int codeLineRemoved  = -10
// signed integer
```

**Boolean** `bool`: They simple define the type `true` or `false`. 
```solidity
bool  hasWrittenCode = <true> or <false> 
```
which means the variable `hasWrittenCode` is defined as a boolean that can either be assigned the value `true`
or `false`.

**Address **`address`: These are special 20byte types in the format: `0xAb098b54332Ae1Fd23Bf0e7ac83aADD123456789` 
used to interact with the blockchain, and are declared with the keyword `address`.

**Strings** `string`: They are used to define words or phrases, using the `string` keyword and adding quotes around its value.
```solidity
string yearsOfWorking = "fifteen";
```
**Bytes** `bytes`: These are special types, they are similar to strings since they are also used to store text types and are used the same way, but they also allow you to prespecify their size.
`byte4` for 4 bytes or `byte32` for 32 bytes string.
```solidity
bytes32 name = "Phensic"
```
their maximum and default byte size is byte32

**Comments** are any kind of primitive type but cannot be executed or compiled as codes. Single line comments are written by adding `//` at the beginning of the line, while multiline comments are written as`{/* code here */}`. 
```solidity
// single line comment 
{/* 
code line here 
code line here 
code line here 
*/}
```


### Basic Functions
**Functions** in Solidity, like every other language are self contained modules that execute a subnet of code or instructions when they are called. Using the keyword `function` in the format:
```Solidity
function <function name>(<variable1>, <variable2>) public returns (<output type>) {
<subnet of code instructions>
}
```
To create a function using the format above, that modify the uint variable `linesOfCodeWritten` after adding and removing a few lines of code.
```solidity
function codeEddited (uint256 _codeAddded, int _codeRemoved) public {
uint newLineOfCode = linesOfCodeWritten  + _codeAdded - _codeRemoved 
}
```
the `returns` keyword in the format is not compulsory when creating a function, but is used to predefine the type of output expected to be returned from the function. 

### Visibility Specifier 
Unlike the `returns` keyword, the visibility specifiers like `public` are compulsorily added and are used to determine where a function can be called and accessible.

**Public** `public`: means the function can be accessed outside the current contract. When used, it creates a getter function or a state variable.
```solidity
function yourName public () {
string name = "Phensic"
}
```
the public function above can be called outside the contract and will return the value of the `variable` name 
denied in the function.

**Private** `private`: When used? they can only be accessible inside the contract, and they can be used to declare a variable or function.

**External** `external`: They are only visible and accessible externally and can only be used for function.

**Internally** `internal`: They are only visible and accessible internally.

**Note**: the underscore (_) is usually added as a naming convention for creating function variables.

### Mapping Function
Mapping is a data structure that has keys mapped to a single variable. They are special types of functions similar to dictionaries because can they assign variables to values by looping through an array.
using the keyword `mapping` in the format:
```solidity
mapping (<from type> => <to type>) public <function name>{
}
``` 
 The mapping function `nameToAge`:
```solidity
mapping (string => uint256) public nameToAge{
}
``` 
created can be used to map a set of `string` variable types to a set of `uint256` variable types.

And to use the function, you can call the `nameToAge` mapping function like this:
```solidity
function addPerson(string memory _name, uint256 _age) public{ 
      people.push(People(_age, _name));
      nameToAge[_name] = _age;
}
```
the new `public` function `addPerson` uses the mappping function `nameToAge` to loop through the `people` array and map the variable `_name` to the variable `_age`.

**Note**: Functions created using the keyword `view` or `pure`, simply means they disallow you to modify the state of the function, but you can only read their states from the blockchain. 

### Arrays & Structs
**Structs** in Solidity are used for creating new types by adding the keyword `struct` before the name of the type you want to create. 
```solidity
struct <type name> {
<variable1> ;
<variable2>;
} 
```

```solidity
struct People {
uint256 age;
string name;
} 
```
the `struct` keyword Is used to create a new type `People` that has two variables names, `age` and `name` in the code above.

```solidity
People public person({
age: 20
name: Phensic
});
```
the code above creates a new variable `person` with the type `People`:

**Arrays** takes the use of a struct farther by using it to create a list of objects in the same format used to create the `person` variable but adding a square bracket after the type name `[]` to declare the array;

```solidity
People[] public allpeople
```
To reset an array of objects.
```solidity
people = new People[] {0};
```
### Dynamic and Fixed arrays:

**Dynamic** arrays are declared by default without adding an integer in the bracket, which means you can add as many lists as you want.

**Fixed** arrays are declared by adding an integer in the bracket, which means you cannot exceed a specific number of a list-objects.

Writing a function that adds to an existing array of type `People`would look like:
```solidity
function newPerson(string memory _name, uint256 _age) public {  
people.push(People(_age, _name)); 
}
```

### Memory Calldata and Storage
If you've noticed the keyword `memory ` used in a few functions earlier, they are keywords used to declare where and how a variable should be stored in solidity.
There are 6 storage specifiers, `stack`, `memory`,   `storage`, `calldata`, `code` `log`.


**Memory** `memory`: is used to declare temporary variables that can be modified, which means they will only exist during the time of the transaction.
For example:
```solidity
function newPerson(string memory _name) public {  
string yourName = _name
}
```
the variable `_name` declared as a `string` with the `memory` keyword means that it will only exist in storage at the time of a transaction.

**Calldata** `calldata`:  are used to declare temporary variables that cannot be modified, they are like constants but are also temporary since they only exist at the time of the transaction.
```solidity
string name = "Julius"
function newPerson(string calldata _name = "Phensic") public {  
_name = "Julius"
}
```
the code above will give an error because you cannot modify a variable stored in the`calldata`.

**Storage** `storage`:  all variables declared by default are stored in the storage, they are permanent (can exist even after the transaction time), and can be modified. 

**Note**: you cannot define variable storage with the `stack`, `code`, or `log`.

### Solidity Loops 
**For Loops** lopping in solidity is quite similar to other languages. Looping through an array or a list in solidity uses the `for` keyword in the following the format:
```solidity
for (<starting index>; <ending index>; <step amount>) {
// code to execute on the index
}
```
```solidity
uint256 finalIndex = 10
for (uint256 firstIndex = 0; firstIndex < finalIndex; firstIndex++) {
// code to execute on the index
}
```
The `for` loop above starts a loop from the value of `firstIndex` (0) and runs any code in the execution space `{}` as long as the `firstIndex` (0) is less than the value of  `finalIndex` (10), and increases the value of `firstIndex`, till it is no longer less than the `finalIndex` (10).

**Require** `require`: the require keyword in solidity work similarly to if-else stataments in other languages, using the format:
```solidity
bool isOldEnough = true;
require(<if statment>, <else-statement>)
```
the `require` keyword creates an if-else-like scenario, where if the first expression before the comma does not hold true, the statement after the comma is returned.
```solidity
bool isOldEnough = true;
require(isOldEnough, "Sorry! you're not old enough.");
```
In the `require` statement above since the variable `isOldEnough` equals true, the statement after the comma will not be returned.

In other words the sentence "Sorry! you're not old enough." will only be returned if the expression before the comma holds false.


## Composability and Smart Contracts Interactions

**Composability**
When working with a large-scale project that requires using more than one contract or ledger for transactions. In solidity, contracts can interact with other contracts, the same way you can import modules in javascript or python, etc. the process is called `Composability`. 

You can either decide to write a multi-contract file, with more than one contract on one page.
```solidity
pragma solidity ^0.8.0;

ledger SimpleCurrencyConversion{
// contract about currency conversion
}

contract TransactionHistory {
// contract about transaction history
}

contract usersDetails {
TransactionHistory public transactions;

function createNewTransactionHistory() public {
        transactions = new TranactionHistory();
}
```
In the contract file above, the `userDetails` contact is deploying a new `TransactionHistory` contract.

Here, the 3 contracts above can be composed together by calling functions from one contract into the other. 

This means that a simple solidity file can hold more than one contract. 

Another more flexible way to interact with other contracts, without having too many lines of code, which is not good practice is using the `import` keyword.
Similarly to other languages, you can import other contracts from different files using the format: 
```solidity
import <solidity file path>
```

From the multi-contract file earlier, if each contract and ledger had its own files you can import them like this:

```solidity
pragma solidity ^0.8.0;

import "SimpleCorrencyConversion.sol";
import "TransactionHistory.sol";
contract usersDetails {
}
```
if the current contract file was the `userDetails` file, you would be able to import the other contract file like in the code above.

**Smart Contract Interaction** 
In order to be able to make interactions with other contracts, like calling functions and variables defined in other contracts files. To make this interaction, you'll need to get the contracts -Application Binary Interface- `ABI` and the contract's  `address`, where the contract is deployed to.

**Note**: 
Although they are usually added automatically after importing the outer function above the bae contract.
The ABI of the contracts defines how the base contract can interact with the other outer contracts, they contain information like the outer contract's byte code, the functions, and the variable declared in the contract. 

## inheritance & Overrides
When interacting with functions and variables in other contracts, solidity also supports inheritance, which means you can modify the use of a function from a child contract created in the parent contract.



Parent Contract:
```solidity
pragma solidity ^0.8.0;


contract TransactionHistory{
uint256 usersAge = 20

function store (uint _addedAge) public virtual{
    usersAge  =  _addedAge; 
    } 
}
```
In the parent contract, the store function simply changes the value of the variable userAge.

The `virtual` keyword tells solidity that the `store` function can be modified in any child contract

Child Contract:
```solidity
pragma solidity ^0.8.0;
import "TransactionHistory.sol"

contract UserDetails is TransactionHistory{
function store (uint256 _yearsPast) public override {
     usersAge  =  usersAge + _yearsPast; 
    }
}
```
The `is` enables the current `UserDetails` contract to inherit all the functionalities of `Transaction` contract. 

The `override` enables the function to rewrite the use of the `store` function from the parent contract.

### Sending Funds In Smart Contract

When making transactions that involve sending tokens, they require creating a function with the keyword `payable` in the format:
```solidity 
function <function name> public payable {
}
```
When using a payable function, you get access to certain global keywords that handles payments `msg`. For example, you can set a value to send as `msg.value`.
To get the address of the sender: `msg.sender`.
To transfer funds in contracts: 
```solidity
payable(msg.sender).transfer(<address>(this).<amount>);
```
the transaction above will semple be reverted if it does not go through and there was an error. 
Other ways of smart funding contracts are:
Using the `send` keyword, which will only return a boolean of true or false if the transaction was success or not.
```solidity
bool sendSuccess = payable(msg.sender).send(<address>(this).<amount>);
require(sendSuccess, "Send failed");
```
And the `call` keyword is a rather lower-level command or sending fund,  and can also be used to call any function in Ethereum. Using the `call` keyword in a format similar to the format.
```solidity
(<boolean variable>, <byte variable>) = payable(msg.sender).call{value: <address>(this).<amount>}("");
```

```solidity
(bool isSuccess, byte details) = payable(msg.sender).call{value: <address>(this).balance}("");
```

the two variable declared at the beginning of the function is returned by default when using the `call` keyword.
Therefore the bool variable is declared the store the returned boolean of <true> if successful and <false> if not.
And the byte variable also stores the information about the transaction. 

Check out other features of payable functions, how to make a payable transactions with the `.msg` keyword, and other transactions on contracts.

### Interfaces & package management
Interfaces are basically standardized deployed contracts.
In simple terms, interfaces are standardized smart contracts that can be accessed using the npm package manager.
They are means of interacting with already written contracts outside your projects.
To use an interface, all you need to do is import the contract directly from its location in the npm package manager or on Github. They usually start with the `@` sign.
An example of how interfaces are imported into a smart contract project:
```solidity
import "@chainlink/contracts/src...sol";

```
more on Interface.


### Constructors
**Constructors ** `constructor`: These are similar to the constructor functions in Javascript, using the `constructor` keyword, they are called immediately after deploying a smart contract. The simple format.
```solidity 
    constructor () {
    uint256 minimumAmount = 10;
    }
```

### Modifiers 
**Modifiers** `modifier`: Are used for functions that can be reused in other functions, they help to reduce repeatability.
the format for creating and using the `modifier`.

`modifier <name>{<code here>}`

```solidity
function transaction() public onlyOwner {
uint256 amountLimit = 100;
}


modifier onlyOwner {
  string owner = "Phensic";
  _;
}
```
The `onlyOwner` is a `modifier` function that assigns a value "Phensic" to a variable `owner`, and can be reused in any other function that has `onlyOwner` in its function declaration.
The underscore means (run any other code after the code in the modifier function), which means the value `Phensic` gets assigned first every time the modifier `onlyPower` is used before any other code.


**Immutables And Constants**
The `constant` keywords are used to create constant variables, variables you don't intend to change throughout the contact. Using the `constant` keyword in the format:
```solidity
uint256 public constant AMOUNT_LIMIT: 1000;
```
**Note**: It's always good practice to use constants where needed, and to use the uppercase for calling their variable name for clear readability.

While `immutable` is used to create constants that are only assigned once after being initialized.Using the `immutable` keyword in the format:
```solidity
address public immutable i_owner;

constructor () {
    i_owner = msg.sender;
}
```
Since the `i_owner` variable is only assigned once after being initialized, you can declare it as an immutable available, which also means it cannot be changed.

**Note**: Global and Local variables act exactly the same in solidity as in other programming languages. 
Global variables are created directly Inside the contract and are accessible anywhere inside the contract.
Local variables are created onside functions and cannot be accessed outside their declared functions.

# Conclusion

**Congratulations** on completing the solidity tutorial guide.

Whether you are a first-time developer learning about contracts or an experienced developer transitioning into the web3 space, you have a basic grasp of how solidity is used or writing smart contracts.

If you've completed this guide, you've taken a big step into transitioning into the web3 space.
Now you'll be able to understand the basic functionalities that make up a smart contract.

**Congratulations again**.