Solidity JumpStarter-Kit

Solidity JumpStarter-Kit

Solidity and Smart Contract Refresher Pack

·

12 min read

INSPIRATION

There are times where we want to look up basic solidity concepts or need some refreshers! What if we could jump-start this process?

OVERVIEW

Do you need a solidity-refresher or want your solidity-basic-muscles revitalized? This guide is intended to help beginners, developers (that seek a refresher) get familiar or acquainted with solidity syntax and smart contract in general.

SOLIDITY JUMPSTARTER-KIT

Solidity Definition

Simply put, Solidity is an object-oriented, high-level language for implementing smart contracts. It is quite similar to other object-oriented programming language like C++, Javascript, Python e.t.c. However, solidity is specifically designed to target the Ethereum Virtual Machine(EVM).

You might want to check out these links

Solidity Docs

Introduction to EVM

So if you write one of the highlighted languages, you can easily pick up solidity.

Smart Contract Definition

Smart contracts are simply programs stored on a blockchain that run when predetermined conditions are met.

Contract Declaration in Solidity

A contract in this context is a collection of code(its function) and data (it’s state) which resides at a specific address on the Ethereum blockchain.

A Simple Smart Contract

Data Types

Solidity is a statically typed language, which means that the type of each variable (state and local) needs to be specified. The following explains useful data types to store variables.

Boolean

bool: true or false

Integer

Unsigned: uint8,uint16,uint32,uint64,uint128,uint256(uint)

Signed: int8, int16, int32, int64, int128, int256(int)

As stated above, solidity can have signed (a regular int) or unsigned (uint) integers.

int: means that the integer can either be positive or negative with a negative sign.

uint (unsigned integer): can hold only positive values along with zero.

For example, uint8 ranges from 0 to 255 while an int8 can hold from -128 to 127.

Address

address: Holds a 20 byte value (size of an Ethereum address).

address payable : Same as address, but includes additional members transfer and send

Methods:

balance

  • .balance : balance of the Address in Wei

transfer and send

  • .transfer(uint256 amount): send given amount of Wei to Address, throws on failure.

  • .send(uint256 amount) returns (bool): send given amount of Wei to Address, returns false on failure.

Note: Using .send or .transfer has a gas limit of 2300 gas

Mappings

Mappings uses the syntax mapping(KeyType => ValueType) with its variable name in front.

Example Mapping(address => uint) addressToBalance

Note: The KeyType can be any built-in value type, bytes, string, or any contract or enum type. Other user-defined or complex types, such as mappings, structs or array types are not allowed. ValueType can be any type, including mappings, arrays and structs.

Struct

We can define new types using structs as provided by Solidity.

  struct Funder {
    address addr;
    uint amount;
}

Funder funders;

Arrays

Arrays can be of fixed size, or they can have a dynamic size.

uint[] dynamicSizeArray;

uint[7] fixedSizeArray;

Array members

push: appends an item to an array, i.e will increase the array length by 1.

pop: removes the last element from an array i.e will decrease the array length by 1

length: is used to check the number of elements present in an array.

Data Locations - Storage, Memory and Calldata

Each variable declared and used in a contract has a data location. It specifies where the value of that variable should be stored.

Storage: A storage variable is stored in the state of a smart contract and is persistent between function calls. It is the permanent residence of data which makes it accessible by all functions within a contract.

Memory: The memory location stores data temporarily and is cheaper than the storage location. It is only accessible within the function in which it was declared. It is important to note that once the function gets executed, its values are discarded.

Calldata: Calldata is a non-persistent data location where all the passing values to the function are stored. However, unlike Storage and Memory that hold mutable data, Calldata is a non-modifiable storage location.. Also, Calldata is the default location of parameters (not return parameters) of external functions.

Function

Function are notated as follows:

function () {internal|external} [pure|view|payable] [returns ()].

Input Parameters: are declared just like variables.

 function add(uint _x, uint _y) {}

Output Parameters: are declared after the return keyword

function add(uint _x, uint _y) returns (uint _sum) {
  _sum = _x + _y;
}

Note: In contrast to the parameter types, the return types cannot be empty - if the function does not return anything, the returns () keyword need not be included in the function declaration.

Control Structure

Most of the control structures known from object-oriented programming languages are available in Solidity: The following are available in solidity:

  • if else

  • while

  • do

  • for

  • break

  • continue

  • return

  • Tenary operator( ? : )

Modifiers: Custom and Access Modifiers

Modifiers automatically check if certain pre-conditions have been met and restrict access of variables or functions to parties that satisfy the conditions

Custom Modifier

As well as built-in Access Modifiers, you can also create your own.

modifier onlyOwner {
    require(msg.sender == owner);
    _;
}

Access modifiers

  • public - can be accessed from this contract, inherited contracts and externally

  • private -can only be accessed from this contract

  • internal -can be accessed only from this contract and contracts inheriting from it

  • external - Cannot be accessed internally, only externally.

Interface

An interface is the description of all functions that an object must have in order for it to operate. It includes function signatures without the implementation of the function definition.

The following are the characteristics of an interface:

  • An interface can be created with the “interface” keyword.

  • All interface functions are implicitly virtual.

  • To easily identify an interface, it’s naming can start with an “I” e.g IERC20

  • Cannot have any functions implemented.

  • Cannot inherit other contracts or interfaces.

  • Cannot define constructor.

  • Cannot declare state variables

  • An interface function can be overridden.

  • Visibility of functions of an interface can be only of type external

Example

Inheritance

Inheritance is a way to extend functionality of a contract. Solidity supports both single as well as multiple inheritance.

Example

Multiple inheritance

Abstract Contract

Abstract Contract is one which contains at least one function without any implementation i.e in abstract contracts, at least one function lacks implementation. This type of contract cannot be compiled, but they can be used as base contracts.

Example

Events

Events allow the convenient usage of the EVM logging facilities. An event is emitted, and its arguments passed in transaction logs. Up to three parameters can receive the attribute indexed, which will cause the respective arguments to be searched for. All non-indexed arguments will be stored in the data part of the log.

Example

Libraries and Using-For

Libraries are similar to Contracts but are mainly intended for reuse. A Library contains functions which other contracts can call.

Characteristics of a Solidity Library

  • Library can not be destroyed as it is assumed to be stateless.

  • A Library cannot have state variables.

  • A Library cannot inherit any element.

  • A Library cannot be inherited.

Example

Using-For

using this for that; can be used to attach library functions to any type.

Example

Error Handling and Custom Errors

in Solidity, the assert(), require() and revert() functions are used to check for conditions. In cases when conditions are not met, they throw exceptions.

  • require(bool condition, string memory message): is used to validate inputs and conditions before execution.

  • assert(bool condition): is used to check for code that should never be false. Failing assertion probably means that there is a bug.

  • *** revert(): *** is used abort execution and revert state changes.

Example

Custom Errors

Starting from Solidity v0.8.4 , there is now an additional way to revert a transaction. With Custom Errors we can now revert transactions in a convenient and gas-efficient way and tell our users why a transaction failed. They are simply defined using the error statement. Also have similar syntax as events do.

Example

Global Variables and functions

Global variables are special variables that are globally available and provide information about the blockchain.

  • block.blockhash(uint blockNumber) returns (bytes32): hash of the given block - only works for the 256 most recent blocks excluding current

  • block.coinbase (address): current block miner’s address

  • block.difficulty (uint): current block difficulty

  • block.gaslimit (uint): current block gaslimit

  • block.number (uint): current block number

  • block.timestamp (uint): current block timestamp as seconds since unix epoch

  • msg.data (bytes): complete calldata

  • msg.gas (uint): remaining gas

  • msg.sender (address): sender of the message (current call)

  • msg.sig (bytes4): first four bytes of the calldata (i.e. function identifier)

  • **msg.value **(uint): number of wei sent with the message

  • tx.gasprice (uint): gas price of the transaction

  • tx.origin (address): sender of the transaction (full call chain)

  • addmod(uint x, uint y, uint k) returns (uint): compute (x + y) % k where the addition is performed with arbitrary precision and does not wrap around at 2**256.

  • mulmod(uint x, uint y, uint k) returns (uint): compute (x * y) % k where the multiplication is performed with arbitrary precision and does not wrap around at 2**256.

  • keccak256(...) returns (bytes32): compute the Ethereum-SHA-3 (Keccak-256) hash of the (tightly packed) arguments

  • sha256(...) returns (bytes32): compute the SHA-256 hash of the (tightly packed) arguments

  • sha3(...) returns (bytes32): alias to keccak256

  • ripemd160(...) returns (bytes20): compute RIPEMD-160 hash of the (tightly packed) arguments

  • ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address): recover the address associated with the public key from elliptic curve signature or return zero on error (example usage).

  • **this **(current contract’s type): the current contract, explicitly convertible to Address

  • selfdestruct(address recipient): destroy the current contract, sending its funds to the given Address.

Ether Units

1 wei == 1

1 gwei == 1e9

1 szabo == 1e12

1 finney == 1e15

1 ether == 1e18

Other Important Keywords

Virtual: A function marked as virtual allows a derived/inheriting contract to override its function behavior. This is suitable when you want to allow another contract that is inheriting from the current contract to override its functionality.

Override: A function that overrides a base function is marked as override. This occurs when you want to change the functionality of an inherited/derived contract function.

Example

Variable packing:

Whenever we declare a variable in our solidity code, the EVM stores it in a storage slot of 32 bytes (256 bits), which means there is a slot where the variable declared is stored. Simply put, whenever we declare a uint256 variable type, we have successfully filled a slot

Variable packing is literally checking the size of data types declared and fitting them sequentially. This is what is done under the hood by the EVM. In order to do this, we need to understand the size of each data type.

Uint256 is 32 bytes Uint128 is 16bytes Uint64 is 8bytes Address and address payable is 20bytes Bool is 1byte String is 1byte per character

This approach is pretty much cool for gas optimisation.

Example

Immutable: Immutable state variables can be declared using the immutable keyword. State variable declared as immutable can only be assigned during contract creation, but will remain constant throughout the life-time of a deployed contract.

uint256 immutable maxSupply = 6464;

new: The new keyword in Solidity deploys and creates a new contract instance.

Example

Constructor: Constructor is a special function declared using constructor keyword. This function is used to initialise state variables of a contract. Following are the key characteristics of a constructor.

  • A contract can have only one constructor.

  • A constructor executed during contract deployment and it is used to initialise contract’s state.

Example:

contract Sample {
   uint num;
   constructor(uint _num) {
      data = _num;   
   }
}

Receive function: A contract can now have only one receive function that is declared with the syntax receive() external payable {…} (without the function keyword).

It executes on calls to the contract with no data (calldata), such as calls made via send() or transfer().

contract ReceiveSample {
    event emitReceive(uint);

  receive() external payable {
        emit emitReceive(msg.value);
    }
}

Fallback function: fallback function does not take any arguments and does not return anything.

Characteristics

Fallback function;

  • is triggered if function that does not exist is called.

  • is triggered if Ether is sent directly to a contract but receive() does not exist or msg.data is not empty.

  • can only be defined once per contract.

  • must be marked as external.

  • has a 2300 gas limit when called by transfer or send.

// SPDX-License-Identifier: Unlicensed
pragma solidity ^0.8.0;

contract Fallback {
    event emitFallBack(uint, gasLeft);

    fallback() external payable {
        emit emitFallBack(msg.value, gasleft());
    }
}

View functions: The mutability of functions can be declared as view if they do not contain any code/logic that potentially modifies the state, but can read from them.

function sub(uint a) public view returns (uint) {
    return a - b; //  where b is a storage variable
}

Pure functions: Functions can be declared pure if they neither read from nor modify the state

function mul(uint a, uint b) public pure returns (uint) {
    return a * b; //  where b is a storage variable
}

DEVELPER'S TOOL KITS AND IDE’s

Solidity: Most dominant Ethereum smart contracting language

Foundry: Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.

Hardhat: Hardhat is an Ethereum development environment. Compile your contracts and run them on a development network. Get Solidity stack traces, console.log and more.

Truffle: A world class development environment, testing framework and asset pipeline for blockchains using the Ethereum Virtual Machine (EVM), aiming to make life as a developer easier.

Ethers js: The ethers.js library aims to be a complete and compact library for interacting with the Ethereum Blockchain and its ecosystem.

Web3 js: web3.js is a collection of libraries that allow you to interact with a local or remote ethereum node using HTTP, IPC or WebSocket

ApeWorx: The Ethereum application development framework for Python Developers, Data Scientists, and Security Professionals.

Metamask: The leading crypto wallet available on browser extension and mobile. Trusted by over 30 million users to buy, store, send and swap crypto securely.

Etherscan: Etherscan is a Block Explorer and Analytics Platform for Ethereum, a decentralized smart contracts platform.

Openzeppelin: OpenZeppelin provides security products to build, automate, and operate decentralized applications.

Brownie: Brownie is a Python-based development and testing framework for smart contracts targeting the Ethereum Virtual Machine.

Ethereum Stack Exchange: Post and search questions to help your development life cycle.

Biconomy: Do gasless transactions in your dapp by enabling meta-transactions using simple to use SDK.

Radicle: Radicle is a new kind of code collab network built on Git. Radicle is a peer-to-peer stack for building software together.

IPFS: A peer-to-peer hypermedia protocol designed to preserve and grow humanity's knowledge by making the web upgradeable, resilient, and more open.

Arweave: Permanent decentralized data storage.

Moralis: Moralis provides a single workflow for building high performance dapps. Fully compatible with your favorite web3 tools and services.

Ankr: Access all the developer tools you need with remote node access, advanced APIs, and the largest multi-chain network of RPCs. Build with fast, reliable infrastructure.

Spheron: Decentralized web hosting which supports storage on Arweave, Skynet, IPFS & Filecoin.

Remix: Remix is a web IDE that allows developing, deploying and administering smart contracts for Ethereum like blockchains. It can also be used as a learning platform.

EthFiddle: This browser-based Solidity IDE lets you compile test code, compiles the smart contract with helpful error handling, and lets you share the fiddles with friends and coworkers effortlessly.

Vs Code: Visual Studio Code extension that adds support for Solidity

IntelliJ: Open-source plug-in for Jetbrains IntelliJ Idea IDE(free/commercial) with syntax highlighting, formatting, code completion etc.

CONCLUSION

This sole aim of this guide is to help beginners, developers (that seek a refresher) get familiar or acquainted with solidity syntax and smart contract in general. I hope it does that!!.

Thanks to all that have taken their time to review this content. WAGMI 🚀 🚀

For the love of the community, all forms of contribution are welcomed. You can find the Github Repo here 👇