[Part 1] Day 2 of #30DaysOfWeb3 : Lets solidify Solidity

Lets start understanding solidity and build a cool smart contract with it.

We will be building a cool shopping store with solidity in this blog.

Solidity is used to write smart contracts for EVM based blockchains. Its a statically typed language. Its syntax is very similar to Javascript and C.

Basic Syntax

First we have to specify the license and then the Solidity version we want to use using pragma keyword. After that name the contract. All code goes inside the contract scope block.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;
contract Store {
}

Data Types

Solidity provides below data types :

TypeDescription
boolcan store either true or false. Its default value is false.
uintUnsigned integers can be positive or zero and range from 8 bits to 256 bits. Its default value is 0.
intIntegers can be positive, negative, or zero and range from 8 bits to 256 bits. Its default value is 0
addressuse to store ethereum addresses which holds 20 byte value. Its default value is 0x0000000000000000000000000000000000000000
stringseries of characters/symbol/digits enclosed using quotes.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;

contract LearnPrimitiveTypes {
    string public greet = "Hello World!";
    bool public boo = true;

    /* 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

    /* Like uint, different ranges are available from int8 to int256 */
    int8 public i8 = -1;
    int public i = -123; // int is same as int256

    address public addr = 0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c;
}

Variables

Solidity supports 3 types of variables :

Variable TypeDescription
State VariablesState Variables are stored in the contract storage i.e on blockchain.
Local VariablesLocal Variables are stored in the memory and their values are only accessible within the function.
Global VariablesThese are special variables in global namespace used to retrieve information about the blockchain, particular addresses, contracts, and transactions.

Variables in solidity have 3 different places to store data :

  • Memory: Variables that are only available within a function and are destroyed after function execution. Local variables are stored in memory.
  • Storage: Variables of this type are permanently stored and are also called state variables. Storage is expensive on the Ethereum blockchain. 1 MB of storage will cost you many bucks.
  • Call data : Same as memory but there value cannot be modified.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;

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

    function doSomething(string memory _name, uint _num) public {
        // Local variables are not saved to the blockchain.
        uint i = 456;
        string memory greet = "Hello";

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

Lets now apply our above knowledge in building our Shopping Store.

  • We defined storeName as string to give a name to our shopping store.
  • We also defined totalItemsSold and totalSales to keep track of our store statistics.
  • We will store our shopping store's owner address into merchant variable.
  • The variable isSaleOn specifies if discounted rates are available on items or not. Only Owner can either start a sale or end the sale.
  • Variable discountPercentage will hold the discount percentage that is to be given on total bill during the sale period.

Refer Solidity documentation for other types.

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

contract Store {
    string public storeName = "My Awesome Store";
    address public merchant; 
    bool public isSaleOn = false;
    uint public discountPercentage = 10;
    uint private totalSales;
    uint private totalItemsSold;
    uint private discountsGiven;
}

Data Structures

Arrays, mappings and structs are all reference types i.e they store the address instead of value directly. Multiple reference type variables could reference the same location, and a change in one variable would affect the others.

Data StructureDescription
ArraysThere are two types of arrays, compile-time fixed-size and dynamic arrays. For fixed-size arrays, we need to declare the size of the array before it is compiled. The size of dynamic arrays can be changed after the contract has been compiled.
StructsStructs are a collection of variables that can consist of different data types. We can define custom data types in the form of structs.
MappingsMappings are a collection of key-value pairs. Mappings cannot be iterated like an array. If we don't know a key we won't be able to access its value. By Default all unknown/known key's value will be 0
EnumsEnums are custom data types consisting of a limited set of constant values. We use enums when our variables should only get assigned a value from a predefined set of values.

Structs

Operations on Structs Description
Declaring a Struct struct Item {
string name;
bool isAvailable;
}
Initializing structs Way 1 : Passing Positional parameters
Item storage myItem = Item("Gaming Mouse", true);
Way 2 : Key-value Pair Style
Item storage myItem = Item({name : "Gaming Mouse", isAvailable: true});
Way 3 : Initialize empty struct and update its members
Item storage myItem;
myItem.name = "Gaming Mouse";
myItem.isAvailable: true;
Accessing structs // Access struct member using dot operator
string myStructName = myItem.name;
Updating struct // Use the dot operator and assign it a new value
myItem.name = "RedGear Mouse";

Lets define our shopping store's structs that we will need.

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

contract Store {

// Item Struct
struct Item {
        uint itemId;
        string itemDetailsURI;  // IPFS Hash for retrieving item details
        uint price;
        uint availableQty;
    }

// Order Struct. itemId and qty are arrays which are co-related. 
// Item at index in itemId will have its quantity at same index in qty.
 struct Order {
        uint orderId;
        uint[] itemId;
        uint[] qty;
        uint grossTotal;
        uint discount;
        uint netTotal;
        uint orderCreatedTimestamp;
        Status shippingStatus;
        address placedBy;
    }

}

Arrays

Operations on Arrays Description
Declaring an Array uint[5] public fixedArr; // Fixed Size Arrays
uint[] public dynamicArr; // Dynamic Arrays
Initializing an Array uint[] public arrInit = [1, 2, 3]; // Initializing all at once

uint[3] public arrInit2; // Initializing one by one
arrInit2[0] = 1;
arrInit2[1] = 2;

// If not initialized the default value of all elements is zero
uint[5] public arrNotInit;
Add/Remove from Dynamic Array // Adds in the end and increase length by 1
arr.push(i);
// Removes last element and decrease length by 1
arr.pop();
Delete an Element // This will just make the 5th element 0 but will not remove it delete arr[4];
Get Array Length //Returns the length of array arr
uint len = arr.length;

Lets define our shopping store arrays that we will need.

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

contract Store {

 // An array of 'Order' structs
    Order[] public orders;

// An array of 'Item' structs
     Item[] public items;
}

Mappings

Operations On Mappings Description
Create Mapping // Syntax
mapping(KeyType => ValueType) <visibility> <mapname>;
The key can be any built-in value type or any contract, but not a reference type. The value type can be of any type.
mapping(uint => address) public numberToAddress;
Accessing values // Just like arrays, provide the name of the mapping and the key in brackets
// No error if we query a non-existing key. Because by default all possible key will have a value 0
uint value = numberToAddress[i];
Setting values // Mapping’s name and key in brackets and assigning it a new value
myMap[_key] = 456;
Removing values // This will just make the specified key's value to 0 but will not remove it delete myMap[_key];
Nested Mapping mapping(address => mapping(uint => string)) public nm; Declare
nm[_outerKey][_innerKey] = "Yuhuu! Solidity Rocks!! "; Assign
string value = nm[_outerKey][_innerKey] ; Access
delete nm[_outerKey][_innerKey]; Delete i.e Reset it to 0

Lets define our shopping store's mappings that we will need.

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

contract Store {

// Address as key will return all orderIds of that user as value. 
// We can then run a loop and gets all order details
  mapping(address => Order[]) private customerOrders;

mapping(address => string) private shippingAddress;
mapping(uint => string) private orderShipping;
}

Enums

Operations on enums Description
Defining enums // Enums are stored as consecutive unsigned integers starting from 0 rather than strings.
enum Status {
Created, // Element 0
Attended, // Element 1
Cancelled // Element 2
}
Initializing a enum // By Default eventStatus will be 0(Pending) if not initialized.
Status public eventStatus;
eventStatus = Status.Attended; OR eventStatus = 1;
Accessing an enum value // Simple. Name of variable will return the value
uint getStatus = eventStatus; // Returns 1
Status getStatusString = eventStatus; // Returns "Attended"
Updating an enum value eventStatus = Status.Cancelled; OR eventStatus = 2;
Removing an enum value // Deleting will set the eventStatus variable value to 0(Created)
delete eventStatus;

Lets define our shopping store's enums that we will need.

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

contract Store {

// We are using this enum in our Order struct
 enum Status {
        "Accepted",
        "Dispatched",
        "Delivered",
        "Cancelled"
    }
}

Hope you enjoyed it and found it useful.

We will covert Functions, Inheritance, Modifiers and more in Part 2. I will share the link to my github repo to view the full source code of my shopping store contract there. Stay Tuned. :)


Sources : Learn ETH by dacade.org and remix.ethereum.org