Introduction

Learning a new programming language comes with some challenges which may include: deciding whether the programming language is worth learning in the first place; time allocation; and hardest of all, persistence in the face of other responsibilities. It's a fact that learning by building a project of interest can be the best motivation to keep the learning going, even when other things need to be attended to.

Hi! This is the first article in a series where we shall be learning Solidity in Easy Steps. We will create a contract for two business partners that don't trust each other 🤣🤣. The first doesn't trust the second to deliver his task or goods after payment, while the second doesn't trust the first to pay after fulfilling his part of the deal... 😳😳Sounds familiar?

Thus, we suggest an Escrow contract.

Expectations

In this article, we will build an escrow smart contract using Solidity with dummy explanation for each line of code. Readers are advised to manually type in the codes provided. Before we get the ball rolling, lets take a look at what is expected of you so that we can be on the same page.

Assumption: You have a basic understanding of Solidity and programming in general.

Difficulty: 1/10 (Beginner)

Programming Time: 5 min.

By the end of this article, readers should understand:

Features to be Implemented

We will have to climb the ladder of features in a stepwise fashion, in this version:

Class Diagram

When analyzing or coding an application, professionals start off with a design (such as class diagram). Though not necessary at this stage, it's good to be accustomed to good practices, hence we are going to come up with a minimalistic class diagram just for conceptualization.

What the hell is a class diagram??? Simply put, a class diagram is a graphical representation of a system. An up-to-date class diagram allows anyone including your future self to gain insight into the entire contract. Typically, a contract class diagram lists the variables, functions, and events in a contract.

The variables

In this version we will need two variables, which are:

The Functions

We will need the following functions for this version:

Development Setup

You don’t need to download anything... What???? That’s strange for a programming session...

In this session, we will be making use of a web-based Solidity development platform called Remix. It can be used freely by accessing https://remix.ethereum.org/. You can learn more about this amazing platform by reading its documentation.

Now, to set up our development environment:

Coding and Explanation

Next the full code for this version is given followed by a detailed line based explanation. While explaining the code lines we will touch on different aspects of Solidity so read on!!! Type the lines below into the Escrow.sol file created above , explanation follows.

This code can be forked in this github gist.

// SPDX-License-Identifier: MIT

pragma solidity >=0.7.0 <0.9.0;

/**
 * @title EscrowSol
 * @dev Manages fund transfers between two parties
 */
contract EscrowSol {
    // Wallet address of the payer
    address public funder;
    // Wallet address of the intended beneficiary
    address public beneficiary;

    /// Lockup a certain crypto value.
    /// @param counterpart the address of the intended beneficiary
    /// @dev lockup crypto for the counterpart
    function fund(address counterpart) public payable {
        beneficiary = counterpart;
        funder = msg.sender;
    }

    /// Release all locked funds.
    /// @dev The deal is done, let only the payer release fund.
    function release() public payable {
        if (msg.sender==funder){
            // Transfer all the funds to the beneficiary
            payable(beneficiary).transfer(address(this).balance);
        }
    }

    /// Return the locked value.
    /// @dev anyone should be able to see the actually locked crpto value .
    /// @return the crypto value
    function getBalance() public view returns (uint) {
        return address(this).balance;
    }
}

Line 1

// SPDX-License-Identifier: MIT

An informative line to signify the license type of the entire code contained within the specific file.

Line 3

pragma solidity >=0.7.0 <0.9.0;

Hey solidity, run this file using any of your versions ranging from 0.7.0 up till 0.9.0. Note that, unlike line 1, this line ends with a semicolon.

In Solidity, all lines that don’t end with brackets, braces or parentheses must end with a semicolon.

Line 5-8

/**
 * @title EscrowSol
 * @dev Manages fund transfers between two parties
 */

Bunch of special type of comments called NatSpec (Natural Specifications). They are useful for automatically generating user documentation. How are NatSpecs different from ordinary multiline comments??? Jargons aside, its sufficient to know that generally, comments can serve three purposes:

Back to code explanation, here we declare the title with @title and a one-line contract description with @dev

Line 9

contract EscrowSol { //} Closed on line 38 

We signify the beginning of our contract named EscrowSol and everything within the parentheses on this line and its closing counterpart will be regarded by Solidity as part of this contract. Why signify the beginning of a contract, after all, solidity is for writing contracts? Well, more than one contract can be placed within a file, hence all elements that belong to a contract, if not imported, must be encapsulated within the parentheses of the contract.

Line 11

    // Wallet address of the payer
    address public funder;

We need to know the funder and since we want anyone to access the funder's address, thus we added a public Solidity keyword to achieve that.

Whenever a variable is assigned public, an automatic getter function is defined by Solidity which makes it possible for the world to see the current value of the variable. Thus, saving us some keystrokes of cooking up a getter function.

Line 13

    // Wallet address of the intended beneficiary
    address public beneficiary;

Same explanation as Line11 but now for the beneficiary.

Line 15-17

    /// Lockup a certain crypto value.
    /// @param counterpart the address of the intended beneficiary
    /// @dev lockup crypto for the counterpart

NatSpecs for the fund function we are about to write. Note that the previous NatSpec was enclosed within "/"and "/" while this time around we used "///" on every line.

Well, that’s a way of letting you know another way it can be achieved in Solidity. Recall that we want the funder to specify the intended beneficiary at the time of funding, thus the only parameter we need to pass on to this function. This is now explicitly stated in the NatSpec with the use of the @param which is the only new tag here.

Line 18

    function fund(address counterpart) public payable { //Closed on line 21

Generally in Solidity, a function is defined by using the function keyword, give it a name, enclose arguments (if any) and their types in a bracket, followed by decorators/modifiers (if any), and lastly followed by parentheses that encapsulate the codes to be executed when called.

Therefore on line 18, we defined a function named fund that accepts the beneficiary address as an argument named counterpart decorated with public Solidity keyword for it to be executable from anywhere and also decorated with payable for payment into the contract to be processed.

What the heck is payable??? Without going into too much details, whenever cryptos are to be transferred, the address or function (as in this case) must be made payable else actual coin transfer will never take place.

Line 19

        beneficiary = counterpart;

We set the beneficiary address to the counterpart address provided by the funder.

Line 20

        funder = msg.sender;
) // End of fund function

We set the address of the funder with msg.sender Hope you are not asking what is msg?

When a contract is invoked, Solidity by default passes some global variables, including msg, that possess properties that can be used to offer information about the blockchain. msg gives information such as the public address that invoked the present operation (msg.address), the amount that is sent (msg.value) and the remaining cost of running the blockchain operation (msg.gas).

Line 25

    function release() public payable {

We put in place a payable function named release.

Line 26-29

        if (msg.sender==funder){
            // Transfer all the funds to the beneficiary
           payable(beneficiary).transfer(address(this).balance);
        }
    } // End of release function

We ensure that the person calling this function is the funder after which we transfer all the funds locked-up in the smart contract to the beneficiary

Line 35-37

    function getBalance() public view returns (uint) {
        return address(this).balance;
    }
} // End of the contract

We now create a function named getBalance to enable us to retrieve the value of funds in our contract. In the process we introduce two new keywords (view and this).

view keyword is used to signify that a function shouldn't be allowed to make any change to the state of a contract on the blockchain though we still want to be able to read the state of the contract. If we don't also need to read any state properties, we could use pure keyword instead.

Here, we accessed the balance of the contract through the this keyword.

this keyword points to the currently running contract and stuff that can be reached through it. In our case, we are simply concerned about its balance property.

Yey!!!! Its time to set our contract into action. Save it if you haven’t already.

Running our Escrow Contract

Remix is equipped with JavaScript VM that simulates blockchain which makes it easy to test smartcontracts on the go within a browser. See the gif below, we first have to compile (this is mostly done automatically unless an error has been encountered) and then deploy our smart contract.

Note that after deploying, we click on contract name below to reveal the eternally accessible variables and functions of the contract. Also notice that some buttons are colored blue while some are colored red.

In Remix, payable functions (functions that are capable of transfer a values between account) are colored red. view or pure functions (functions that do not cause any change in state of the contract but return a value stored in the contract) are colored blue.

By default, Remix JavaScript VM gives some addresses and fake ethers to run our contract. In this case, we will assume the second account to be the funder, while the third account to be the beneficiary.

That said, let’s perform some operations after which you can play around with the contract as you deem fit. A gif illustration is displayed below followed by the list of the steps that were taken to run the contract.

Well done!!!! You've developed the first version of a blockchain smart contract in Solidity.

Areas for Further Improvement

Let's now take a look at some room for further development which we will explore in the next article of this series.

These amongst other issues will be tackled in the next post of this series.

Let me go cook it up!!!

Also read here.