Solidity for Beginners : Writing your first Smart Contract

So if you have been following this series, you already got the Solidity basics down.

It's time for you to become a Solidity Developer.
Writing your first Smart Contract and earning tons of dollars!
penguin printing dollars

Just kidding, it will take some time from here too.
But first,

What is a Smart Contract?

🚨Spoiler Alert : They are not really Smart, and they are literally not Contracts.

Smart contracts are basically programs written in a programming language and stored on a Computer Node(Blocks) that execute automatically(hence the word Smart).

But wait, don't all programs execute automatically? Yes, they do.

How do we write a Smart Contract?

There are steps for doing anything. So we'll follow a simple set of steps.

Step 1 : Building Trust

Blockchain is essentially a set of interactions, each costing a fees(cryptocurrency).
Do you give your money to anyone? (PS : If you do, I would love to have a cup of coffee from you πŸ˜‰ ).
talking dollar bill
No, you need to trust that person first. Also, you'll have to prevent people from copying your code and using it to deceive others.

Well, that's why need to include a license specifier at the top.
You can use any open source licensing like : MIT, Apache, GNU, etc or UNLICENSED if you want to prevent people from copying your code.

Also, you need to specify the version of Solidity you are using.
For this we use the pragma directive.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
Enter fullscreen mode Exit fullscreen mode

Step 2 : Building blocks

Now that we have the trust, we start writing our Contract.
Today, we will try to build a Smart Contract that helps us book a Hotel Room.

contract HotelRoom {
//code goes here
}
Enter fullscreen mode Exit fullscreen mode

Let's see what does a Hotel Room have?

  • Occupancy : A hotel room should either be Vacant or Occupied. So we will use an enum to check if the room is occupied or empty.
  • Cost : You cannot rent a room to someone without charging them some money right? Here, we will take 2 Ether for each room.
  • Owner : Where will all the moneyπŸ’Έ go? To you - that is the account that is hosting this contract.

So, now the contract will look like this :

contract HotelRoom {
    enum Status {
        Vacant, 
        Occupied
    }

    address payable public owner;
    Status public currentStatus;

    constructor(){
        owner = payable(msg.sender);
        currentStatus = Status.Vacant;
    }
}
Enter fullscreen mode Exit fullscreen mode

We see there is a constructor function. If you are familiar to programming you know that constructors are used for initializing data.

Similarly, we are assigning the owner as the account address that is hosting the smart contract.

Note : msg is a global variable that is like the this variable in other languages. It has various properties that refer to the calling object. Constructors in smart contracts are 🚨ONLY🚨 called during deployment. So, msg.sender is the account hosting the smart contract.

Step 3 : Adding functionality

Now that we are ready with the basic setup, we will dive into the actual functionalities.

There is only 1 thing to do : Book the hotel. 🌟
But the process is not simple.

Remember, we can book the room only if 2 conditions are met πŸ‘‡:

  • Room is empty
  • The person sends enough Ether to book the room.

We will check these conditions using modifiers.

Modifiers are conditions that are checked before running a function.

Let's create our 2 modifiers for the above conditions.

   //check if room is empty
    modifier onlyWhileVacant(){
        require(currentStatus == Status.Vacant, "Room Already Booked");
        _;
    }

    //check if ethers sent are enough
    modifier costs(uint _amount){
        require(msg.value >= _amount, "Not Enough Ether");
        _;
    }
Enter fullscreen mode Exit fullscreen mode

require is a special function that checks if the first argument is true and returns the second(optional) argument if false.

But there are useless without a function to book the room, right?
mr. bean with eye roll

The function is also simple :

   function book() payable public onlyWhileVacant costs(2 ether){

        currentStatus = Status.Occupied;

        (bool sent, bytes memory data) = owner.call{value : msg.value}("");
        require(true);

        emit Occupy(msg.sender, msg.value);
    }
Enter fullscreen mode Exit fullscreen mode

You can see the modifiers being called in the first line itself.
But wait there is something new : payable and emit.

βœ…Payable is a keyword that specifies that a function or an address accepts payments.
Here, that will be 2 ethers.

But, what is emit.

Step 4 : Finishing touches

We are almost there. Just a last thing.
Yes, the room is booked. But, the smart contract knows it.
What about the blockchain?

Well, for that we have events.

An Event is a member of a smart contract that applications can subscribe and listen to. These are logged and stored into the blockchain for as long as the blockchain exists.

So, for a room to be booked, we need to make a log for that. This makes it a public record that the room was booked by the account for those many ethers.πŸ“

The event would be :

event Occupy(address _occupant, uint _value);
Enter fullscreen mode Exit fullscreen mode

And this event is emitted by the booking function.

There, you have created your first contract.
steve carrell clapping
Head over to the Remix IDE and test it out.

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


contract HotelRoom{
    enum Status {
        Vacant, 
        Occupied
    }

    address payable public owner;
    Status public currentStatus;

    constructor(){
        owner = payable(msg.sender);
        currentStatus = Status.Vacant;
    }

    event Occupy(address _occupant, uint _value);

    modifier onlyWhileVacant(){
        require(currentStatus == Status.Vacant, "Room Already Booked");
        _;
    }

    modifier costs(uint _amount){
        require(msg.value >= _amount, "Not Enough Ether");
        _;
    }

    function book() payable public onlyWhileVacant costs(2 ether){

        currentStatus = Status.Occupied;

        (bool sent, bytes memory data) = owner.call{value : msg.value}("");
        require(true);

        emit Occupy(msg.sender, msg.value);
    }
}
Enter fullscreen mode Exit fullscreen mode

Do comment and let me know if you want a series on a Web3 project development using React and Solidity. See you in the next one.πŸ‘‹

Till then follow me on πŸ•πŸ• Twitter and Github